Linux内核分析:实验一

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

 

现在的计算机大多数采用的是“冯.诺依曼”体系结构,即采用存储程序的核心思想。它是将指令和数据通通存放在内存中,有eip(rip)指定下一条执行指令的地址。 在计算机底层,指令以二进制的方式被读取执行。但由于二进制指令对于人来说很难读懂,故而采用汇编语言这一和二进制之间简单映射又容易被理解的语言,帮助人们理解计算机底层的指令执行过程。 实验给出的源码如下:

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

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

int main(void)
{
        return f(12) + 19;
}

然后使用下面的这个命令:

gcc -S -o main.S main.c -m32

将C源码以32位机器的指令格式编译成汇编语言如图2:

我们可以看到在汇编代码中,每个函数的开头都是:

pushl    %ebp
movl    %esp, %ebp

这是例程的序幕工作:它将EBP压如栈中,然后把ESP复制到ebp中,使其成为新的指针。这样可以保证后面的寻址都是根据EBP为基址进行寻址。

接下来在main函数中:

subl      $4, %esp
movl    $12, (%esp)

第一句是将栈顶向下增长4,开辟一块新的空间; 第二句是将立即数12放到ESP所指向的存储空间;

然后是调用函数f

在f函数中,同样是进行了前两句的准备工作

subl            $4, %esp
movl    8(%ebp), %eax
movl    %eax, (%esp)

第一句是将栈顶向下增长4,开辟一块新的空间; 然后将EBP向上增长4的位置的存储内容给eax,也就是main函数中刚刚所存储的12给eax然后又把12存储带当前栈顶位置;

然后是调用函数g;

movl    8(%ebp), %eax
addl        $19, %eax
popl        %ebp

由于函数调用以及准备工作将栈顶又向下移了2个位置所以第一句将EBP向上移动8的位置的值给eax;然而那个位置存储的是12;所以在执行完第二句之后eax的值就成了12+19 = 31.然后EBP出栈,这句话之后EBP就变成了调用g函数之前的值,相应的esp也要减4。

下面的return语句,将esp的值+4,然后eip指向f函数中调用g函数的下一条指令leave,而leave指令相当于下面两条指令:

Movl        %ebp,%esp
Popl         %ebp

执行完第一句之后,就将之前存的12弹出栈,然后第二句执行完之后,EBP从函数f的基址变为了main函数的基址; Return执行完之后,esp向上移动4个位置,指向存储eip的存储单元,这个eip指向的事调用f的下一条指令,即

addl            $19, %eax

此时eax的值为19+31 = 50.然后继续执行完后面的语句,EBP和esp变为执行main函数前的原始值。

总结:

1、通过分析以上步骤,使我深刻认识到计算机底层执行指令时的流程及栈的操作; 2、也让我明白了C语言和汇编语言之间的转化关系。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值