Понимание операндов x86 m* (FPU и других)
Я пытаюсь сделать простой дизассемблер x86 (пока 32-битный) для учебных целей.
Таким образом, документы Intel идут:
Но я нахожу это очень запутанным.
Прежде всего, операнды m8-32, кажется, указывают либо ES:(E)DI
или же DS:(E)SI
,
Но нельзя сказать, в каких ситуациях будет та или иная ситуация. В некоторых кодах операций у вас есть OPCODE m8, m8
в других у вас есть только один операнд m8
и после проверки нескольких, я пришел к выводу, что нет общего правила.
Тогда есть эти другие, которые просто описаны как memory operand in memory
, которые оставляют меня еще более запутанным. Должно ли быть смещение, может быть, абсолютный адрес или относительное смещение? Если так, то какой смысл, так как у нас есть moffs
а также rel
?
Последующие имеют смысл, но является ли число после двоеточия смещением?
А амперсанды оставляют меня совершенно невежественным.
Кроме того, есть эти m[number][descriptor]
Что, насколько я вижу, для FPU? (Я еще не имел дело с экранированными кодами 0Fh).
Прошу прощения за то, что я, вероятно, упускаю что-то действительно очевидное, как я часто это делаю.
Заранее спасибо.
2 ответа
Нормальные инструкции вроде add
который может использовать операнд памяти, также работать с регистрами, поэтому ADD имеет кодировки для add r32, r/m32
а также add r/m32, r32
,add eax, ecx
может использовать любую кодировку / код операции (не имеет значения).
Вот почему m32
(и неr/m32
) обычно является неявным операндом дляmovsd
или же stosd
или другие строковые инструкции, и почему Intel говорит, что они обычно используют ES:(E)DI
или же DS:(E)SI
,
Прежде всего, операнды m8-32, кажется, указывают либо ES:(E)DI, либо DS:(E)SI. Но нельзя сказать, в каких ситуациях будет та или иная ситуация.
m32
означает 32-битный операнд памяти, который не может быть регистром. Посмотрите на записи для конкретных инструкций, чтобы увидеть, как определены операнды(например, DS:(E/R)SI
подразумевается дляlodsb/w/d/q
), в то время как другие могут использовать операнд ModR/M, но для этого требуется память.
Для x87 дополнительная аннотация говорит вам, как инструкция интерпретирует это. например m32fp
32-битная IEEE с одинарной точностью float
(например, для fmul
или же fld
), в то время как m32int
32-разрядное целое число (например, для fimul
или же fild
).
Помимо x87, число просто говорит вам размер операнда. Это все.
Обычно операнды памяти задаются с помощью обычного ModR/M + необязательного SIB. Единственными исключениями являются неявные режимы адресации (например, pop rax
чтение qword [rsp]
или строковые инструкции), или moffs
формы MOV, которые пропускают байт ModR/M и просто используют 16/32/64-битное смещение (тот же размер, что и размер адреса).
mov al/ax/eax/rax, [moffs8/16/32/64]
(или форма для хранения) - единственная инструкция, которая может использовать 64-битный абсолютный адрес напрямую, без предварительного внесения в регистр.
Обратите внимание, что moffs8
является 8-битным операндом, а не 8-битным непосредственным адресом. Атрибут адреса-размера инструкции (по умолчанию 64-битный в 64-битном режиме, переопределяемый с помощью 0x67
префикс размера адреса) определяет, сколько байтов абсолютного адреса следует за кодом операции.
Ассемблер позаботится об этом за вас и использует moffs
кодирование, когда он сохраняет размер кода для mov eax, [symbol]
в 32-битном коде. В общем, просто напишите режимы адресации обычным способом ( ссылка на содержимое области памяти. (Режимы адресации x86)) и позвольте ассемблеру сгенерировать байты ModR/M или предупредить вас, если вы сделаете что-то недопустимое (не кодируемое), например попытайтесь использование movsb
с разными регистрами.
Подробнее о x86 asm см. Вики-тег x86. Кроме того, руководства Агнера Фога очень хороши, хотя он не пытается охватить основные вещи, как это. Однако, прочитав руководства Агнера и увидев, что он говорит о своих коротких примерах (пара инструкций), вы сможете понять, как работает asm.
Я только что обнаружил, что у http://ref.x86asm.net/ есть " выродочная " версия его таблиц.
Опкоды описаны здесь.
Компьютерная версия не так однозначна, как кодер.
Тем не менее, если бы кто-то мог направить меня туда, где он сам узнает это, это было бы очень ценно. Кажется, я не могу найти его в документации Intel или где-либо еще, кроме x86asm.
Опять же, я часто скучаю по вещам, поэтому, если я найду что-то, я буду редактировать.
Надеюсь, я смогу помочь.