How the Computer Works (based on X86/Linux)

注明

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

一、实验过程

首先创建一个C语言文件

vi main.c

接着编写一段C语言代码

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

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

int main(void)
{
  return f(6) + 1;
}

结束保存并退出

shift+:
wq

利用gcc的功能,将上面的代码编译成32位的汇编代码

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

这样就将main.c编译成main.s文件,如下图

bwlq分别代表8位、16位、32位和64位,而这里的指令是以l结尾,说明该文件内容的确是32位的汇编代码。
将所有以点开头的内容删除,留下来的就是纯汇编代码。

二、汇编分析

分析前先顺便明白以下知识:
1. EIP:Instruction Pointer 是如同指针一样指向内存的某一块区域,E开头则是因为为32位的系统
2. 堆栈是计算机中非常基础性的东西
3. CPU在实际取指令时根据CS:eip来准确定位一个指令
4. 寄存器模式,以%开头的寄存器标示符
5. 立即数是以$开头的寄存器标志符
6. 直接寻址:直接访问一个指定的内存地址的数据
7. 间接寻址:将寄存器的值作为一个内存地址来访问内存
8. 变址寻址:在间接寻址的时候改变寄存器的数值
9. Linux内核使用的是AT&T汇编格式
10.eip寄存器不能被直接修改,只能通过特殊指令间接修改
11.函数调用堆栈是由逻辑上多个堆栈叠加起来的
12.函数的返回值默认使用eax寄存器储存返回给上一级函数

设执行前的栈如图所示,esp与ebp均为0








从代码里的行数分析:

18-19:(main开始) 入栈 一 = ebp0,esp下移0→1,ebp下移0→1

20:esp下移1→2

21:二 = 6

22:三 = eip(23),esp下移2→3,eip跳转到f(第8行)

9-10:入栈 四 = ebp1,esp下移3→4,ebp下移1→4

11:esp下移4→5

12:变址寻址,eax = 6

13:五=6

14:六=eip(15),esp下移5→6,eip跳转到g(第1行)

2-3:入栈 七=ebp4,esp下移6→7,ebp下移4→7

4:变址寻址,eax=6

5:eax=eax+32=38

6:出栈 ebp上移7→4,esp上移7→6

7:esp上移6→5,eip(15)

15:执行leave,esp上移5→4,ebp上移4→1,esp再上移4→3

16:esp上移3→2,eip(23)

23:eax=eax+1=39

24:执行leave,esp上移2→1,ebp上移1→0,esp再上移1→0

25:ret,结束

可看出栈的执行情况如下,最后经过了从入栈到出栈的过程,eax的值为39


一 = ebp0


二 = 6


三 = eip(23)


四 = ebp1


五 = 6


六 = eip(15)


七 = ebp4

三、总结

没学过汇编和操作系统原理直接学Linux内核分析的确比较吃力,还好坚持下来和做完作业与测试。
希望能再接再厉,继续深入了解。

时间: 2024-11-03 20:53:29

How the Computer Works (based on X86/Linux)的相关文章

VELT-0.1.6开发:在VS2013下用QEMU调试x86 Linux内核

快乐虾 http://blog.csdn.net/lights_joy/(QQ群:Visual EmbedLinux Tools 375515651) 欢迎转载,但请保留作者信息 VELT的全称是Visual EmbedLinuxTools,它是一个visual studio插件,用以辅助完成Linux开发.利用这个插件,将可以在visualstudio的IDE中进行Linux应用程序的开发(包括编译和调试),也可以进行uboot和linux内核的编译和调试,并根据编译时的错误信息正确定位到源码

Vs2012在Linux开发中的应用(13): 添加对x86 Linux的支持

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 因为马上要进入Debugger的研究,为了方便对GDB的学习,先添加对虚拟机中的x86 linux的平台支持.按照先前的做法,很容易就看到结果了: 突然发现,原来的修改注册表似乎并不是必须的!! 在交叉编译器参数中直接留空: 看编译结果: 搞定!!! 

X86 Linux 下 SIGBUS 总结

SIGBUS 在 x86 Linux 上并不多见,但一旦出现,其调用堆栈常常让人摸不着头脑,加之信号问题各平台系统间差异较大,更让人难以理清,这里稍微总结一下 x86 Linux 上大概有哪些情形会触发 BUS ERROR. 文件映射访问异常 这是 SIGBUS 在用户态最为常见的场景,也最容易触发,通常来说根本原因都是进程 mmap 了一个文件后,另外的进程把这个文件截断了,导致 mmap 出来的某些内存页超出文件的实际大小,访问那些超出的内存页就会触发 SIGBUS,具体来说有以下几种场景:

Linux 内核分析 之一:How Computer Works 实验

说明 欧长坤 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 这学期学校恰好有操作系统的课程,上个学习就开始寻思研究研究Linux内核代码,恰好MOOC有这个课程,遂选了此课. 一.实验过程首先,我们将C语言代码利用编译器编译成汇编代码,下面是C语言代码: int g(int x) { return x + 999; } int f(int x) { return g(x); } int

随想录(在x86 linux上仿真多核cpu运行)

[ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 搞过嵌入式开发的朋友都知道无论在实际环境还是在fpga上调试代码是一件非常辛苦,同时吃力不讨好的事情.一方面芯片的片上资源少,另外一方面就是除了软件之外你还要处理各种意外的硬件事故.好一点的公司可能还会提供虚拟机来调试,但很多时候虚拟机的稳定性也是一个问题.搞过skyeye的朋友应该比较有体会. 其实,如果调试驱动代码或者cpu boot代码,那么毫无疑问应该在实际环境上开发.但是如果开发的

【翻译mos文章】Linux x86 and x86-64 系统中的SHMMAX最大值

Linux x86 and x86-64 系统中的SHMMAX最大值 参考原文: Maximum SHMMAX values for Linux x86 and x86-64 (文档 ID 567506.1) 目标: 问题1:32-bit (x86) Linux system 系统中的最大值? 问题2:64-bit (x86-64) Linux system系统中的最大值? 解决方案: 答案1: Oracle Global Customer Support 官方推荐 SHMMAX 的最大值是小于

【翻译mos文章】Linux x86 and x86-64 系统SHMMAX最大

Linux x86 and x86-64 系统SHMMAX最大值 参考原始: Maximum SHMMAX values for Linux x86 and x86-64 (文件 ID 567506.1) 目标: 问题1:32-bit (x86) Linux system 系统中的最大值? 问题2:64-bit (x86-64) Linux system系统中的最大值? 解决方式: 答案1: Oracle Global Customer Support 官方推荐 SHMMAX 的最大值是小于4G

linux init-&gt;upstart-&gt;systemd

http://en.wikipedia.org/wiki/Init init From Wikipedia, the free encyclopedia This article is about the Unix process. For the pre-Mac OS X extension mechanism, see Extension (Mac OS). Version 7 Unix: /etc listing, showing init and rc Version 7 Unix: c

Linux日知录(常用问题笔记)

http://blog.csdn.net/yizhu2000/article/details/70688420)序言 日有一知,当有一录,自09年来,工作所需,接触开源平台,对Linux常有涉猎,其间问题,记录在案,虽为敝帚,不敢自珍,所记条目,并未严格整理,但愿于后来者有所裨益. 1)常用 查看某个命令的路径 which:查看某个命令的路径,该命令在PATH变量配置的路径中寻找命令,并给出第一个查询结果返回 查看用户信息的几种方法 finger id groups 删除目录 果目录为空,可以用