函数堆栈

#include <windows.h>

int func002(char *str, int len)
{
    strcpy(str, "hello");
    
    return len;    
}

int func001(int x, char y, char *z)
{
    char buff[10];
    int aa;
    
    func002(z, aa);
    
    return 0x100;
}

void main_call()
{
    int a;
    char b;
    char c[100];
    
    func001(a, b, c);	
    
    func002(c, a);
}

void main()
{
    main_call();
}



对应的反汇编代码:cl /Fac1.asm cat.c

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08 

	TITLE	E:\code\ctoasm\cat.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

_DATA	SEGMENT
$SG76990 DB	'hello', 00H
_DATA	ENDS
PUBLIC	_func002
EXTRN	_strcpy:PROC
; Function compile flags: /Odtp
_TEXT	SEGMENT
_str$ = 8						; size = 4
_len$ = 12						; size = 4
_func002 PROC
; File e:\code\ctoasm\cat.c
; Line 5
	push	ebp
	mov	ebp, esp
; Line 6
	push	OFFSET $SG76990
	mov	eax, DWORD PTR _str$[ebp]
	push	eax
	call	_strcpy
	add	esp, 8
; Line 8
	mov	eax, DWORD PTR _len$[ebp]   //eax才是函数返回值,len实际未赋值
; Line 9
	pop	ebp
	ret	0
_func002 ENDP
_TEXT	ENDS
PUBLIC	_func001
; Function compile flags: /Odtp
_TEXT	SEGMENT
_aa$ = -4						; size = 4
_x$ = 8							; size = 4  //0的前面压栈了pc和ebp。
_y$ = 12						; size = 1
_z$ = 16						; size = 4
_func001 PROC
; Line 12
	push	ebp
	mov	ebp, esp
	sub	esp, 20					; 00000014H
; Line 16
	mov	eax, DWORD PTR _aa$[ebp]
	push	eax
	mov	ecx, DWORD PTR _z$[ebp]
	push	ecx
	call	_func002
	add	esp, 8
; Line 18
	mov	eax, 256				; 00000100H //返回值
; Line 19
	mov	esp, ebp
	pop	ebp
	ret	0
_func001 ENDP
_TEXT	ENDS
PUBLIC	__$ArrayPad$
PUBLIC	_main_call
EXTRN	___security_cookie:DWORD
EXTRN	@__security_check_cookie@4:PROC
; Function compile flags: /Odtp
_TEXT	SEGMENT
_c$ = -120						; size = 100  //字节对齐108,并填充12字节,所以分配的局部变量空间是120B
__$ArrayPad$ = -12					; size = 4
_b$ = -5						; size = 1
_a$ = -4						; size = 4
_main_call PROC
; Line 22
	push	ebp  // 每一级的ebp指向上一级的esp起始地址。
	mov	ebp, esp
	sub	esp, 120				; 00000078H
	mov	eax, DWORD PTR ___security_cookie
	xor	eax, ebp
	mov	DWORD PTR __$ArrayPad$[ebp], eax   //&*%*&%
; Line 27
	lea	eax, DWORD PTR _c$[ebp]  //为什么不都用eax?
	push	eax
	movzx	ecx, BYTE PTR _b$[ebp]   //赋值并清零。
	push	ecx
	mov	edx, DWORD PTR _a$[ebp]
	push	edx
	call	_func001
	add	esp, 12					; 0000000cH // 调用者将压栈参数弹出堆栈。
; Line 29
	mov	eax, DWORD PTR _a$[ebp]
	push	eax
	lea	ecx, DWORD PTR _c$[ebp]
	push	ecx
	call	_func002
	add	esp, 8
; Line 30
	mov	ecx, DWORD PTR __$ArrayPad$[ebp]
	xor	ecx, ebp
	call	@__security_check_cookie@4   // 大概是堆栈检查的调试功能。
	mov	esp, ebp  // 前面将esp保存到ebp中,这里恢复esp的取值,相当于丢弃了局部变量空间。
	pop	ebp
	ret	0
_main_call ENDP
_TEXT	ENDS
PUBLIC	_main
; Function compile flags: /Odtp
_TEXT	SEGMENT
_main	PROC
; Line 33
	push	ebp
	mov	ebp, esp
; Line 34
	call	_main_call
; Line 35
	xor	eax, eax   //eax存放函数返回值
	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END

汇编代码的核心是ESP、EBP的设计。

ESP是函数堆栈指针,每次PUSH减4,每次pop加4.

EBP是每个函数的基址指针,表示该函数的“起始堆栈”,可用户函数返回后恢复堆栈,类似盗梦空间的kick处理。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值