C语言汇编查看笔记(一)

#include 

int sum(int x, int y){
	int t = x + y;
	return t;
}

int main(void){
	sum(1,2);
}

利用

gcc -S test.c

查看其汇编代码,我写了很多注释

	.file	"test1.c"
	.text
	.globl	_sum
	.def	_sum;	.scl	2;	.type	32;	.endef
_sum:
LFB13:
	;CFI全称是Call Frame Instrctions, 即调用框架指令。CFI提供的调用框架信息, 为实现堆栈回绕(stack unwiding)或异常处理(exception handling)提供了方便, 它在汇编指令中插入指令符(directive), 以生成DWARF可用的堆栈回绕信息。这里列有gas(GNU Assembler)支持的CFI指令符。
	.cfi_startproc	;函数开始
	;pushl %ebp和movl %esp,%ebp 这两步操作是个规范化步骤, 叫做前序(prologue), 它有两个作用 :
	;1.标记一个新的调用框架。保存前一个函数的调用框架的基址(旧的ebp), 使ebp指向当前函数的调用框架基址。
	;2.在函数的执行过程中, 函数的局部变量将会是在返回地址之下的区域开辟空间来存放, 由于ebp是固定的, 可以用它作标杆, 标示参数与局部变量的位置。比如第一个参数位于%ebp + 8, 第二个参数位于%ebp + 12。也正是这个原因, 参数采用从右到左传递, 对实现可变参数有利: 通过%ebp + 8获取第一个参数后, 可从中获知参数个数, 然后, 依次偏移, 即可获取各个参数。
	pushl	%ebp	;压栈保存ebp,设未压栈时栈顶指针的偏移地址为offset;此时offset-4
	.cfi_def_cfa_offset 8	;此处距离CFA地址为8字节,1.CFA(Canonical Frame Address)是标准框架地址, 它被定义为在前一个调用框架中调用当前函数时的栈顶指针。2.至于此处指的是esp寄存器指向的位置
	.cfi_offset 5, -8	;把第5号寄存器原先的值保存在距离CFA - 8的位置
	movl	%esp, %ebp	;栈顶指针传给ebp=offset-4
	.cfi_def_cfa_register 5	;该指令是位于movl %esp, %ebp之后。它的意思是: 从这里开始, 使用ebp作为计算CFA的基址寄存器(前面用的是esp)。
	subl	$16, %esp	;esp=offset-4-16=offset-20,这里只有两个局部变量, 且两者在x86上都分别是4字节, 按理说, 只要开辟8字节的空间即可, 这里却开辟了16字节。这是因为GCC的栈上默认对齐是16字节
	movl	8(%ebp), %edx	;edx赋值ebp+8=offset+4的地址的值
	movl	12(%ebp), %eax	;eax赋值ebp+12=offset+8的地址的值
	addl	%edx, %eax	;eax的地址offset+8赋值=eax的值+edx的值
	movl	%eax, -4(%ebp)	;ebp-4=offset-8的地址的值赋eax的地址的值
	movl	-4(%ebp), %eax	;eax的地址的值赋值ebp-4=offset-8的
	leave	;movl %ebp,%esp 和 popl %ebp 之后 栈顶指针esp地址为offset-4,esp出栈,和前序对应的尾声
	.cfi_restore 5	;现在第5号寄存器恢复到函数开始的样子
	.cfi_def_cfa 4, 4	;现在重新定义CFA, 它的值是第4号寄存器(esp)所指位置加4字节
	ret
	.cfi_endproc	;函数停止
LFE13:
	.def	___main;	.scl	2;	.type	32;	.endef
	.globl	_main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
LFB14:
	.cfi_startproc
	pushl	%ebp	;压栈ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp	;
	.cfi_def_cfa_register 5
	andl	$-16, %esp
	subl	$16, %esp
	call	___main
	movl	$2, 4(%esp)
	movl	$1, (%esp)
	call	_sum
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE14:
	.ident	"GCC: (MinGW.org GCC Build-20200227-1) 9.2.0"

这里我画了张图来总结这个C程序在栈中发生了什么
C语言汇编查看笔记(一)_第1张图片
另一种查看汇编代码的格式为

gcc -c test1.c
objdump -d test1.o

你可能感兴趣的:(汇编)