首页 > 技术文章 > 汇编语言8堆栈指针

mayingkun 2015-07-06 18:32 原文

分析程序1:
C语言代码如下

#include <stdio.h>
void fun(int na, int nb)
{
int nc = na+nb;
printf("one\n");
}
void fun1()
{
printf("two\n");
}
void main()
{
fun(55,66);
fun1();
}

 




汇编代码. 详细标出esp的变化情况

void fun(int na, int nb)
{                        esp=0xfa38 ebp=0xfa44 ;call fun (12B1000h)执行后 
push ebp    esp=0xfa34 ebp=0xfa44      ;esp-=4
mov ebp,esp                  esp=0xfa34 ebp=0xfa34 
push ecx    esp=0xfa30           ;esp-=4

int nc = na+nb;
mov eax,dword ptr [na] 
add eax,dword ptr [nb] 
mov dword ptr [nc],eax 
printf("one\n");
push 3720F4h               ;esp-=4 
call dword ptr [3720A0h] 
add esp,4                  ;esp+=4, 重置下栈顶
}
void fun1()
{
push ebp 
mov ebp,esp 
printf("two\n");
push offset ___xi_z+3Ch (0CA20FCh) 
dword ptr [0CA20A0h] 
add esp,4 
}


void main()
{                          esp=0xfa48 ebp=0xfa88
push ebp                      esp=0xfa44 ebp=0xfa88  esp-=4 
mov ebp,esp                    esp=0xfa44    ebp=0xfa44 
fun(55,66);
push 42h    esp=0xfa40                ;esp-=4
push 37h    esp=0xfa3c                ;esp-=4 
call fun (12B1000h)                 ;esp-=4 
add esp,8                      ;esp+=8, 重置下栈顶
fun1();                      ;esp-=4 
call fun1 (12B1020h) 
}
xor eax,eax                      ;异或 eax=0
pop ebp                              ;还原ebp    
ret                          ;设置eip = 调用main的位置

 

要点归纳:
1.堆栈初始化代码:
push ebp
mov ebp,esp
..................
pop ebp
ret


2. ESP, EBP指令
ESP就是一直指向栈顶的指针,而EBP只是存取某时刻的栈顶指针,以方便对栈的操作,如获取函数参数、局部变量等,
ESP是栈指针,是CPU机制决定的,push、pop指令会自动调整ESP的值, EBP不是必须的,但有了它可以把过程分开,方便调试。
push 指令 调用后 esp-=4
pop 指令 调用后 esp+=4
call 指令 调用后 esp-=4
函数内部 push后 要 设置esp,保证栈中用不到的内存被覆盖

 

小程序2:
C代码如下

#include <stdio.h>
bool f =false;
bool fun(int na)
{
if (na>100)
return true;
else
return false;
}
void main()
{
f = fun(11111);
}

 

汇编代码.

#include <stdio.h>
bool f =false;
bool fun(int na)
{
push ebp 
mov ebp,esp 
if (na>100)
cmp dword ptr [ebp+8], 64h                  ;[ebp+8] 表示na存放的位置
jle 128100Fh
return true;
mov al,1 
jmp 1281011h                     ;1281011h编译器计算好的
else
jmp 1281011h                        ;1281011h编译器计算好的
return false;
xor al,al                            ;异或设置eax=0
}
pop ebp 
ret                              ;改变eip


void main()
{
push ebp 
mov ebp,esp 
f = fun(11111);
push 2B67h 
call fun (1281000h) 
add esp,4 
mov byte ptr [f (1283370h)],al          ;函数返回值保存在EAX里面, bool 相当于一个8位数据
}
xor eax,eax 
pop ebp 
ret

 

推荐阅读