计算机系统基础笔记(11)——程序的机器级表示

前言

跟前面的顺序有点不一样 因为在补笔记233

一、基础知识

(一)Intel处理器体系结构的历史

1.Intel x86系列处理器

  • 理论上CISC的性能很难与精简指令集计算机(RISC)相匹敌,但是Intel采用了CISC(CISC之前提过 指令多且格式复杂)
  • 向后兼容至8086处理器(诞生于1978年)
  • 进化的里程碑如下
    在这里插入图片描述
  • 新特性
    • 多媒体操作的指令支持
      提供了更加有效率的条件操作指令
      机器字长从32位变为64位
      多核

2.摩尔定律

  • 单位面积上可以容纳的晶体管数量
    几乎每两年增加一倍
    在这里插入图片描述

3.Core i7 Broadwell 2015

下面是CPU芯片
粉色的是内存
内存右边的是串形显卡
中间蓝色的BDW Core是八核
蓝色的LLC是高速缓存
左边浅蓝色的是网卡
网卡右边的DMA 和PCU是控制器
网卡下边的SATA是硬盘
左下角是时针
时针旁边是接口
右下角是集成I/O

在这里插入图片描述

4.X86兼容处理器:AMD

  • 历史上
    AMD仅仅跟随着Intel
    性能稍差,价格更便宜
  • 随后
    从DEC和其他业绩下降的公司招聘顶级电路设计师
  • 提出了Opteron架构:成为Pentium 4的有力竞争对手
    引入了x86-64架构,自主的扩展到64位体系结构
  • 近年来
    Intel重新迎头赶上,重新占据了半导体技术的世界主导地位
    AMD稍有落后,依赖外部的半导体代工厂

5.Intel 64位体系结构发展的历史

  • 2001年:Intel试图从IA32彻底转变为IA64

    完全不同的体系结构(安腾)
    ◼ 以legacy(传统)模式执行IA32的指令
    ◼ 性能令人失望

  • 2003年:AMD提出了体系结构进化的解决方案
    ◼ x86-64位体系结构(现称为AMD64)

  • Intel觉得有义务专注于IA64
    ◼ 难以承认技术路线的错误以及AMD方案更优
    Intel 64位体系结构发展的历史

  • 2004年:Intel提出了EM64T体系结构实现对IA32的64
    位扩展◼ 扩展实现了64位内存寻址技术
    ◼ 几乎与x86-64相同

  • 2019年:英特尔宣布放弃IA64架构

  • 除低端x86处理器外,其他处理器均支持x86-64
    ◼ 但是目前许多程序仍然在32位模式下运行

(二)C语言,汇编语言和机器语言

1.定义

  • 体系结构:(指令集体系结构,ISA)编写汇编代码时需要理解的处理器设计部分。
    ◼ 例如:指令集规范、寄存器组织

  • 微体系结构:体系结构的具体实现
    ◼ 例如:高速缓存大小、核心频率

  • 代码格式
    ◼ 机器语言:处理器可以直接执行的字节级的程序
    ◼ 汇编语言:文本形式的机器语言

  • 举例:常见的指令集体系结构
    ◼ Intel: x86, IA32, Itanium, x86-64
    ◼ ARM:几乎所有的移动电话中都使用

2.汇编语言/机器语言视角下的计算机

  • PC:程序计数器
    ◼ 存储下一条要执行指令的地址
    ◼ 在x86-64中的名称为 RIP
  • 寄存器文件
    ◼ 程序的数据会频繁地使用它来存储
  • 条件码
    ◼ 存储最近一次算术逻辑运算的状态
    信息
    ◼ 用于条件分支
  • 存储器
    ◼ 基于字节寻址的阵列
    ◼ 存储程序和用户数据
    ◼ 存储栈数据(以实现过程的支持)
    在这里插入图片描述

3.将C语言代码转换为机器语言

  • 代码文件:p1.c p2.c
  • 编译命令:gcc –Og p1.c p2.c -o p
    ◼ 使用基本的编译优化选项 –Og (最新版本GCC支持)
  • 将编译结果写入文件 p

在这里插入图片描述


下面是例子
这是C语言
在这里插入图片描述
这个是汇编语言
在这里插入图片描述

  • 使用下面的命令生成汇编语言
    ◼ 生成文件:sum.s
  • 警告:由于编译选项的不同和gcc版本的不同可能会得到不同的编译结果

4.汇编语言的特征

(1)数据类型
  • 整数:1、2、4或8字节的
    ◼ 数据的值
    ◼ 地址 (无类型的指针)
  • 浮点数:4、8或10字节
  • 代码:指令的字节序列编码
  • 没有聚合类型,例如:数组或结构体
    ◼ 这些在汇编语言中都都表现为在内存中连续分配的字节
(2)操作
  • 对寄存器或存储器数据执行算术/逻辑运算
  • 在寄存器和存储器间传输数据
    ◼ 将数据从存储器加载至寄存器
    ◼ 将寄存器的数据存储至存储器
  • 转移控制
    ◼ 无条件跳转 至/从 过程
    ◼ 条件分支

5.条件码(重点)

  • 汇编器
    ◼ 将 .s 翻译为 .o
    ◼ 对每条指令进行二进制编码
    ◼ 几乎是完整的可执行代码
    ◼ 缺少了不同文件的链接信息
    在这里插入图片描述

6.反汇编目标码

