正如标题所述,为什么人们会使用“movl $ 1,%eax”,而不是“movb $ 1,%eax”,我被告知movl会将%eax的高阶位清零,但是是不是%eax是一个相当于系统字大小的寄存器?意思是movl实际上是一个整数运算(而不是长整数?)
我显然对这一切感到困惑;感谢。
答案 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位字。
%eax
或movl $0, %eax
,否则 xorl %eax, %eax
不会被清零。否则它会保留之前的任何值。当您movl $1, %eax
时,您将在寄存器中以0x00000001
结束,因为32位指令将32位立即值移入寄存器。
答案 3 :(得分:3)
long
最初为32位,而int
和short
为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)
%eax
是32位。 %ax
为16位,%ah
和%al
为8位高和低成分。
因此movl
完全有效。效率方面,movl
将与movb
一样快,将%eax
的高3字节归零通常是理想的属性。您可能希望稍后将其用作32位值,因此movb
不是在那里移动字节的好方法。