为什么会使用“movl $ 1,%eax”而不是“movb $ 1,%eax”

时间:2009-12-14 03:59:26

标签: assembly x86

正如标题所述,为什么人们会使用“movl $ 1,%eax”,而不是“movb $ 1,%eax”,我被告知movl会将%eax的高阶位清零,但是是不是%eax是一个相当于系统字大小的寄存器?意思是movl实际上是一个整数运算(而不是长整数?)

我显然对这一切感到困惑;感谢。

6 个答案:

答案 0 :(得分:39)

  

反对,比如“movb $ 1,%eax”

该指令无效。你不能在movb指令中使用eax。 您将改为使用8位寄存器。例如:

movb $ 1,$ al

  

但不是%eax是一个寄存器   相当于系统的大小   WORDSIZE?

没有。无论系统的寄存器大小如何,EAX都将始终为32位值。

您将C变量大小与寄存器大小混淆。 C变量大小可能会根据您的系统和编译器而改变。

汇编比C简单。在GAS汇编中,指令后缀有字母“b”,“s”,“w”,“l”,“q”或“t”,以确定操作数的操作数是多少。

* b = byte (8 bit)
* s = short (16 bit integer) or single (32-bit floating point)
* w = word (16 bit)
* l = long (32 bit integer or 64-bit floating point)
* q = quad (64 bit)
* t = ten bytes (80-bit floating point)

这些尺寸是不变的。它们永远不会改变。 al始终为8位,eax始终为32位。

答案 1 :(得分:7)

在32位机器上,%eax是一个4字节(32位)寄存器。 movl将写入所有4个字节。在您的示例中,它会将高3字节清零,并将1放在最低字节中。 movb只会改变低位字节。

答案 2 :(得分:5)

%eax是一个32位寄存器。要使用较小的宽度,16位需要%ax。对于%ax的高字节,%ah可以进一步分为%ax,对于低字节,%al可以进一步分为mov。其他x86 GPR也是如此。

查看%al指令的Intel指令集参考,我没有看到可以将单个字节移动到32位寄存器的变体 - 它可能被解释为移入{{1 }}

由于movl是32位指令,因此在立即值的情况下,高位字节的值将对应于零。如果你从内存中移动,你将移动一个完整的32位字。

除非您%eaxmovl $0, %eax,否则

xorl %eax, %eax不会被清零。否则它会保留之前的任何值。当您movl $1, %eax时,您将在寄存器中以0x00000001结束,因为32位指令将32位立即值移入寄存器。

答案 3 :(得分:3)

long最初为32位,而intshort为16.并且每当有人推出新操作系统时,操作码的名称都不会改变。< / p>

答案 4 :(得分:2)

您的第二个选择只会产生错误,x86没有该指令。在将字节加载到某些寄存器方面,X86有点独特。是的,在大多数指令集架构中,操作数为零或符号扩展,但x86允许您只写一些低位字节或低16位。

当然还有其他选择,例如清除寄存器然后递增它,但这里有三个最初看起来合理的选择:

   0:   b8 01 00 00 00          movl   $0x1,%eax

   5:   31 c0                   xorl   %eax,%eax
   7:   b0 01                   movb   $0x1,%al

   9:   b0 01                   movb   $0x1,%al
   b:   0f b6 c0                movzbl %al,%eax

第一个是5个字节,第二个是4,第三个是5.所以第二个是优化空间的最佳选择,否则我认为最有可能快速运行的是第一个。 X86现在已经深度流水线化,因此两条指令将互锁,并且机器可能需要相当多的等待状态,具体取决于管道硬件的细节。

当然,这些x86操作系统正在以特定于CPU的方式转换为 CPU micro-ops ,因此谁知道会发生什么。

答案 5 :(得分:1)

在32位计算机上,

%eax是32位。 %ax为16位,%ah%al为8位高和低成分。

因此movl完全有效。效率方面,movl将与movb一样快,将%eax的高3字节归零通常是理想的属性。您可能希望稍后将其用作32位值,因此movb不是在那里移动字节的好方法。