objdump –d sum

  • 反汇编器
    ◼ 将 t 的值存储至 dest 指向的地址
    ◼ 探索目标码的一个十分有用的工具
    ◼ 可以分析指令的编码序列
    ◼ 根据目标码重新生成汇编代码
    ◼ 可以对任何可执行程序文件和.o文件进行反汇编
  • 另一种反汇编方法: 使用gdb调试器
    ◼ 反汇编过程(函数)
    ◼ 反汇编从sumstore开始的的14个字节目标码
    反汇编后的汇编指令如图
    在这里插入图片描述
    目标码如图
    在这里插入图片描述

7.反汇编的条件

  • 任何可以解释为可执行代码的文件
  • 反汇编程序分析字节并重构为汇编代码

下面是一个机器指令的例子
这个是C代码
在这里插入图片描述
这个是汇编语言
在这里插入图片描述
这个是机器指令
在这里插入图片描述

二、基本操作

这节比较重要 会考

(一)x86寄存器

  • x86-64 寄存器
    ◼每个寄存器的低4/2/1字节
    都有唯一的标识(r开头的是64位 e开头的是32位 可以看到64位比32位多八个寄存器)
    在这里插入图片描述

在这里插入图片描述

  • IA32 (x86-32) 寄存器在这里插入图片描述
    让我们来逐个分析一下这些寄存器
  • eax 累加
  • ecx 计数器
  • edx 数据
  • ebx 基地址
  • esi 源操作数
  • edi 目标操作数
  • esp 栈顶指针
  • ebp 栈底指针

(二)数据移动指令(move)

1.汇编语言格式

  • [label :] [opcode] [operand 1] [, operand 2]
    [标号:] [操作码] [操作数1 ] [,操作数2 ]
  • 汇编例子: l1: movq $5 , %rax

2.移动数据(重点)

movq Source, Dest
◼ 操作数类型

  • 立即数整数常量
    ◼ 例如: $0x400, $-533
    Example: $0x400, $-533
    ◼ 和C语言中的常数类似,但需要加前缀 $
    ◼ 被编码为1、2、4或8个字节
  • 寄存器十六个整数寄存器之一
    ◼ 例如: %rax, %r13
    %rsp有特殊用途,通常不使用
    ◼ 其他寄存器在一些特殊的指令中也会有特殊用途
  • 存储器指向的内存中8个连续字节,由寄存器给出地址(指针)
    ◼ 一个简单的例子:(%rax)
    ◼ 有很多其他的“寻址模式”

3.move指令操作数几种组合

在这里插入图片描述
前面几个都好理解
最后一行的操作是

  • 先在寄存器组里面找到rax
  • 然后根据rax里面的地址找到相应的存储单元 取出操作数的地址
  • 再放到rdx寄存器中

4.数据格式(很重要)

记住后缀以及各类型的大小
在这里插入图片描述

5.几种简单的存储器寻址模式

  • 间接寻址 ® Mem[Reg[R]]
    Normal
    (R ) Mem[Reg[R]]
    ◼寄存器 R 指向了存储器的地址
    ◼和C语言中的指针作用相同
  • 基地址+偏移量寻址 D( R ) Mem[Reg[R]+D]
    D( R ) Mem[Reg[R]+D]
    ◼寄存器 R 指定了存储器区域的开始位置
    ◼常数 D 是偏移量

下面是例子 swap 函数分析
这是C代码
在这里插入图片描述
这是汇编代码
在这里插入图片描述
可以分析出来各寄存器里的变量:
在这里插入图片描述
在这里插入图片描述
一开始是这样的
在这里插入图片描述
然后执行第一条指令movq (%rdi), %rax # t0 = *xp
在这里插入图片描述
接着执行第二条指令movq (%rsi), %rdx # t1 = *yp
在这里插入图片描述
movq %rdx, (%rdi) # *xp = t1
在这里插入图片描述

movq %rax, (%rsi) # *yp = t0

在这里插入图片描述

6.完整的存储器寻址模式(重要)

  • 最通用的形式D(Rb, Ri, S)Mem[Reg[Rb] + S * Reg[Ri] + D]
    ◼D:常数偏移量,可以为 1,2,4或8字节整数
    ◼Rb:基地址寄存器16个寄存器之一
    ◼Ri:变址寄存器,除%rsp外的其他寄存器
    ◼S:比例因子:可以为1,2,4或8 (为什么是这些数字?)(因为地址是跳跃的 与数据类型有关)

  • 一些特殊形式
    Special Cases
    (Rb, Ri) Mem[Reg[Rb] + Reg[Ri]]
    D(Rb, Ri) Mem[Reg[Rb] + Reg[Ri] + D]
    (Rb, Ri, S) Mem[Reg[Rb] + S * Reg[Ri]]

(三)算术、逻辑运算指令

1.地址计算指令

leaq Src, Dst

  • Src是寻址模式表达式
    ◼ 将表达式计算的地址写入Dst
  • 用途
    ◼ 计算地址(计算过程中不需要引用存储器)
    ◼ p = &x[i]
    ◼ 计算模式为 x + k*y的表达式
    ◼ k = 1, 2, 4, or 8

下面是例子
在这里插入图片描述
这是汇编代码(所以地址计算也可以用于计算x + k*y的表达式)
在这里插入图片描述

2.一些算术运算指令在这里插入图片描述


下面是例子
这是C代码
在这里插入图片描述
这是汇编代码
其中leaq: 地址计算
salq: 左移
imulq: 乘法
在这里插入图片描述
各寄存器中的情况
在这里插入图片描述
不同的颜色对应不同的代码
在这里插入图片描述
我们可以发现

  • 指令顺序和C语言语句顺序不同
  • 一些表达式需要由多条指令组合实现
  • 一些指令可以实现多个表达式的功能
  • (x+y+z)(x+4+48y)可以得到相同的汇编代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值