2017-2018-1 20179215《Linux内核原理与分析》第二周作业
20179215《Linux内核原理与分析》第二周作业
这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型、X86汇编指令包括几种内存地址的寻址方式和push、pop、call、re等几个重要的汇编指令。主要分为两部分进行这周的学习总结。第一部分对学习内容进行总结,第二部分对实验进行分析(反汇编一个C程序)。
一、学习内容
1、现在计算机绝大多数采用冯诺依曼体系结构,逻辑上可以抽象成:
以程序员的角度看:
2、几种寻址方式
• movl %eax,%edx edx=eax 寄存器寻址
• movl $0x123,%edx edx=0x123 立即寻址
• movl 0x123,%edx edx=*(int32_t)0x123 直接寻址
• movl (%ebx),%edx edx=(int32_t)ebx 间接寻址
• movl 4(%ebx),%edx edx=(int32_t)(ebx+4) 变址寻址
其中%..代表寄存器,$..代表取出数据,(%..)代表取出寄存器中所存储的数据,b、w、l、q分别代表8位、16位、32位和64位。
3、push、pop、call等几个重要的汇编指令。
eg (1) pushl %eax 意思是把eax寄存器压栈。分解来看相当于第一步:subl $4 esp,第二步:movl %eax (%esp),来解释一下:首先我们要知道esp是指堆栈栈顶,那么由于栈的一般生长方向为自上向下增长,进行push压栈指令时栈顶指针向下移动4个字节(因为是32位机),之后把eax放入当前内存位置。
(2) popl %eax意思是把eax寄存器出栈。分解来看相当于第一步: movl(%esp), %eax第二步:add $4 %esp,道理同(1)逆。
(3) call 0X12345 意思是函数调用,过程是首先将当前CPU获取内存的指令压栈保存,赋予新值,CPU下次就从新地址来取指令了,即实现了函数调用。
二、实验分析
首先创建main.c文件,即:touch main.c,之后用如下命令输入一段C语言代码:
$vi main.c,之后用gedit main.c 查看编写好的C程序,如下图所示:
然后用如下命令反汇编:$gcc -S -o main.s main.c -m32,之后用gedit main.c 查看结果,如下图所示:
由于“.”开头的大都是用于链接辅助信息,实际并不会执行,所以可以直接忽略。删除所有点开头的内容,留下来的是纯汇编代码。那么此段程序简化后就变成如下形式:
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $20, %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 $10, (%esp)
call f
addl $30, %eax
分析如下图:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!