Исследование простого crackme (часть 2) / Хабр
Здравствуйте, Хабралюди!
Этот топик является продолжением цикла статей о исследовании крякмисов (часть 1). В этой статье мы рассмотрим крякмис по-сложнее, чем в предыдущей статье. Основная сложность будет заключаться в алгоритме шифровки. Однако, всё равно, многим он покажется слишком простым.
Необходимый материал
Итак приступим.
Из инструментов я буду использовать только отладчик. Вот и сам крякмис.
Пробный запуск
Итак, традиционно запустим его без отладчика, введём фейковые данные, и посмотрим на результат:
На этот раз никакого месаджбокса не было. Значит будем ставить бряк на все вызовы функции GetDlgItemTextA, так как именно она ответственна за «извлечение» данных из текстовых полей в данном случае.
Трассировка
Cтавим бряки, запускаем программу, вводим имя и серийник и жмём Verify.
Далее, вот в этом куске кода:
Идёт уже знакомая нам процедура модификации имени, при котором каждый его(имени) символ заменяется на последующий в таблице ASCII.
Основная сложность
Дальше самое интересное:
004015FF |> 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
00401602 |. 0385 14FFFFFF ADD EAX,DWORD PTR SS:[EBP-EC]
00401608 |. 83E8 70 SUB EAX,70
0040160B |. 0FBE10 MOVSX EDX,BYTE PTR DS:[EAX]
0040160E |. 8B85 10FFFFFF MOV EAX,DWORD PTR SS:[EBP-F0]
00401614 |. 31D0 XOR EAX,EDX
00401616 |. 0FBE4D EC MOVSX ECX,BYTE PTR SS:[EBP-14] //рандомное значение.
0040161A |. D3E0 SHL EAX,CL
0040161C |. 8B8D 14FFFFFF MOV ECX,DWORD PTR SS:[EBP-EC]
00401622 |. D3F8 SAR EAX,CL
00401624 |. 8985 0CFFFFFF MOV DWORD PTR SS:[EBP-F4],EAX
0040162A |. 8D85 10FFFFFF LEA EAX,DWORD PTR SS:[EBP-F0]
00401630 |. FF00 INC DWORD PTR DS:[EAX]
00401632 |. 8B85 0CFFFFFF MOV EAX,DWORD PTR SS:[EBP-F4]
00401638 |. 3385 10FFFFFF XOR EAX,DWORD PTR SS:[EBP-F0]
0040163E |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX
00401642 |. 8B85 0CFFFFFF MOV EAX,DWORD PTR SS:[EBP-F4]
00401648 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
0040164C |. 8B85 10FFFFFF MOV EAX,DWORD PTR SS:[EBP-F0]
00401652 |. 890424 MOV DWORD PTR SS:[ESP],EAX
00401655 |. E8 36FCFFFF CALL craomaxx.00401290
0040165A |. 8985 08FFFFFF MOV DWORD PTR SS:[EBP-F8],EAX
00401660 |. 8B85 0CFFFFFF MOV EAX,DWORD PTR SS:[EBP-F4]
00401666 |. 3385 10FFFFFF XOR EAX,DWORD PTR SS:[EBP-F0]
0040166C |.
894424 08 MOV DWORD PTR SS:[ESP+8],EAX
00401670 |. 8B85 0CFFFFFF MOV EAX,DWORD PTR SS:[EBP-F4]
00401676 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
0040167A |. 8B85 10FFFFFF MOV EAX,DWORD PTR SS:[EBP-F0]
00401680 |. 890424 MOV DWORD PTR SS:[ESP],EAX
00401683 |. E8 2EFCFFFF CALL craomaxx.004012B6
00401688 |. 8985 04FFFFFF MOV DWORD PTR SS:[EBP-FC],EAX
0040168E |. 8B85 04FFFFFF MOV EAX,DWORD PTR SS:[EBP-FC]
00401694 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
00401698 |. 8B85 08FFFFFF MOV EAX,DWORD PTR SS:[EBP-F8]
0040169E |. 890424 MOV DWORD PTR SS:[ESP],EAX
004016A1 |. E8 34FCFFFF CALL craomaxx.004012DA
004016A6 |. 8985 00FFFFFF MOV DWORD PTR SS:[EBP-100],EAX
004016AC |. 8B85 00FFFFFF MOV EAX,DWORD PTR SS:[EBP-100]
004016B2 |. 2385 08FFFFFF AND EAX,DWORD PTR SS:[EBP-F8]
004016B8 |. 3385 04FFFFFF XOR EAX,DWORD PTR SS:[EBP-FC]
004016BE |.
8985 FCFEFFFF MOV DWORD PTR SS:[EBP-104],EAX
004016C4 |. 8B85 00FFFFFF MOV EAX,DWORD PTR SS:[EBP-100]
004016CA |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX
004016CE |. 8B85 04FFFFFF MOV EAX,DWORD PTR SS:[EBP-FC]
004016D4 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
004016D8 |. 8B85 08FFFFFF MOV EAX,DWORD PTR SS:[EBP-F8]
004016DE |. 890424 MOV DWORD PTR SS:[ESP],EAX
004016E1 |. E8 D0FBFFFF CALL craomaxx.004012B6
004016E6 |. 8985 F8FEFFFF MOV DWORD PTR SS:[EBP-108],EAX
004016EC |. 8B85 F8FEFFFF MOV EAX,DWORD PTR SS:[EBP-108]
004016F2 |. 894424 0C MOV DWORD PTR SS:[ESP+C],EAX
004016F6 |. 8B85 FCFEFFFF MOV EAX,DWORD PTR SS:[EBP-104]
004016FC |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX
00401700 |. 8B85 04FFFFFF MOV EAX,DWORD PTR SS:[EBP-FC]
00401706 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX
0040170A |. 8B85 08FFFFFF MOV EAX,DWORD PTR SS:[EBP-F8]
00401710 |.
890424 MOV DWORD PTR SS:[ESP],EAX
00401713 |. E8 DCFBFFFF CALL craomaxx.004012F4
00401718 |. 8985 F4FEFFFF MOV DWORD PTR SS:[EBP-10C],EAX
0040171E |. 8B85 10FFFFFF MOV EAX,DWORD PTR SS:[EBP-F0]
00401724 |. 890424 MOV DWORD PTR SS:[ESP],EAX
00401727 |. E8 F8FBFFFF CALL craomaxx.00401324
0040172C |. 8985 10FFFFFF MOV DWORD PTR SS:[EBP-F0],EAX
00401732 |. 8B85 0CFFFFFF MOV EAX,DWORD PTR SS:[EBP-F4]
00401738 |. 890424 MOV DWORD PTR SS:[ESP],EAX
0040173B |. E8 E4FBFFFF CALL craomaxx.00401324
00401740 |. 8985 0CFFFFFF MOV DWORD PTR SS:[EBP-F4],EAX
00401746 |. 8B85 08FFFFFF MOV EAX,DWORD PTR SS:[EBP-F8]
0040174C |. 890424 MOV DWORD PTR SS:[ESP],EAX
0040174F |. E8 D0FBFFFF CALL craomaxx.00401324
00401754 |. 8985 08FFFFFF MOV DWORD PTR SS:[EBP-F8],EAX
0040175A |. 8B85 04FFFFFF MOV EAX,DWORD PTR SS:[EBP-FC]
00401760 |. 890424 MOV DWORD PTR SS:[ESP],EAX
00401763 |.
E8 BCFBFFFF CALL craomaxx.00401324
00401768 |. 8985 04FFFFFF MOV DWORD PTR SS:[EBP-FC],EAX
0040176E |. 8B85 00FFFFFF MOV EAX,DWORD PTR SS:[EBP-100]
00401774 |. 890424 MOV DWORD PTR SS:[ESP],EAX
00401777 |. E8 A8FBFFFF CALL craomaxx.00401324
0040177C |. 8985 00FFFFFF MOV DWORD PTR SS:[EBP-100],EAX
00401782 |. 8B85 F4FEFFFF MOV EAX,DWORD PTR SS:[EBP-10C]
00401788 |. 890424 MOV DWORD PTR SS:[ESP],EAX
0040178B |. E8 94FBFFFF CALL craomaxx.00401324
00401790 |. 8985 F4FEFFFF MOV DWORD PTR SS:[EBP-10C],EAX ; |
00401796 |. 8B85 F4FEFFFF MOV EAX,DWORD PTR SS:[EBP-10C] ; |
0040179C |. 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX ; |
004017A0 |. 8B85 00FFFFFF MOV EAX,DWORD PTR SS:[EBP-100] ; |
004017A6 |. 894424 18 MOV DWORD PTR SS:[ESP+18],EAX ; |
004017AA |. 8B85 04FFFFFF MOV EAX,DWORD PTR SS:[EBP-FC] ; |
004017B0 |. 894424 14 MOV DWORD PTR SS:[ESP+14],EAX ; |
004017B4 |.
8B85 08FFFFFF MOV EAX,DWORD PTR SS:[EBP-F8] ; |
004017BA |. 894424 10 MOV DWORD PTR SS:[ESP+10],EAX ; |
004017BE |. 8B85 0CFFFFFF MOV EAX,DWORD PTR SS:[EBP-F4] ; |
004017C4 |. 894424 0C MOV DWORD PTR SS:[ESP+C],EAX ; |
004017C8 |. 8B85 10FFFFFF MOV EAX,DWORD PTR SS:[EBP-F0] ; |
004017CE |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX ; |
004017D2 |. C74424 04 7840>MOV DWORD PTR SS:[ESP+4],craomaxx.004040>; |ASCII "C%dr%do%dm%da%dx%dX"
004017DA |. 8D85 18FFFFFF LEA EAX,DWORD PTR SS:[EBP-E8] ; |
004017E0 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
004017E3 |. E8 C8070000 CALL <JMP.&msvcrt.sprintf> ; \sprintf
004017E8 |. C785 14FFFFFF >MOV DWORD PTR SS:[EBP-EC],0
004017F2 |> 8D85 18FFFFFF /LEA EAX,DWORD PTR SS:[EBP-E8] ; |
004017F8 |. 890424 |MOV DWORD PTR SS:[ESP],EAX ; |
004017FB |. E8 D0070000 |CALL <JMP.&msvcrt.strlen> ; \strlen
00401800 |.
EB C0 \JMP SHORT craomaxx.004017F2
00401832 |> 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00401835 |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX
Тут происходит создание восьми последовательностей, состоящих из цифр. Далее, шесть из них, посредством функции sprintf с аргументом C%dr%do%dm%da%dx%dX, образуют такую строку (п — последовательность) —
Cп1rп2oп3mп4aп5xп6X.
Потом идёт процедура, которая заменяет каждый символ этой огромной строки на симвот следующий за следующим В таблице ASCII(извините но не знаю как это по — другому объяснить). Например был символ A стал С, был 1 стал 3, и так далее. И в итоге получается готовый, валидный серийник.
Сложность в том, что эти строки образуются почти рандомно. То есть тут мы видим не традиционную модификацию имени, а скорее модификацию адресов, содержащихся в регистрах и стеке. Адреса меняются в зависимости от длины имени, поэтому имена с одинаковой длиной имели бы одинаковые серийники если бы не некоторое рандомное значение принцип образования которого я не могу понять(оно прокомментировано).
Примеры
Пример имени — Myname
Пример серийника — E99696;:2t5284;342q87;:6458o696924:c3995:68326z432575;:22Z
Пример имени2 — name
Пример серийника2 — E73872238t9:5274:q;5257262o;2752558c3:72987622z3:575886::Z
Примеры могут у вас не работать, как раз из за рандомного значения.
Вот такой вот пример нерешабельного кейгенми.
P.S. Следующая статья будет интереснее. Раскажу о ручной распаковке, и о более сложных алгоритмах шифровки.
Описание типов данных в Ассемблере Intel
Для описания типов данных используются директивы резервирования и инициализации памяти:
DB – 1 байт – 8 бит,
DW – 2 байта – 16 бит,
DD – 4 байта – 32 бита,
DQ – 8 байт – 64 бита,
DT – 10 байт – 80 бит.
Примечание. Дополнительными директивами являются директивы, описывающие данные длиной 6 байт (для дальнего указателя – 2 байта селектор и 4 байта смещение):
DF – 6 байт – 48 бит,
DP – 6 байт – 48 бит,
Примеры:
The_byte DB 5 ; 0 … 255 (28-1)
The_word DW 3000 ; 0 … 65 535 (216-1)
The_dword DD 12345678 ; 0 … 4 294 967 295 (232-1)
The_qword DQ 1122334455667788 ; 0 … (264-1)
The_ptr DP 112233445566 ; 0 … (248-1)
При резервировании
памяти можно задавать различное
количество элементов данных, инициализируя
их значения или не инициализируя,
присваивая имя или не присваивая.
Для описания символов в коде ASCII
Ассемблер допускает записывать значения
байт в кавычках.
Примеры:
DB ? ; один байт без инициализации и имени
DB 5, 0Fh ; два байта без имени с инициализацией
DB 5,?,7 ; три байта, два с инициализацией, один – без
Five_bytes DB 0,0,0,0,0 ; область 5 байт, значения всех нулевые
The_ptr DB 1122334455 ; 0 … (248-1)
Str DB ‘Строка текста’ ; 13 байт
DB ‘5’ ; один байт, равный 53 или 35h или ‘5’
DB 5 ; один байт, равный 5
При заполнении памяти повторяющимися значениями используется оператор dup:
Примеры:
Buffer DB 200h dup (0) ; буфер 512 байт инициализирован нулями.
String_buf DB 78 dup (‘ ‘) ; буфер приема строки заполнен пробелами.
К одним и тем же
ячейкам памяти можно обращаться как к
данным различных типов. Один из способов
описания таких ячеек памяти предполагает
использование директивы LABEL.
Примеры:
Bytes label byte
Words label word
DB 0,1,2,3,4,5 ; определены шесть байт или три слова
; слова равны: 0100h, 0302h, 0504h
Обращение к ячейкам как к данным нужного типа можно выполнять и без описания их в директиве LABEL, если явно указать тип данных в команде, используя оператор PTR.
Примеры:
b_or_w db 1,2,3,4 ; данные
…
mov al, byte ptr b_or_w ; al := 01
mov ax, word ptr b_or_w ; ax := 0201h
mov al, byte ptr b_or_w+3 ; al := 04
mov ax, word ptr b_or_w+2 ; ax := 0403h
w_or_b dw 0201h,0403h ; те же данные
…
mov al,byte ptr w_or_b+3 ; al := 04
mov ax,w_or_b+2 ; ax := 0403h
Ниже приведен
пример программы на языке Ассемблер с
различными типами данных, описанными
в сегменте данных. Сегмент данных выделен
полужирным шрифтом.
На первой странице листинга программы, приведенной ниже, можно увидеть результаты трансляции рассматриваемой программы. Описанные в исходном модуле данные выделены.
Turbo Assembler Version 2.51 03/07/00 12:25:41 Page 1
prog.ASM
1 name prog
2
3 0000 .model small
4
5 0000 .data
6 ;———————
7 0000 42 65 67 69 6E 20 6F+ db ‘Begin of DATAseg’
8 66 20 44 41 54 41 73+
9 65 67
10
11 0010 12 x1 db 12h
12 0011 1234 x2 dw 1234h
13 0013 12345678 x3 dd 12345678h
14 0017 0123456789ABCDEF x4 dq 0123456789ABCDEFh
15 001F 112233445566778899AA x5 dt 112233445566778899AAh
16 0029 112233445566 x6 dp 112233445566h
17 002F AABBCCDDEEFF x7 df 0AABBCCDDEEFFh
18
19 0035 53 74 72 69 6E 67 20+ s1 db ‘String 1’
20 31
21 003D 2A db ‘*’
22 003E ?? db ?
23 003F ?? db ?
24
25 0040 10*(02 03) b1 db 10h dup (2,3)
26
27 0060 . code
28 ;———————
29 0000 main proc far
30 0000 start:
31 0000 B8 0000s mov ax,@data
32 0003 8E D8 mov ds,ax
33
34 0005 exit:
35 0005 B8 4C00 mov ax,4C00h ; exit
36 0008 CD 21 int 21h
37
38 000A main endp
39 ;———————
40 end start
На второй странице листинга приведена таблица символических имен с указанием их адресов. Так, адрес переменной x4 равен 0017h, т. е. находится в 23-ей ячейке относительно начала сегмента данных, который находится в группе DGROUP.
Turbo Assembler Version 2.51 03/07/00 12:25:41 Page 2
Symbol Table
Symbol Name Type Value
??DATE Text «03/07/00»
??FILENAME Text «prog «
??TIME Text «12:25:41»
??VERSION Number 0205
@CODE Text _TEXT
@CODESIZE Text 0
@CPU Text 0101H
@CURSEG Text _TEXT
@DATA Text DGROUP
@DATASIZE Text 0
@FILENAME Text PROG
@MODEL Text 2
@WORDSIZE Text 2
B1 Byte DGROUP:0040
EXIT Near _TEXT:0005
MAIN Far _TEXT:0000
S1 Byte DGROUP:0035
START Near _TEXT:0000
X1 Byte DGROUP:0010
X2 Word DGROUP:0011
X3 Dword DGROUP:0013
X4 Qword DGROUP:0017
X5 Tbyte DGROUP:001F
X6 Pword DGROUP:0029
X7 Pword DGROUP:002F
Groups & Segments Bit Size Align Combine Class
DGROUP Group
_DATA 16 0060 Word Public DATA
_TEXT 16 000A Word Public CODE
Вид модуля в
отладчике AFD показан на рис. 1.
В ыделенная внизу область – это сегмент данных программы. Адреса данных складываются из двух шестнадцатеричных чисел: в левом столбце и верхней строке над данными. Так, начальный байт имеет адрес 0000h, а его значение равно 42h, или ‘B’ лат., первый символ строки String1 имеет адрес 0030h + 5h = 0035h, а его значение равно 53h или ‘S’ лат. Справа от шестнадцатеричного дампа памяти расположено ASCII-представление этих данных (символьное представление, удобное для чтения текстовых констант).
Рисунок 1
С
егмент
данных в модуле приведен на рис.2. Показаны
зарезервированные в исходном модуле
области данных. Обратное по отношению
с записью в исходном модуле расположение
байтов – характерный эффект, связанный
с представлением ячеек памяти в окне
отладчика слева направо (от младших к
старшим). Так, двойное слово x3,
значение которого инициализировано
шестнадцатеричной константой 12345678h,
занимает байты с адресами 13, 14, 15, 16. При
этом две младшие цифры числа (7 и 8)
занимают младший байт с адресом 13,
следующие две цифры (5 и 6) занимают
следующий байт с адресом 14 и т.д. Строка
текста в окне отладчика читается так
же, как и в исходном модуле, т.к. расположение
текста в памяти – от начала текста в
младших адресах к концу текста в старших
адресах – совпадает с естественным
расположением читаемого текста слева
направо (см. рис.1). Байты с адресами 3E, 3F,
значения которых равны нулю, не
инициализируются программой. Байты с
адресами 40-5F занимают область, зарезервированную
с использованием оператора dup.
Рисунок 2
Вид модуля в отладчике TurboDebuger 5.0 показан на рис.3.
Рисунок 3
x86 — указатель байта сборки, означающий
спросил
Изменено 1 год, 10 месяцев назад
Просмотрено 24к раз
В ecx
у меня есть строка, например "abc"
.
mov ah, БАЙТ PTR [ecx+0] mov al, БАЙТ PTR [ecx+1]
Что именно он делает? Это как в ах
у меня "а"
и в аль
у меня "б"
?
- в сборе
- x86
2
byte ptr
указывает, что операнд памяти относится к байту в памяти, а не к слову или двойному слову. Обычно это можно опустить, так как ассемблер может вывести размер операнда из используемых регистров, но есть некоторые инструкции, такие как mov [eax],0
, где размер не может быть выведен, поэтому необходим префикс byte ptr
, word ptr
или dword ptr
.
1
Иногда нам нужно помочь ассемблеру транслировать ссылки на данные в памяти.
byte ptr
-> это просто означает, что вы хотите получить байт из адреса.
если бы он сказал word ptr
или dword ptr
, вы бы получили слово или двойное слово из адреса в исходном индексе.
Когда вам нужно что-то вроде byte ptr
пример, вы перемещаете непосредственное значение по косвенному адресу:
mov ebx, OFFSET some_symbol ; или указатель из другого регистра мов [ebx], 10
Обычно это не разрешено — ассемблер не знает, хотите ли вы 10 как байт
, слово
, двойное слово или (в 64-битном коде) четверное слово . Вам нужно сделать это явным, указав размер:
mov byte ptr [ebx], 10 ; записать 10 в байт mov word ptr [ebx], 10 ; написать 10 в слово mov dword ptr [ebx], 10 ; написать 10 в dword
3
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Требуется, но не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
Сборка— x86, разница между BYTE и BYTE PTR
Сводка:
- NASM/YASM требует
слова [ecx]
, когда размер операнда не подразумевается другим операндом.(Иначе
[ecx]
в порядке). - MASM/TASM требует
word ptr [ecx]
, когда размер операнда не подразумевается другим операндом. (В противном случае[ecx]
в порядке).
Каждый из них давится синтаксисом другого.
ПРЕДУПРЕЖДЕНИЕ: Это очень странная область без каких-либо стандартов ISO или легкодоступных таблиц BNF; и я не эксперт по минным полям проприетарного синтаксиса MASM.
В вашем случае разницы может и не быть, но в других случаях оператор PTR может означать:
http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm
Обычно оператор PTR заставляет выражение обрабатываться как указатель указанного типа:
.ДАННЫЕ числовое двойное слово 0 .КОД mov ax, WORD PTR [число] ; Загрузить значение размера слова из DWORD
Я думаю, что есть также специфические требования к ассемблеру (nasm/tasm/другой asm), и использование «byte ptr» более переносимо.
Также проверьте раздел 4.2.16 в книге из Индии и разделы 8.12.3 (и 8.11.3 «Конфликты типов») в » Искусство программирования на языке ассемблера «.
ОБНОВЛЕНИЕ: благодаря Фрэнку Котлеру кажется, что NASM «использует вариант синтаксиса ассемблера Intel» (вики), который не включает операцию PTR.
ОБНОВЛЕНИЕ1: есть оригинал » ASM86 LANGUAGE REFERENCE MANUAL » от Intel, 1981-1983, оператор PTR определен на стр. 4-15:
Оператор PTR
Синтаксис: введите имя PTR
Описание: Оператор PTR используется для определения ссылки на память определенного типа. Ассемблер определяет правильную инструкцию для сборки на основе типа операндов инструкции. В некоторых случаях вы можете указать операнд, который не имеет типа. Эти случаи включают использование числовых или регистровых выражений. Здесь оператор PTR используется для указания типа операнда. Следующие примеры иллюстрируют это использование:
MOV WORD PTR [BX], 5 ;установить слово, на которое указывает BX = 5 INC DS:BYTE PTR 10 ;увеличить байт со смещением 10 ;из ДС
Эту форму также можно использовать для переопределения атрибута типа переменной или метки.
Если, например, вы хотите получить доступ к уже определенной словесной переменной как к двум байтам, вы можете закодировать следующее:
MOV CL, BYTE PTR AWORD ;получить первый байт MOV CL, BYTE PTR AWORD + 1 ;получить второй байт
Значения поля:
ТипЭто поле может иметь одно из следующих значений: BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR
имя Это поле может быть: 1. Имя переменной. 2. Имя ярлыка. 3. Адрес или регистровое выражение. 4. Целое число, представляющее смещение.
ОБНОВЛЕНИЕ 2: спасибо битсейверу Университета Штутгарта! Существует оригинальное руководство по MACRO-86 от Microsoft (1981 г.). Страница 3-7:
Оператор PTR можно использовать как другой способ сэкономить байт при использовании прямых ссылок. Если вы определили FOO как прямую константу, вы можете ввести оператор:
ДВИГАТЕЛЬ [BX],FOO
Вы можете указать FOO как непосредственный байт.
В этом случае вы можете ввести любой из операторов (они эквивалентны):
MOV БАЙТ PTR [BX],FOO MOV [BX],BYTE PTR FOO
Эти операторы сообщают MACRO-86, что FOO является непосредственным байтом. Генерируется меньшая инструкция.
И стр. 3-16:
Переопределение операторов
Эти операторы используются для переопределения сегмента, смещения, типа или расстояния переменных и меток.
Указатель (PTR)
<атрибут> PTR <выражение>
Оператор PTR переопределяет тип (BYTE, WORD, DWORD) или расстояние (NEAR, FAR) операнда.
<атрибут>
— новый атрибут; новый тип или новое расстояние.
<выражение>
— это операнд, атрибут которого должен быть переопределен.Наиболее важным и частым использованием PTR является обеспечение того, чтобы MACRO-86 понимал, какой атрибут должен иметь выражение.