我的教科书上有一个问题: 根据操作数给出正确的后缀:
NAP_Schools_2012_2017$Num_Read_Yrs35_GE80_2015_2017 <-
(NAP_Schools_2012_2017$Num_Read_Yrs35_GE80_2017==TRUE) &
(NAP_Schools_2012_2017$Num_Read_Yrs35_GE80_2016==TRUE) &
(NAP_Schools_2012_2017$Num_Read_Yrs35_GE80_2015==TRUE)
答案是:
push $0xFF
但是为什么不 pushl $0xFF
(我认为pushb $0xFF
不存在)或 pushb
(pushw $0xFF
确实存在),因为pushw
是一个字节,为什么必须是32位/ 4字节的'l'?
答案 0 :(得分:4)
AT&T语法中getYourCountLimitFromSomewhere()
的默认操作数大小(以及所有其他汇编程序,例如NASM和MASM)是宽度当前模式。 (在16位模式下为16位,在32位模式下为32位,在64位模式下为64位。)这与push
/ call
的“堆栈宽度”相匹配。
How many bytes does the push instruction push onto the stack when I don't specify the operand size?
ret
的默认版本也是不需要额外的机器代码前缀进行编码的版本。
在存在歧义时,例如,大多数指令都需要一个显式的操作数大小。 pop
是无效的,但是mov $1234567, (%esp)
是合法的,因为寄存器表示操作数的大小。
但是mov %eax, (%esp)
太有趣了:push
的非默认宽度很少使用,以至于asm语法设计者选择了为其提供默认值而无需push
(AT&T)或{ {1}}(NASM)。请注意,Intel语法排在第一位。 AT&T紧随其后。因此,也许AT&T语法设计人员遵循了早期的Intel语法汇编程序的约定。
我指出这一点是因为,对于AT&T语法,大小后缀仅增加1个字母,但是在Intel语法中看起来比较笨拙。
pushl $0xff
即时型大量用于传统的效率低下的调用约定中,该约定总是在堆栈上传递args,因此易于键入很有意义。
您的教科书是否真的说了“按个字节” ,或者是您编造的?
您不能像您所说的那样在x86中将正义推入一个字节。
您的汇编器甚至无法使用 pushl imm8
编码,因为push dword 0xff
不适合使用符号扩展的8位整数。只有从-128(0xFFFFFF80)到127(0x0000007F)的值才适合带符号的8位整数。