Конвертировать инструкцию в коде ассемблера 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]
Другие вопросы по тегам