Конвертировать инструкцию в коде ассемблера lods и stos, чтобы NASM мог скомпилировать
Итак, я пытаюсь собрать некоторый код в сборке, используя nasm -f elf final.asm
:
xor eax,eax
push eax
push dword(0x75792273)
push dword(0x70742027)
push dword(0x77777875)
push dword(0x20237678)
push dword(0x76727827)
push dword(0x27797175)
push dword(0x75711225)
push dword(0x72747676)
push dword(0x74231476)
push dword(0x70707470)
push dword(0x23247077)
push dword(0x78707822)
push dword(0x24711174)
push dword(0x22707373)
push dword(0x78717974)
push dword(0x75771777)
push dword(0x70777125)
push dword(0x73731472)
push dword(0x71277377)
push dword(0x79251822)
push dword(0x79707478)
push dword(0x78742779)
push dword(0x72727871)
push dword(0x71251475)
push dword(0x27247772)
push dword(0x79757479)
push dword(0x70227071)
push dword(0x77737420)
push dword(0x70251970)
push dword(0x74747127)
push dword(0x23277677)
push dword(0x79712024)
push esp
pop esi
mov edi,esi
mov edx,edi
cld
mov ecx,0x80
mov ebx,0x41
xor eax,eax
push eax
lods byte[esi]
xor eax,ebx
stos byte[es:edi]
loop 0xb7
push esp
pop esi
int 0x3
Что приводит к следующей ошибке:
final.asm:44: error: parser: instruction expected
final.asm:46: error: parser: instruction expected
Я нашел ответ на эти ошибки по адресу: NASM: parser: инструкция ожидаемого rep movs
По сути, это говорит о том, что инструкции lods и stos не распознаются NASM. Это означает, что мне нужно преобразовать их во что-то, что NASM распознает, чтобы получить тот же результат.
Мой вопрос заключается в том, на что я могу изменить эти две строки, чтобы NASM мог скомпилировать их, чтобы в итоге я смог их отладить.
2 ответа
Какие lodsb
делает это:
mov al,[esi]
inc esi ; (or dec, according to direction flag)
Вы также можете использоватьlodsw
загрузить слова (для ax
), или жеlodsd
загрузить мечи eax
).esi
будет увеличен на 2 или 4 в этих случаях
а также stosb
делает
mov [es:edi],al
inc edi
тоже самое, stosw
а также stosd
будет хранить 2 или 4 байта
одна загружается из памяти, на которую указывает регистр SOURCE (ESI), другая записывает в память, указанную регистром DESTINATION (ES:EDI).
Вам не нужно (и нельзя) указать, какие регистры будут использоваться. Источником всегда будет ES I, а местом назначения всегда будет ED I
Изменить на сегментных регистрах: lods
Инструкция может использоваться вместе с префиксом переопределения сегмента (т.е. ss lodsb
). stos
инструкция фиксируется на es
(отсутствует деталь в исходном ответе) использование сегмента, и не может быть переопределено.
movsb/movsw/movsd
инструкции (size*(mov [es:edi],[ds:esi] inc esi inc edi)
) также может быть переопределено на стороне источника, т.е. es movsb
будет извлекать байты из es:esi
вместо ds:esi
, но регистр сегмента назначения фиксирован es
,
Документация Intel LODS предполагает, что вы можете использовать операнды в качестве документации и подразумевать размер операнда (и переопределение сегмента), как вы пытаетесь сделать, в качестве альтернативы суффиксу размера операнда.
Эта форма явных операндов предоставляется для разрешения документации; Однако обратите внимание, что документация, предоставленная этой формой, может вводить в заблуждение. То есть исходный символ операнда должен указывать правильный тип (размер) операнда (байт, слово или двойное слово), но он не должен указывать правильное местоположение. Местоположение всегда определяется DS:(E)SI-регистрами, которые должны быть загружены правильно перед выполнением команды загрузки строки.
Предположительно разработчики синтаксиса NASM решили, что lods byte [r15]
сборка была плохой идеей, и полностью запретить форму с одним операндом было проще, чем написать кучу кода, просто чтобы проверить, является ли данный операнд тем, чем он должен быть.
Поскольку NASM имеет синтаксис префикса для переопределений сегментов / операндов / адресов, fs lodsb
позволяет вам написать то, что в противном случае понадобился бы операнд для присоединения переопределения сегмента к lodsb fs:[rsi]
в синтаксисе MASM.)
Выполнение этого таким образом делает строковые инструкции несвойственными для ассемблера; это просто еще одна запись в таблице, отображающая мнемонику в коды операций. Если бы собственный синтаксис Intel включал мнемонические префиксы для байтов префикса машинного кода, они могли бы сделать такой же выбор дизайна.
Интересный факт: сегмент STOS не может быть переопределен (из ES). Возможно, Intel хотела поделиться большим количеством транзисторов с первоначальной реализацией MOVS8086, где переопределение сегмента влияет только на [DS:SI]
источник, а не [ES:DI]
место назначения.
другие монтажники:
GNU .intel_syntax
поддерживает синтаксис префикса сегмента, но не NASM o16
/o32
/o64
или же a16
/a32
/a64
Операнды и спецификаторы размера адреса.
# assembled with as --32 disassembled with ndisasm -b 32
.intel_syntax noprefix
mov al, byte ptr fs:[esi]
00000038 648A06 mov al,[fs:esi]
gs lodsb
0000003B 65AC gs lodsb
lods dword ptr ss:[ecx]
# Warning: `dword ptr ss:[ecx]' is not valid here (expected `[esi]')
0000003D 36AD ss lodsd
ss lodsd [si]
0000003F 3667AD ss a16 lodsd
lods eax, dword ptr ss:[esi]
00000042 36AD ss lodsd
#lods al # Error: operand type mismatch for `lods'
#fs es lodsd # Error: same type of prefix used twice
#a16 lodsb # Error: no such instruction: `a16 lodsb'
Я не вижу способа написать переопределение размера адреса без использования явного операнда для строковых инструкций в синтаксисе GNU (AT&T или Intel).
objdump -Mintel
выход тот же:
4: 64 8a 06 mov al,BYTE PTR fs:[esi]
7: 65 ac lods al,BYTE PTR gs:[esi]
9: 36 ad lods eax,DWORD PTR ss:[esi]
b: 36 67 ad lods eax,DWORD PTR ss:[si]
e: 36 ad lods eax,DWORD PTR ss:[esi]