本周着重学习了汇编指令,并通过反汇编C程序了解栈帧变化。

实践

看了孟老师的演示视频后,我重新写了C程序,如下:

 int main()
{
int a=1,b=2;
return g(a,b);
}
int g(int x,int y)
{
return x+y;
}

通过 gcc –S –o main.s main.c -m32反汇编,删除不需要的信息:

main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $1, 24(%esp)
movl $2, 28(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl 24(%esp), %eax
movl %eax, (%esp)
call g
leave
ret
g:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax
popl %ebp
ret

在分析汇编程序执行的过程时,我想对自己的分析进行验证(例如每一步是否esp,ebp所在位置是否与我分析的一致),于是我想到了用调试的方法。在阅读课本18章时我知道了调试需要使用gdb。通过 gcc –g –o main main.s -m32生成main可执行程序,然后开始调试:

可以看出ebp值为0x0,esp值为0xffffd4ac,eip值为0x80483ed,是main函数的第一条指令pushl %ebp,初始栈空间大致如下:

执行以下两条指令:

pushl	%ebp
movl %esp, %ebp

此时ebp和esp的值均为0xffffd4a8,存放的是ebp原来的值0x00000000,栈空间大致如下:

andl	$-16, %esp

可以看出esp减少了8个字节,栈空间大致如下:

subl $32, %esp为局部变量预留空间,栈空间如下:

movl	$1, 24(%esp)
movl $2, 28(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl 24(%esp), %eax
movl %eax, (%esp)

将1,2分别放到esp指地址向高地址分别偏移24、28个字节处,再将其分别赋给eax,eax再将值放到esp指地址向高地址偏移4个字节以及esp所指地址处(注:esp值没有变),栈空间大致如下:

**思考:

(1)此处为什么要把1和2两次存入空间?**

我将原代码改为:

 int main()
{
int a=1,b=2;
return a+b;
}

编译后:

去掉函数调用后,确实少了参数第二次入栈,这让我想到了函数调用中的实参和形参,第二次入栈的可能是形参x和y,但现在还不能确定(后面的分析可以解决)。

(2)第二次入栈中,为什么先入“2”后入“1”?

   参考为什么函数入栈顺序从右往左

call指令将下一条要执行的leave指令的地址0x0804841a压入栈,esp加4值为0xffffd47c,调试结果及栈空间如下:

进入g函数,前两条指令同上,即将旧的ebp压入栈,并将ebp移到esp所指位置:

movl	12(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax

三条指令完成了1+2,此时eax里的值为3:

这里所使用的“1”和“2”是8(%ebp)和12(%ebp)中的,即是第二次入栈的,它们参与的是g函数的运算,因此可以确定二者是形参。

popl %ebp 指令执行后,恢复ebp,此时esp的值为main函数的leave指令:

ret相当于执行popl %eip,从g函数返回main函数:

leave指令相当于

movl %ebp,%esp popl %ebp

ret后:

附表(每一条指令执行后eip,ebp,esp,eax,edx的值):

操作结束后我发现很多函数调用中都有leave指令,自己实践的g函数却没有,那是怎么回到main函数的呢?分析后我发现g函数没有增加变量,所以不用再次分配空间,ebp和esp所指位置相同,这和增加变量后分配空间,用leave指令的第一步movl %ebp,%esp 将esp移回栈顶同理,故g函数只有leave指令的第二步。这加深了我对leave指令的理解,既然分配空间要用leave,那leave指令便有将栈中为函数预留空间“收回”的功能。

未解决问题

  经过搜索后知道andl $-16, %esp命令是为了实现地址对齐的填充数据,但为什么在实践中esp减少了8个字节而不是16个字节?

小结

1.通过本周学习,对本科所学的数据结构中的栈有了更深刻的认识,每个栈帧对应着一个未运行完的函数,栈帧中保存了该函数的返回地址和局部变量;

2.以前学习C语言只知道写出程序能够实现功能就可以了,现在初步了解写出的语言转化为汇编语言如何在计算机中运行(如:实参、形参、返回、调用到底如何实现);

3.计算机体系结构中的中断时保存现场和pushl $eip有异曲同工之处。

2017-2018-1 20179202《Linux内核原理与分析》第二周作业的更多相关文章

  1. 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303第二周作业 1.汇编与寄存器的学习 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中 ...

  2. 20169219 linux内核原理与分析第二周作业

    "linux内核分析"的第一讲主要讲了计算机的体系结构,和各寄存器之间对数据的处理过程. 通用寄存器 AX:累加器 BX:基地址寄存器 CX:计数寄存器 DX:数据寄存器 BP:堆 ...

  3. 2019-2020-1 20199314 <Linux内核原理与分析>第二周作业

    1.基础学习内容 1.1 冯诺依曼体系结构 计算机由控制器.运算器.存储器.输入设备.输出设备五部分组成. 1.1.1 冯诺依曼计算机特点 (1)采用存储程序方式,指令和数据不加区别混合存储在同一个存 ...

  4. Linux内核原理与分析-第二周作业

    写之前回看了一遍秒速五厘米:如果

  5. Linux内核原理与分析-第一周作业

    本科期间,学校开设过linux相关的课程,当时的学习方式主要以课堂听授为主.虽然老师也提供了相关的学习教材跟参考材料,但是整体学下来感觉收获并不是太大,现在回想起来,主要还是由于自己课下没有及时动手实 ...

  6. 2019-2020-1 20199314 <Linux内核原理与分析>第一周作业

    前言 本周对实验楼的Linux基础入门进行了学习,目前学习到实验九完成到挑战二. 学习和实验内容 快速学习了Linux系统的发展历程及其简介,学习了下的变量.用户权限管理.文件打包及压缩.常用命令的和 ...

  7. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  8. 2020-2021-1 20209307 《Linux内核原理与分析》第九周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第九周作业> 这个作业的目标 & ...

  9. 20169212《Linux内核原理与分析》课程总结

    20169212<Linux内核原理与分析>课程总结 每周作业链接汇总 第一周作业:完成linux基础入门实验,了解一些基础的命令操作. 第二周作业:学习MOOC课程--计算机是如何工作的 ...

  10. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

随机推荐

  1. sourceTree的下载与安装

    一. SourceTree是什么? 一个拥有可视化界面的项目版本控制的软件,适用于git项目管理,在window和mac均可使用. 二. SourceTree下载 下载地址:SourceTree官网 ...

  2. ASP.NET Core的身份认证框架IdentityServer4--IdentityServer相关文章【记录】

    Identity Server 4 预备知识 -- OpenID Connect 简介: 原文地址

  3. Chrome工具使用

    (1) Chrome插件的使用 本来还想说FQ了,结果实验半天没成功,最后才知道公司已经邮件通知了,郁闷,FQ后我把我的插件重新装了一遍,觉得好像又懂了好多,记载下来我装的一些东西和有关PostMan ...

  4. 百度搜索URL中的参数都是什么

    最近,点石排名更新了一个新功能——站内搜索.其实理解起来也很简单,就是通过URL限定搜索结果为某个网站,从而参与点击(例如:https://www.baidu.com/s?wd=SEO&si= ...

  5. low逼三人组、nb二人组、归并、希尔排序----小结

  6. javascript 中的 this 关键字详解

    1.javascript 中 什么是 this? this 指的是当前行为执行的主体,或者是当前方法执行的主体 context:是当前行为或者方法执行的环境 实例: xx 去北京饭店吃东西:上下文是“ ...

  7. Unity MMO 参考数值

    贴图格式: iOS :RGBA 32 (pvrtc 4 ) Android : RGB Compresed ETC 4 或 RGBA 32  . DrawCall: 总计Drawcall 平均 100 ...

  8. 深入理解C指针----学习笔记

      深入理解C指针     第1章 认识指针   理解指针的关键在于理解C程序如何管理内存,指针包含的就是内存地址.     1.1 指针和内存   C程序在编译后,以三种方式使用内存: 1. 静态. ...

  9. 14个最常见的Kafka面试题及答案【转】

    原创 IT168企业级 2017-08-21 17:40 本文为您盘点了14个最常见的Kafka面试题,同时也是对Apache Kafka初学者必备知识点的一个整理与介绍. 1.请说明什么是Apach ...

  10. nfs挂载无法卸载

    故障现象:今天发现服务器的upload负载很高,到18左右,同时df查看磁盘命令卡住 用top\vmstat\iostat查看并未发现可以服务或进程. 上网查发现可能是nfs问题. 卸载nfs挂载的方 ...