assembly 为什么x86 MOV是两个字节,而不是一个?操作码和机器码是如何工作的?[duplicate]

isr3a4wc  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(143)
    • 此问题在此处已有答案**:

How to read x86 instruction tables from this site(1个答案)
How to tell the length of an x86 instruction?(6个答案)
How to determine if ModR/M is needed through Opcodes?(1个答案)
x86_64 Opcode encoding formats in the intel manual(1个答案)
How to read the Intel Opcode notation(3个答案)
22小时前关门了。
我无法理解一条非常基本的x86指令。

0x080491d7 <+1>:     mov    %esp,%ebp

我知道它会把esp的值移到ebp中,但是我正在努力理解操作码,这个指令是2个字节长,而不是1个字节长,我很困惑,我本以为它只有1个字节。
此指令的内存为:

0x80491d7 <main+1>:     0x89    0xe5

我知道0x89是操作码for MOV之一。我一直在阅读英特尔手册。我不知道0xe5是什么。它是一个后缀还是另一个操作码值还是其他什么?英特尔手册有点混乱。
c程序针对x86 32位进行编译,Linux服务器为x86_64。

mftmpeh8

mftmpeh81#

该指令是2字节长,而不是1,我感到困惑。
是得,查看Intel Developer Manual volume 2中mov指令得说明,可以看到编码为8B /r,根据3.1.1.1“指令汇总表中得操作码列”一章,它具有以下含义:/r — Indicates that the ModR/M byte of the instruction contains a register operand and an r/m operand.因此,第二个字节是ModR/M字节。其含义可在表2-2“ModR/M字节的32位寻址形式”中找到。

fhg3lkii

fhg3lkii2#

我知道0x89是MOV的操作码之一。我一直在阅读英特尔手册。我不知道0xe5是什么。它是像一个后缀或另一个操作码值或其他东西?英特尔手册有点混乱。
您发现mov %esp, %ebp指令使用2个字节进行编码:0x89和0xE5的值。
参考英特尔手册是正确的做法,但我建议使用正确的英特尔语法mov ebp, esp查看您的指令。这可能会使您避免在解释操作码表时出现意外错误。
在单字节操作码表中查找89h,您会看到表中提到的"Ev,Gv"。
"使用操作码表"一章解释了这些字符组合的含义。
E---ModR/M字节跟在操作码后面,指定操作数。
v---字或双字,具体取决于操作数大小属性。
,---通常是分隔逗号。
G--ModR/M字节内的寄存器字段选择通用寄存器。
因此第二个字节是ModR/M字节。
您的ModR/M字节是E5h或11 '100' 101b,以二进制表示法表示,紧跟在分组'mod-reg-r/m'之后。

  • 由于提到"Gv",寄存器字段(100b)指的是(d)字长的通用寄存器。它可以指SP或ESP。
  • 因为2个最高有效位(11b)设置在ModR/M字节中,所以3个最低有效位(101b)指寄存器。并且因为提到"Ev",所以它可能指BP或EBP。

哪些寄存器?为此,我们看一下操作码89h或100010'0 '1b(二进制表示法,跟随在' TTTTTT-d-w '分组之后)。
位0(w)告诉我们这是一个(d)字长的操作(与上面提到的"v"一致)。由于这是32位代码,并且没有使用操作数大小前缀(0x66),因此剩下的是ESP/EBP
位1(d)告诉我们哪个操作数是源操作数还是目的操作数(这与上面提到的"E,G"一致)。由于该位为0,所以reg字段(ESP)表示源和r/m字段(EBP)表示目的地。如果设置了d位,则相反,表示字节0x8B,0xEC也是您指令mov %esp, %ebp的完美编码。

相关问题