汇编 x86 "enter 0,0" 的目的是什么
Assembly x86 what's the purpose of "enter 0,0"
目前我正在使用 NASM 学习 x86 的汇编。我尝试编写以下计算斐波那契数的函数:
unsigned int fibonacci(unsigned int n) {
if (n < 2)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
这就是我目前所做的,效果很好,与上述方法完全一样。但据我所知, enter 0,0
指令是为了在堆栈中释放 space 用于局部变量。我将两个局部变量压入堆栈:push dword ptr[n]
。但是,如果我像这样使用 enter
指令,这难道不应该是可能的吗:enter 8,0
。为两个 int 变量释放 space。如果我尝试这样做,我会收到 Whosebug 异常。
__declspec(naked) unsigned int fibonacci2(unsigned int n) {
__asm {
enter 0,0
cmp dword ptr [n], 2
jae elsee
mov eax, 1
jmp end
elsee:
push dword ptr[n] // Here I am pushing two local variables to the stack.
push dword ptr[n] // 2 * 4 Bytes
dec [ebp-4]
dec [ebp-8]
dec [ebp-8]
push[ebp-4]
call fibonacci2
mov [ebp-4], eax
push [ebp-8]
call fibonacci2
add eax, [ebp-4]
end:
leave
ret
}
}
这是函数的编译版本:
00C426E0 enter 0,0
00C426E4 cmp dword ptr [n],2
00C426E8 jae fibonacci2+11h (0C426F1h)
00C426EA mov eax,1
00C426EF jmp end (0C42716h)
elsee:
00C426F1 push dword ptr [n]
00C426F4 push dword ptr [n]
00C426F7 dec byte ptr [ebp-4]
00C426FA dec byte ptr [ebp-8]
00C426FD dec byte ptr [ebp-8]
00C42700 push dword ptr [ebp-4]
00C42703 call _fibonacci2 (0C413BBh)
00C42708 mov dword ptr [ebp-4],eax
00C4270B push dword ptr [ebp-8]
00C4270E call _fibonacci2 (0C413BBh)
00C42713 add eax,dword ptr [ebp-4]
end:
00C42716 leave
00C42717 ret
To free up space for the two int variables.
编译器不需要为局部变量使用堆栈。在某些情况下,它甚至可以完全优化堆栈使用并将局部变量存储在寄存器中。
I push two local variables to the stack: push dword ptr[n]. But shouldn't this only be possible if I use the enter instruction like this: enter 8,0.
enter
指令的作用与您认为的完全相反:
它不分配(堆栈)可被push
指令使用的内存,但它使用(堆栈) 与 push
指令相同的内存方式:
enter 80,0
的工作方式类似于先执行 enter 0,0
,然后使用 10 个 random 值执行 push
10 次。这对 "create" 10 个未初始化的局部变量在堆栈上很有用。
如前所述enter 0,0
,只会push
并初始化ebp
寄存器。使用启用了优化的真实 C 编译器,在这种情况下您可能不会获得 enter
指令。
If I try to do so, I get a Whosebug exception.
很难说为什么:
如果您为大量数字调用您的函数,您的函数将需要大量堆栈。通过使用 enter 8,0
而不是 enter 0,0
你需要 8*n
字节更多的函数参数堆栈 n
.
如果你的堆栈在使用enter 0,0
时已经接近"full",那么在使用enter 8,0
时肯定会满。
其次是你的反汇编不完整:
- 显然,C 编译器在地址
0C413BBh
. 处添加了一些名为 _fibonacci2
(带下划线)的包装器
- 反汇编没有将
n
显示为 ebp+8
,而是显示为 n
。
可能是您发布的代码中看不到错误:
- 它可能位于地址
0C413BBh
的包装器中
- 或者
n
没有被正确替换(被ebp+8
)
目前我正在使用 NASM 学习 x86 的汇编。我尝试编写以下计算斐波那契数的函数:
unsigned int fibonacci(unsigned int n) {
if (n < 2)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
这就是我目前所做的,效果很好,与上述方法完全一样。但据我所知, enter 0,0
指令是为了在堆栈中释放 space 用于局部变量。我将两个局部变量压入堆栈:push dword ptr[n]
。但是,如果我像这样使用 enter
指令,这难道不应该是可能的吗:enter 8,0
。为两个 int 变量释放 space。如果我尝试这样做,我会收到 Whosebug 异常。
__declspec(naked) unsigned int fibonacci2(unsigned int n) {
__asm {
enter 0,0
cmp dword ptr [n], 2
jae elsee
mov eax, 1
jmp end
elsee:
push dword ptr[n] // Here I am pushing two local variables to the stack.
push dword ptr[n] // 2 * 4 Bytes
dec [ebp-4]
dec [ebp-8]
dec [ebp-8]
push[ebp-4]
call fibonacci2
mov [ebp-4], eax
push [ebp-8]
call fibonacci2
add eax, [ebp-4]
end:
leave
ret
}
}
这是函数的编译版本:
00C426E0 enter 0,0
00C426E4 cmp dword ptr [n],2
00C426E8 jae fibonacci2+11h (0C426F1h)
00C426EA mov eax,1
00C426EF jmp end (0C42716h)
elsee:
00C426F1 push dword ptr [n]
00C426F4 push dword ptr [n]
00C426F7 dec byte ptr [ebp-4]
00C426FA dec byte ptr [ebp-8]
00C426FD dec byte ptr [ebp-8]
00C42700 push dword ptr [ebp-4]
00C42703 call _fibonacci2 (0C413BBh)
00C42708 mov dword ptr [ebp-4],eax
00C4270B push dword ptr [ebp-8]
00C4270E call _fibonacci2 (0C413BBh)
00C42713 add eax,dword ptr [ebp-4]
end:
00C42716 leave
00C42717 ret
To free up space for the two int variables.
编译器不需要为局部变量使用堆栈。在某些情况下,它甚至可以完全优化堆栈使用并将局部变量存储在寄存器中。
I push two local variables to the stack: push dword ptr[n]. But shouldn't this only be possible if I use the enter instruction like this: enter 8,0.
enter
指令的作用与您认为的完全相反:
它不分配(堆栈)可被push
指令使用的内存,但它使用(堆栈) 与 push
指令相同的内存方式:
enter 80,0
的工作方式类似于先执行 enter 0,0
,然后使用 10 个 random 值执行 push
10 次。这对 "create" 10 个未初始化的局部变量在堆栈上很有用。
如前所述enter 0,0
,只会push
并初始化ebp
寄存器。使用启用了优化的真实 C 编译器,在这种情况下您可能不会获得 enter
指令。
If I try to do so, I get a Whosebug exception.
很难说为什么:
如果您为大量数字调用您的函数,您的函数将需要大量堆栈。通过使用 enter 8,0
而不是 enter 0,0
你需要 8*n
字节更多的函数参数堆栈 n
.
如果你的堆栈在使用enter 0,0
时已经接近"full",那么在使用enter 8,0
时肯定会满。
其次是你的反汇编不完整:
- 显然,C 编译器在地址
0C413BBh
. 处添加了一些名为 - 反汇编没有将
n
显示为ebp+8
,而是显示为n
。
_fibonacci2
(带下划线)的包装器
可能是您发布的代码中看不到错误:
- 它可能位于地址
0C413BBh
的包装器中
- 或者
n
没有被正确替换(被ebp+8
)