long getesp() { __asm__("movl %esp,%eax"); } void main() { printf("%08X\n",getesp()+4); }
爲什麼在堆棧幀設置之前esp指向value,並且它與下面的代碼有什麼區別?在C++中執行彙編函數
void main() { __asm__("movl %esp,%eax"); }
long getesp() { __asm__("movl %esp,%eax"); } void main() { printf("%08X\n",getesp()+4); }
爲什麼在堆棧幀設置之前esp指向value,並且它與下面的代碼有什麼區別?在C++中執行彙編函數
void main() { __asm__("movl %esp,%eax"); }
後,我做了一個gcc -S file.c
getesp:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
#APP
# 4 "xxt.c" 1
movl %esp,%eax
# 0 "" 2
#NO_APP
leave
ret
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
call getesp
addl $4, %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
的getesp
有pushl
其操縱esp
,並與在線獲取eax
操縱esp
和以及在ebp
。
進行函數調用來獲取堆棧指針並在main
中得到它肯定是不同的,並且它相差12個字節(在這個特定情況下)。這是因爲當你執行call
時推動eip
(如果不是段間,並且對於linux/unix正常程序執行它只是eip
)(需要引用),接下來在getesp
函數中有另一個push
和ebp
,之後堆棧指針減去4.因爲eip
和ebp
是4個字節,所以總差值現在是12個字節。實際上我們可以在函數調用版本中看到。
沒有函數調用eip
等esp
沒有推動操作,所以我們得到主設置後的esp
值。
我不熟悉AT & T所以這裏是Intel語法和下面的Intex語法asm dump中的相同代碼。需要注意的是在主值內printf
呼籲__asm__
陷入a
沒有推或其他esp
修改的話,裏面主要的__asm__
得到這是在主要由sub esp, 20
線設置esp
值。如上所述,通過調用getesp
得到的值就是(你所期望的) - 12。
C代碼
#include <stdio.h>
int a;
long getesp() {
__asm__("mov a, esp");
}
int main(void)
{
__asm__("mov a,esp");
printf("%08X\n",a);
getesp();
printf("%08X\n",a);
}
輸出是在我的案件的具體運行:
BF855D00
BF855CF4
英特爾語法轉儲:
getesp:
push ebp
mov ebp, esp
sub esp, 4
#APP
# 7 "xt.c" 1
mov a, esp
# 0 "" 2
#NO_APP
leave
ret
main:
lea ecx, [esp+4]
and esp, -16
push DWORD PTR [ecx-4]
push ebp
mov ebp, esp
push ecx
sub esp, 20
#APP
# 12 "xt.c" 1
mov a,esp
# 0 "" 2
#NO_APP
mov eax, DWORD PTR a
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], OFFSET FLAT:.LC0
call printf
call getesp
mov eax, DWORD PTR a
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], OFFSET FLAT:.LC0
call printf
add esp, 20
pop ecx
pop ebp
lea esp, [ecx-4]
ret
我希望這有助於。