“添加esp,0FFFFFFF8h”的序幕

时间:2015-10-14 03:29:59

标签: assembly x86 masm integer-overflow stack-pointer

我的MASM上有点生疏,所以我真的不记得在这里做什么(如果有什么需要做的话)。我有一个MASM(X86)例程,如下所示。它有两个局部变量占用总共5个字节:

MSC_ASM_GenerateBlock PROC buffer:DWORD,bsize:DWORD,safety:DWORD
  LOCAL val:DWORD, rc:BYTE  ;; local variables
  MWSIZE EQU 4              ;; machine word size

  .WHILE bsize >= MWSIZE && safety > 0
     ;; RDRAND is not available prior to VS2012. Just emit
     ;;   the byte codes using DB. This is `rdrand eax`.
     DB 0Fh, 0C7h, 0F0h
     setc rc
     ...
  .ENDW
  ...
MSC_ASM_GenerateBlock ENDP

当我检查反汇编时,我看到:

> dumpbin.exe /DISASM rdrand-x86.obj
Dump of file rdrand-x86.obj

_MSC_ASM_GenerateBlock:
  00000000: 55                 push        ebp
  00000001: 8B EC              mov         ebp,esp
  00000003: 83 C4 F8           add         esp,0FFFFFFF8h
  00000006: EB 1D              jmp         00000025
  00000008: 0F C7 F0           rdrand      eax
  0000000B: 0F 92 45 FB        setb        byte ptr [ebp-5]
  0000000F: 80 7D FB 00        cmp         byte ptr [ebp-5],0
  ...

我相信add esp, 0FFFFFFF8h是另一种说sub esp, 08h的方式。

正如约书亚指出的那样,add espsub esp之间的差异是手术后的标志。汇编程序的混淆或指令选择可以基于汇编程序无法查看RDRAND上下文的事实。相反,它仅基于jmp看到CY,并且汇编程序认为标志处于良好状态。

为什么MASM会生成依赖于无符号整数换行的非直观add?更重要的是,它可以吗?

我使用更宽的机器字执行了到MASM64 / ML64的路由端口。它产生相同的代码(模数机器字大小):

Dump of file rdrand-x64.obj

MSC_ASM_GenerateBlock:
  0000000000000000: 55                 push        rbp
  0000000000000001: 48 8B EC           mov         rbp,rsp
  0000000000000004: 48 83 C4 F0        add         rsp,0FFFFFFFFFFFFFFF0h
  0000000000000008: EB 1D              jmp         0000000000000037
  0000000000000010: 48 0F C7 F0        rdrand      rax
  000000000000001D: 0F 92 45 F7        setb        byte ptr [rbp-9]
  0000000000000024: 80 7D F7 00        cmp         byte ptr [rbp-9],0
  ...

2 个答案:

答案 0 :(得分:5)

奇数编译器。很奇怪。

add esp, 0FFFFFFF8h

完全相同
sub esp, 8h

除了它以不同方式设置标志位。这很好,是的,这取决于无符号整数换行。这不是问题,因为组装本质上是不可移植的。如果你想知道为什么你不得不问微软,他们可能不知道了。

答案 1 :(得分:0)

我不知道为什么MASM会认为这是一个好主意但无符号溢出会起作用(所以这是安全的),更令人困惑的是,这是一个安全的替代,即使在64位处理器上,因为32位操作数将使寄存器的高32位归零!有关说明,请参阅this

此外,由于两个指令都是3个字节长,因此没有任何低效率。