将一个字节压入堆栈(IA32)

时间:2018-08-17 06:49:57

标签: assembly x86

我的教科书上有一个问题: 根据操作数给出正确的后缀:

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'?

1 个答案:

答案 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位整数。