第一章   计算机工作原理

1   存储程序计算机工作模型

     存储程序计算机的主要思想是将程序存放在计算机存储器中,然后按存储器中的存储程序的首地址执行程序的第一条指令,以后就按照该程序中编写好的指令执行,直至程序执行结束。

冯·诺依曼体系结构的核心是存储程序计算机。

2   x86-32汇编基础

    8086CPU中总共有14个16位的寄存器(AX、BX、CX、DX、SP、BP、SI、DI、IP、FLAG、CS、DS、SS和ES),然后对应也有32位的寄存器(EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI、EIP、EFlags、CS、DS、SS、ES、FS和GS)32位寄存器只是把对应的16位寄存器扩展到了32位,并且所有开头为E的存储器,一般是32位的。

要注意的是在16位的CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,但在32位的CPU中,32位寄存器EAX、EBX、ECX和EDX不仅可以传送数据、暂存数据保存算术逻辑运算结果,还可以作为指针寄存器,这些32位寄存器更具通用性。

以32位为主介绍一些常见的汇编指令:

寄存器寻址:movl %eax,  %edx;

寄存器寻址就是操作的是寄存器,不和内存打交道,%eax,其中%开头后面跟一个寄存器名称。上述代码的含义为把寄存器%eax的内容放到%edx中。

  立即寻址:movl $0x123,%edx

上述代码的意思是把0x123这个十六进制的数值直接放到EDX寄存器中。立即寻址也和内存没有关系。

直接寻址:movl 0x123,  %edx

上述代码的意思是把0x123内存地址所指向的那块内存里存储的数据放到EDX寄存器里。直接寻址就是用内存地址直接访问内存中的数据。

间接寻址:movl (%ebx),  %dx

间接寻址就是寄存器加个小括号。上述代码的意思是%ebx这个寄存器中存的值是一个内存地址,加个小括号表示这个内存地址所存储的数据,我们把它放到EDX寄存器中。

变址寻址: movl 4(%ebx),  %edx

代码中“(%ebx)”前面出现了一个4,也就是在间接寻址的基础上,在原地址上加上一个立即数4。

还有一点需要注意,一般说来,全是大写字母的一般是Intel汇编,全是小写字母的一般是AT&T汇编。在这里代码用到的寄存器名称都遵守AT&T汇编格式采用全小写的方式。

接下来介绍几个很重要的指令:pushl/popl和call/ret。

在AT&T汇编中,pushl等效于以下汇编指令:

 subl  $,  %esp  #把堆栈的栈顶ESP寄存器的值减4,因为堆栈是向下增长的
movl %eax, (%esp) #把EAX寄存器的值放到ESP寄存器所指向的地方

在AT&T汇编中,popl等效于以下汇编指令:

 movl  (%esp),  %eax  #把栈顶的数值放到EAX寄存器中
addl $, %esp #栈顶加4,相当于栈向上回退了一个存储单元的位置

在AT&T汇编中,call指令是函数调用,调用一个地址,例如call 0x12345等效于以下汇编指令:

 pushl   %eip  (*)  #把当前的EIP寄存器压栈
movl $0x12345, %eip (*) #把0x12345这个立即数放到EIP寄存器里

然后在这里要特别注意,上面的两个动作并不存在实际对应的指令,这里用“(*)”来特别标记一下,这两个动作是由硬件一次性完成的,而且出于安全方面的原因,EIP寄存器不能被直接使用和修改。

在AT&T汇编中,ret指令跟call指令相对应,是函数返回指令,ret等效于以下汇编指令:

 popl  %eip  (*)  #把当前堆栈栈顶的一个存储单元放到EIP寄存器中

同样这里的动作并不存在实际对应的指令,这个动作也是硬件一次性完成的。

3   汇编一个简单的C语言程序并分析其汇编指令执行过程

      输入ls命令可看到“Code”和“LInuxKernel”,因为目录“Code”按照“实验楼”的使用约定是保存用户编写代码的目录,所以进入“Code”目录下进行操作。

本次实验中用到的C语言代码为:

 // main.c
int g(int x)
{
return x + 4;
} int f(int x)
{
return g(x);
} int main(void)
{
return f(6) + ;
}

在命令行下输入" vi  main.c"命令打开文本编辑main.c文件,按"i"键进入输入状态,如下图所示:

接下来在文本编辑器VIM中按“Shift” + “:”进行文本编辑的命令模式,输入“wq”就可把代码保存到main.c中,并退出VIM编辑器,但是我遇到了一个问题就是在插入模式下按照前边操作是无效没有反应的,我的解决方案是:按ESC退出编辑模式,此时的模式为“NORMAL”模式,然后再输入冒号,接着输入“wq”,再按回车键即可,如下图所示:

然后使用gcc main.c命令编译main.c这个代码文件,这时会生成一个目标文件a.out,它是可执行的,但此时看不到任何信息,可以通过echo $?命令查看这个程序的返回值,该C语言程序的结果为11,如下图所示:

接着可以把main.c编译成一个汇编代码,可使用gcc -S -o main.s main.c -m32这个命令,如下图所示:

