c程序是如何跑起来的?

王涵宇  原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

计算机是什么?

我们所说的计算机,总体上概括基本上都在冯-诺依曼的框架之内,那么只能存储01的电路版,芯片是怎样实现复杂的功能呢?

实际上0和1能做许多事情,冯诺依曼的体系结构正是把这种朦胧的"材料"分化清晰,它为代码,数据,指令划分了明确的界限,由此有了计算机的初步印象:

cpu的ip寄存器通过总线指向内存的代码段,从里面取指令,内存保存指令和数据,cpu负责执行。


第一个实验:反汇编简单c代码并做分析

0~

知识储备:

最基本常用指令

movl %eax,%edx 把eax的值赋值给edx
movl $0x123,%edx 把绝对数值放到寄存器里
movl 0x123,%edx edx=*(int32_t*)0x123;把这个地址里放的值放到寄存器中
movl (%ebx),%edx edx=*(int32_t*)ebx
movl 4(%ebx),%edx edx=*(int32_t*)(ebx+4)
操作堆栈指令(:后面是方便理解的步骤,实际上程序员不能这样操作)
pushl %eax  :subl $4,%esp
movl %eax,(%esp)
popl  %eax  :movl (%esp),%eax
addl $4,%esp
call 0x12345 :pishl %eip //保存当时的eip
movl $0x12345,%eip
ret :pop %eip
leave :movl %ebp,%esp
popl %ebp


1~写一段c代码,保存为main.c,主要目的是为了展现栈的嵌套

int g(int x)
{
  return x + 2;
}

int f(int x)
{
  return g(x);
}

int main(void)
{
  return f(5) + 2;
}

2~.在实验楼的linux客户端输入gcc -S -o main.s main.c -m32,来反汇编

3~.打开main.s



4~.做分析

删掉main.s的冗余代码,主要代码是这样的

g:
	pushl	%ebp
	movl	%esp, %ebp
	movl	8(%ebp), %eax
	addl	$2, %eax
	popl	%ebp
	ret
f:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$4, %esp
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	g
	leave
	ret
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$4, %esp
	movl	$5, (%esp)
	call	f
	addl	$2, %eax
	leave
	ret
%ebp,%esp理解成指针指向运行栈的位置,每一个栈在运行之前通过push %ebp,movl %ebp,%esp两个操作开辟新空间,保存旧的空间

(%esp)理解成指针指向的内存单元(4字节),用笔在纸上划一个栈,跟着一步一步走,也就不难理解栈的巧妙之处了。

如下...(图很丑,理解大意..)



经过画图,这段代码在栈上执行了开辟栈和回收栈,把结果9放到eax中
栈的关键在于ebp和esp,esp用于开辟新的栈空间,而ebp用来保存每次执行完之后上一次栈的栈顶,push和pop正是完成此操作的关键
call和ret则是针对eip的“保存”,保证了eip恢复当前到执行指令的下一条(比如执行完f之后回到main)
leave还原栈上一次的样子

5~.小结

通过实验复习了栈的嵌套调用(上学期病毒课学过一点),计算机运算的奥秘就在于寄存器(快速运算),栈(能够保存现场)

可以说没有栈就不会有c程序等高级语言,我们现在还在操作寄存器而编程...











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值