我正在查看一些汇编代码和相应的内存转储,但我无法理解正在发生的事情。我正在使用this as reference for opcodes for x86和this as reference for registers in x86。我遇到了这些命令,我意识到我仍然错过了一大块难题。
8B 45 F8 - mov eax,[ebp-08]
8B 80 78040000 - mov eax,[eax+00000478]
8B 00 - mov eax,[eax]
基本上我不明白操作码之后的两个字节是什么意思,我找不到任何能为命令提供逐位格式的地方(如果有人能指出我的话)一个人会非常感激。)
CPU如何知道每个命令的持续时间?
根据我的参考,这个8B mov命令允许使用32b或16b寄存器,这意味着有16个可能的寄存器(AX,CX,DX,BX,SP,BP,SI,DI及其扩展等价物)。这意味着您需要一个完整的字节来指定在每个操作数中使用哪个寄存器。
到目前为止仍然很好,操作码后面的两个字节可以指定使用哪些寄存器。然后我注意到这些命令在内存中逐字节堆叠,并且它们都使用不同的字节数来指定解除引用第二个操作数时要使用的偏移量。
我想你可以限制寄存器只能使用带有16b的16b和带32b的32b,但这只会释放一个位,不足以告诉CPU有多少字节的偏移量。
哪些值对应哪些寄存器?
困扰我的第二件事是虽然我的引用明确地给寄存器编号,但是在这些命令中操作码之后没有看到与字节的任何相关性。即使是他们自己,这些命令似乎也不一致。第二个和第三个命令都是从eax到eax,但在第一个字节中间有一点不同。
根据我的参考,我假设0是EAX,1是ECX,2是EDX,依此类推。但是,这并不能让我深入了解如何在RAX,EAX,AX,AL和AH之间进行指定。一些命令似乎只接受8b寄存器,而其他命令接受16b或32b,而在x86_64上,一些命令似乎接受16b,32b或64b寄存器。所以你会做一些类似0-7的事情是R,8-15 E,16-23非延伸,24-31 H和L?即使它是这样的,似乎应该更容易找到手册或指定的东西。
答案 0 :(得分:9)
操作码之后的第一个字节是ModR / M字节。您链接的第一个引用包含朝向页面末尾的ModR / M字节的表。对于诸如此类的存储器访问指令,ModR / M字节表示正在加载或存储的寄存器以及用于存储器访问的寻址模式。
ModR / M字节后面的字节取决于ModR / M字节的值。
在“mov eax,[ebp-8]”指令中,ModR / M字节为45.从32位ModR / M字节表中,这表示Reg是eax,有效地址是[EBP] + DISP8。指令的下一个字节F8是8位有符号偏移量。
指令的操作数大小可以隐含在指令中,也可以由指令前缀指定。例如,66前缀表示16位操作数,对于mov指令,例如示例中的那些。如果您使用的是64位模式,则48前缀表示64位操作数。
8位操作数通常由指令的低位指示。如果将示例中的指令从8B更改为8A,则它将变为8位移动到al。