此时我们可以看到main.s汇编文件还有一些“.cfi_”打头的字符串以及其他以“.”打头的字符串,这些都是编译器在链接阶段所需的辅助信息,可以通过在VIM中输入“g/\.s*/d”命令删除所有以“.”打头的字符串简化main.s里的汇编代码,注意在这里VIM编辑器要在“NORMAL”模式下输入“:”,再输入“g/\.s*/d”命令,按回车键即可,如下图所示:

接着我介绍一下在上面main.s文件中新出现的汇编指令leave指令,还有与leave指令相对应的enter指令。

leave指令用来撤销函数堆栈,等价于下面两条指令:

 movl  %ebp,  %esp
popl %ebp

enter指令用来建立函数堆栈,等价于下面两条指令:

 pushl  %ebp
movl %esp, %ebp

最后对该C语言程序的汇编代码进行分析:

首先假定堆栈为空栈的情况下EBP和ESP寄存器都指向栈底,而且为了简化起见,我们为栈空间的存储单元进行标号,压栈时标号加1,出栈时标号减1,如下图所示:

下面是我的分析过程:

我在分析汇编代码时movl  8(%ebp),  %eax中的间接寻址产生了一个误区:我以为使用ESP寄存器变址寻址,是ESP寄存器向上移动两个标号,导致我后边的分析出了差错。后来翻看课本对间接寻址的定义,才知道是EBP寄存器存储的数值加8,ESP寄存器不移动。

4   总结

       在本次学习中,我通过课本,再一次回顾了存储程序计算机工作模型以及基本的一些的汇编语言,重点是再一次深入理解了函数调用堆栈相关汇编指令,如call/ret和pushl/popl,还有leave和enter,并通过自己动手实践将一个C语言代码程序在Linux环境下运行,同时反汇编C语言程序,最后自己分析了汇编代码是如何在存储程序计算机工作模型上一步步执行的。

2019-2020-2 20199317《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. 2019-2020-1 20199329《Linux内核原理与分析》第十三周作业

    <Linux内核原理与分析>第十三周作业 一.本周内容概述 通过重现缓冲区溢出攻击来理解漏洞 二.本周学习内容 1.实验简介 注意:实验中命令在 xfce 终端中输入,前面有 $ 的内容为 ...

  10. 2019-2020-1 20199329《Linux内核原理与分析》第十二周作业

    <Linux内核原理与分析>第十二周作业 一.本周内容概述: 通过编程理解 Set-UID 的运行机制与安全问题 完成实验楼上的<SET-UID程序漏洞实验> 二.本周学习内容 ...

随机推荐

  1. JavaSE语法

    二.JavaSE语法(上) 1.Java 有没有 goto 语句? goto 是 Java 中的保留字,在目前版本的 Java 中没有使用.根据 James Gosling(Java 之父)编写的&l ...

  2. (25)ASP.NET Core EF查询(复杂查询运算符、原生SQL查询、异步查询)

    1.复杂查询运算符 在生产场景中,我们经常用到LINQ运算符进行查询获取数据,现在我们就来了解下生产场景经常出现几种复杂查询运算符. 1.1联接(INNER JOIN) 借助LINQ Join运算符, ...

  3. elastalter邮件告警

    一:简介 ElastAlert是一个简单的框架,用于通过Elasticsearch中的数据异常警告,峰值或其他感兴趣的模式. 监控类型 "匹配Y时间内有X个事件的地方"(frequ ...

  4. 微软的分布式应用框架 Dapr

    微服务架构已成为构建云原生应用程序的标准,微服务架构提供了令人信服的好处,包括可伸缩性,松散的服务耦合和独立部署,但是这种方法的成本很高,需要了解和熟练掌握分布式系统.为了使用所有开发人员能够使用任何 ...

  5. Apache Spark 3.0 预览版正式发布,多项重大功能发布

    2019年11月08日 数砖的 Xingbo Jiang 大佬给社区发了一封邮件,宣布 Apache Spark 3.0 预览版正式发布,这个版本主要是为了对即将发布的 Apache Spark 3. ...

  6. Python OpenCV4趣味应用系列(四)---颜色物体实时检测

    今天,我们来实现一个视频实时检测颜色物体的小实例,视频中主要有三个颜色物体,我们只检测红色和绿色的球状物体,如下图所示: 第一步需要打开视频(或者摄像头): cap = cv2.VideoCaptur ...

  7. Linux系统中nc工具那些不为人知的用法

    Linux nc命令用法 参考地址:https://www.cnblogs.com/jjzd/p/6306273.html -g<网关>:设置路由器跃程通信网关,最多设置8个; -G< ...

  8. Python基础之JSON

    作用 对Python对象进行序列化,便于存储和传输 Python对象与JSON字符串相互转换 Python对象转JSON字符串 import json data = [ { 'a' : 1, 'b' ...

  9. pat 1120 Friend Numbers(20 分)

    1120 Friend Numbers(20 分) Two integers are called "friend numbers" if they share the same ...

  10. Apache Hudi 介绍与应用

    Apache Hudi Apache Hudi 在基于 HDFS/S3 数据存储之上,提供了两种流原语: 插入更新 增量拉取 一般来说,我们会将大量数据存储到HDFS/S3,新数据增量写入,而旧数据鲜 ...