鉴于这段代码:
swap:
push ebp ; back up the base pointer,
mov ebp, esp
; push the context of the registers on the stack
push eax
push ebx
push ecx
push edx
mov eax, [ebp+8] ; address of the first parameter
mov ebx, [ebp+12] ; address of the second parameter
mov dl, [eax]
mov cl, [ebx]
mov [eax], cl
mov [ebx], dl
; restore the context of the registers from the stack
pop edx
pop ecx
pop ebx
pop eax
; restore the ebp
pop ebp
ret
(这只是方法。之前我们在堆栈上推送了第一个和第二个参数。)
我的问题是:为什么我们将8添加到Base Pointer以获取第一个参数的地址,然后是12?
我得到的事实是他们是dword所以他们每个都是4个字节..所以从ebp + 8到ebp + 12它让人感觉很好。但为什么第一个是ebp + 8?因为如果ESP指向堆栈的顶部,那么mov ebp,esp意味着EBP指向堆栈的TOP。然后我们在堆栈上推送4个值:eax,ebx,ecx和edx。为什么EBP + 8指向第一个参数?
答案 0 :(得分:45)
调用该函数时,堆栈如下所示:
+-------------+
| Parameter 2 |
+-------------+
| Parameter 1 |
+-------------+
| Return Addr | <-- esp
+-------------+
然后在设置“堆栈帧”之后:
+-------------+
| Parameter 2 | <-- [ebp + 12]
+-------------+
| Parameter 1 | <-- [ebp + 8]
+-------------+
| Return Addr |
+-------------+
| saved ebp | <-- ebp
+-------------+ <-- esp
现在保存了上下文:
+-------------+
| Parameter 2 | <-- [ebp + 12]
+-------------+
| Parameter 1 | <-- [ebp + 8]
+-------------+
| Return Addr |
+-------------+
| saved ebp | <-- ebp
+-------------+
| saved eax |
+-------------+
| saved ebx |
+-------------+
| saved ecx |
+-------------+
| saved edx | <-- esp
+-------------+
不要忘记,在许多系统上,堆栈向下增长(对于x86系列来说确实如此),因此堆栈的顶部将具有最低的内存地址。
答案 1 :(得分:6)
因为堆叠上还有另外两个项目;你在这个例程的开头推送的前一个ebp,以及通过调用例程放在堆栈上的返回地址。