"add esp, 0FFFFFFF8h" 序言
Prologue of "add esp, 0FFFFFFF8h"
我的 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
的另一种说法。
正如 Joshua 所指出的,add esp
和 sub esp
之间的区别在于操作后的标志。汇编器对指令的混淆或选择可能是基于汇编器看不到 RDRAND
上下文这一事实。相反,它只看到基于 CY
的 jmp
,并且汇编器认为标志状态不佳。
为什么 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
...
奇怪的编译器。很奇怪。
add esp, 0FFFFFFF8h
与
完全相同
sub esp, 8h
除了它以不同方式设置标志位。没关系,是的,它取决于无符号整数换行。这不是问题,因为组装本质上是不可移植的。如果你想知道为什么你必须问微软,他们可能已经不知道了。
我不知道为什么 MASM 会认为这是个好主意,但无符号溢出会起作用(所以这是安全的),更令人困惑的是,即使在 64 位处理器上,这也是一个安全的替代,因为 32 位操作数会将寄存器的高 32 位清零!有关解释,请参阅 this。
此外,由于两条指令都是 3 个字节长,因此没有任何低效率。
我的 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
的另一种说法。
正如 Joshua 所指出的,add esp
和 sub esp
之间的区别在于操作后的标志。汇编器对指令的混淆或选择可能是基于汇编器看不到 RDRAND
上下文这一事实。相反,它只看到基于 CY
的 jmp
,并且汇编器认为标志状态不佳。
为什么 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
...
奇怪的编译器。很奇怪。
add esp, 0FFFFFFF8h
与
完全相同sub esp, 8h
除了它以不同方式设置标志位。没关系,是的,它取决于无符号整数换行。这不是问题,因为组装本质上是不可移植的。如果你想知道为什么你必须问微软,他们可能已经不知道了。
我不知道为什么 MASM 会认为这是个好主意,但无符号溢出会起作用(所以这是安全的),更令人困惑的是,即使在 64 位处理器上,这也是一个安全的替代,因为 32 位操作数会将寄存器的高 32 位清零!有关解释,请参阅 this。
此外,由于两条指令都是 3 个字节长,因此没有任何低效率。