汇编语言程序设计 第一部分 基础知识 笔记 (学堂在线-张悠慧)
大部分都是老师讲的,如果侵权了,马上删除。仅作为个人学习参考。
极小部分是自己查资料所得,如有错误欢迎指正。
1 概述
1.1 关于本课程
课程定位
计算机系统的入门课
为后续课程打下指令集,汇编编程及微体系结构入门的基础
课程内容
-
基本知识
- 种类指令集初步
- 数制与整数表示
-
X86汇编
- 80x86计算机组成与保护模式
- X86指令系统与寻址方式
- X86汇编语言程式与基本编程
-
MIPS汇编
- MIPS计算机组织初步
- 指令系统介绍
- 汇编代码与异常处理
课程目标
- 了解汇编语言与计算机系统结构的关系及起到的作用
- 了解X86系列微处理器的指令系统及寻址方式,能编写程序掌握C语言基本代码段与汇编语言的对应关系
- 掌握MIPS指令集
参考书
深入理解计算机系统(Computer System:A Programmer’s Perspective)
SEE MIPS RUN (MIPS体系结构透视)
1.2 汇编语言概念
语言 | 特点 |
---|---|
机器语言 | 执行速度快 效率高 |
汇编语言 | 涉及硬件细节, 要求熟悉计算机系统的内部结构 |
高级程序语言 | 抽象程度更高 |
不同编程语言体现了对系统结构不同层面的"视角"
1.3 指令系统分类
- 计算机系统结构(狭义)Computer Architecture -> 程序员所看到的计算机系统属性
- 计算机组成 Computer Organization -> 计算机系统的逻辑实现
- 计算机实现 Computer Implementation. -> 计算机系统的物理实现
CISC(复杂指令系统,Complex Set Instruction Computer)
- 特点
- 面向高级语言,缩小机器指令系统与高级语言语义差距
- 指令条数多,寻址方式多变
- 单条指令功能相对复杂
- 代表:X86
- X86指令集的基本特色
- 向下兼容
- 变长指令:1-15字节,多数为2-3字节长度
- 多种寻址方式(可访问不对齐的内存地址)
- 通用寄存器个数有限
X86-32系统 8 个, X86-64系统16个 - 至多有一个操作数在内存中,另一个操作数为立即数或寄存器
RISC(精简指令系统,Reduced instruction set computer)
- 特点
- 通常只支持常用的能在一个周期内完成的操作(80:20原则)
- 简单而统一的指令格式
- 只有LOAD和STORE指令可以访问存储器,简单的寻址方式
- 较多的寄存器
- 指令条数相对较少,依赖于编译器产生高效的代码
- 处理器微体系结构相对简单,运行频率高
- 代表:MIPS/ARM/PowerPC
- MIPS指令集特点
- 以寄存器为中心(32个), 只有Load/store指令访问内存,所有的计算类型的指令均需要从寄存器堆中读取数据并把结果写入寄存器中
- MIPS32还定义了32个浮点寄存器
- MIPS32指令集的指令格式非常规整, 所有的指令长度一定,且指令操作码在固定的位置上
- 寻址方式非常简单, 每条指令操作简单
- MIPS32的指令格式只有3种:
- R(Register)类型的指令从寄存器堆中读取两个源操作数,计算结果,写回寄存器堆
- I(immediate)类型的指令使用一个16位立即数作为源操作数
- J(jump)类型的指令使用一个26位立即数作为跳转的目标地址(target address)
CISC和RISC互为借鉴,走向融合。兼容性考虑是指令集发展的关键性因素
1.4 整数的机器表示
数制、数制转换、逻辑运算
X86中 1word=2byte ; MIPS中 1word=4byte
逻辑运算记住符号
机器字
-
机器字(machine word)长
- 一般指计算机进行一次整数运算所能处理的二进制数据的位数,通常也包括数据地址长度
- 32位字长:地址的表示空间约是4GB
- 64位字长:地址的表示空间约是1.8X10^19 bytes,目前64位机器实际支持的是48位(就够用了)
-
机器字在内存中的组织
- 地址按照字节(Byte)来定位,从0开始,相邻机器字地址相差4或8
- 字节序
- Big Endian:Sun,PowerPC,Internet , 低位字节(Least signigicant byte,LSB)占据高地址
- Little Endian:x86 (低对底,高对高)
整数的机器表示(无符号数与带符号数)
- 原码、反码、补码
- C语言中基本数据类型的大小(in Bytes)
- 原码[-127, +127]
- 第一位是符号位
- 由于加法需额外考虑符号位,弃
- 反码[-127, +127]
- 负数除符号位,按位取反
- 由于正零负零问题,弃
- 补码[-128, 127]
- 负数除符号位,按位取反加一(反码加一,利用负零)
- 补码原理(补码如何统一加减运算/为什么按位取反再加一)
溢出等于取模,同余即是相等
https://blog.****.net/jiaobuchong/article/details/83188674
- C语言中基本数据类型的大小(in Bytes)
- 无符号数与带符号数的最大值和最小值
- 无符号与带符号转换(C中),二进制串不变,解释不同
- C语言中的无符号数与带符号数
- 默认带符号,除非有后缀U
- 混用,带符号默认转成无符号
是32位操作系统中最大的符号型整型常量
- 何时采用无符号数
- 模运算
- 按位运算
- 能不用,就不用
sizeof()返回unsigned
- 无符号数加法
注意溢出 - 有符号数补码加法的溢出
- 除以2^k
- 无符号数:逻辑右移
shrl $3,%eax - 带符号数:
- 非负数:算术右移
-
负数算术右移有舍入错误
若无进位:则无影响(被移出了)
若有进位:加一
- 无符号数:逻辑右移
- 练习
1.5浮点数的机器表示
IEEE浮点数标准
- 754标准
- 局限性:只能精确的表示X/2^k这类形式和的数据
- 计算机内存储方式
s(符号位) | exp域(阶码E) | frac域(尾数M,是一个位于区间[1.0,2.0)内的小数) |
---|
单精度:exp 8bits, frac 23bits, 共32bits
双精度:exp 11bits, frac 52bits, 共64bits
扩展精度: exp 15bits, frac 63bits, 共80bits(1 bit wasted)
- IEEE754浮点数的类型
- 规格化
- exp既不是全0,也不是全1
- E = exp - Bias(偏置量) <-为了表示正负
Bias = 2^{e-1} - 1, e = exp域的位数
Bias,单精度127,双精度1023 - frac是把M的第一位省去(M=1.xxxxx, frac=xxxx)
- 非规格化
- exp全0
- E = -Bias + 1
- M = 0.xxxxxx
- 用途
- exp=0 frac=0 表示0,浮点数有+0 -0
- exp=0 frac!=0 表示非常接近0的浮点数, Gradual underflow
- 一些特殊值
- exp全1
- 用途
- exp全1, frac=0, 表示无穷/数值溢出,有正无穷、负无穷
- exp全1, frac!=0, NaN
- 规格化
- 特点
- (几乎)可以使用无符号整数的比较方式
反例:符号位,+0/-0,NaN
其他情况都可:规格化vs非规格化, 规格化vs无穷
- (几乎)可以使用无符号整数的比较方式
Rounding(舍入)
- 基本流程
算出精确值,转化为所需精度(指数绝对值大会导致溢出,可能需要舍入) - 舍入模式
- zero,round down, round up, Nearest Even (default)
- 向偶数舍入,意味着最低有效数字为0(对于二进制)
C语言中的浮点数
- 单精度 float
- 双精度 double
- int(32), float, double.
double, float -> int ,尾数截断, 如果溢出或者浮点数是NaN则转换结果没有定义 - int->double, 能精确转换
- int->float(23),不会溢出,但是可能被舍入
1.6 X86体系结构初步
计算机系统
存储器-主存(main memory)
- 8bit为单位
- 每个字节单元有一个地址(0开始)
- 地址用二进制表示(无符号整数,写成16进制)
- 低对低,高对高(小端)
- 字单元地址用其低位地址表示
80X86处理器与保护模式
- 历史
- 8086与8086
芯片 推出 外数据总线 字长 意义 8086 1978 16位 16位 x86架构的鼻祖 8088 1979 8位 介于16位与8位之间的准16位微处理器 1980 IBM使用8088开发出16位微型计算机IBM-PC - 80186与80286
- 1982,80286,16条数据线,24条地址线相互独立,不再分时,可寻址16M地址空间
- 任务转换、存储管理、多种保护
- 80386(非常有代表性的32位微处理器)
- 1985,Intel第四代,32位微处理器。
- 内部由CPU,MMU,BIU组成
- 3种工作模式
- 实地址模式
相当于一个可进行32位快速运算的8086 - 虚地址保护模式
是80X86设计目标全部达到的工作模式,通过对程序使用的存储区采用分段、分页的存储管理机制,达到分级使用、互不干扰的保护目的。能为每个任务提供一台虚拟处理器,使每个任务单独执行,快速切换 - 虚拟8086模式
- 实地址模式
- 8086与8086
- 32位微处理器的寄存器
- 8个通用寄存器(32位)
%eax, %edx, %ecx, %ebx, %esi, %edi, %esp(栈顶指针寄存器), %ebp(动态基址指针) - 6个段寄存器(16位,其中13位代表内存段的一个编号,称为段选择器)
CS DS SS ES FS GS
- 8个通用寄存器(32位)
- 保护模式保护什么?
- 分清不同人物的存储区域,不允许随便使用其他任务的数据和代码
- 必要条件:
- 标记每段存储区的所有者或者被使用的权限级别
- 标记使用者是谁(权限级别)
- 中间环节: CPU要去判断此次访问是否合法
- 如何实现保护?
- 大致原理:
- 在X86-32体系保护模式下,内存地址由段基地址(32位)和偏移地址构成
- 每个段描述符(64位)由段基地址(32位):段长度(20位,段长度单位2^12):访问权限
- 由于后向兼容,段寄存器只有16位,如何塞下64位的段描述符?
-
通过描述符表:高13位作为索引访问该表(低两位表示使用描述符的特权级别)
-
GDT全局描述符表,存放os和各任务公用描述符(只有一个)
共用的数据和代码段描述符、各任务TTS(任务状态段)描述符和LDT描述符
GDT register (GDTR), 48bit 存放了GDT表的基本信息 -
LDT局部描述符表,存放各个任务的私有描述符(每个任务有一个)
-
- 具体流程:
- 大致原理: