前言
本文介绍8086的汇编语言语法(注意不是80x86,是8086),旨在通过8086(16位)汇编,去了解Intel的汇编,从而达到阅读基于80386(32位)的 Linux 0.11 内核源码中汇编代码的目的,点到为止,不去深究Intel的其他汇编指令。
参考书目:
1992 杨季文《80x86汇编语言程序设计教程》
1998 杨季文《80x8汇编语言程序设计教程》
2008 王 爽《汇编语言_第2版》
2012 李 忠《x86汇编语言-从实模式到保护模式》
一. 基础知识
1.1 CPU寻址空间的概念
PC机中各类存储器的逻辑连接:
CPU将各类存储器看做一个统一的逻辑存储器:
1.2 段的概念
内存并没有分段,段的划分来自于CPU,即来自于程序员的定义。物理地址 = 基底址(段地址x16) + 偏移地址
也即物理地址 = cs * 16 + ip
。有两点需要注意:一个段的起始地址一定是16的倍数,因为段地址x16必然是16的倍数;一个段的长度被限制为64KB,因为偏移地址寄存器为16位,16位最大寻址范围为64KB。
1.3 补码的概念
二. 寄存器
8086有14个16位寄存器:
分类 | 寄存器 | 英文展开 | 说明 |
---|---|---|---|
通用 数据 寄存器 | ax | Accumulator | 累加寄存器; 两个独立的8位寄存器 ah、al |
bx | Base | 基底址寄存器; 两个独立的8位寄存器 bh、bl | |
cx | Counter | 计数寄存器,用于存放循环次数; 两个独立的8位寄存器 ch、cl | |
dx | Data | 数据寄存器; 两个独立的8位寄存器 dh、dl | |
段 寄 存 器 | cs | Code Segment | 代码 段寄存器 |
ds | Data Segment | 数据 段寄存器 | |
ss | Stack Segment | 堆栈 段寄存器 | |
es | Extra Segment | 附加 段寄存器 | |
堆栈 寄存器 | sp | Stack Pointer | 堆栈指针寄存器 |
bp | Base Pointer | 基指针寄存器 | |
变址 寄存器 | si | Source Index | 源变址寄存器 |
di | Destination Index | 目的变址寄存器 | |
控制 寄存器 | ip | Instruction Pointer | 指令指针寄存器 |
PSW | Program Status Word | 程序状态字寄存器(flag寄存器),不会被程序员显式调用 |
三. 汇编指令
注: ①8086汇编指令和寄存器名不区分大小写。
汇编语言由以下3类指令组成:
① 汇编指令:机器码的助记符,有对应的机器码。
② 伪指令:没有对应的机器码,由编译器执行,计算机并不执行。
③ 其他符号:如+ - * / 等,由编译器识别,没有对应的机器码。
那么问题来了,标号属于上述分类的哪一类呢?
1. 数据传送指令
除 SAHF 和 POPF 指令外,这组指令对各标志位没有影响。
1.1 传送指令
MOV DST, SRC
1.2 交换指令
1.3 地址传送指令
1.4 堆栈操作指令
1.5 标志传送指令
1.6 查表指令
1.7 输入输出指令
- 通用传送类指令
mov dst, src
注:
① dst(destination)和 src(source )的位数要一致。
② 存储单元不能传送到传送单元。
③ 段寄存器不能传送到段寄存器;cs 代码 段寄存器不能做为 dst;立即数不能传送到段寄存器。
④ 对于变量而言,加不加[]
都表示取值;对于寄存器而言,有[]
表示取地址,无[]
表示取值。
⑤mov
指令不会影响标志位。 - 取有效地址指令
lea reg16, mem !指令含义:load effective address,取源操作数的偏移地址,并将其传送到目的操作数单元。
① 目的操作单元一般为16位寄存器。
② 对于变量而言,加不加[]
都表示取地址;对于寄存器而言,与mov
相反有[]
表示取值,无[]
表示取地址。
在进行数据传送或运算时,要注意指令的两个操作对象的位数应该是一致的
mov ax, 18 //将立即数18送入寄存器ax,高级语言描述:ax = 18
mov ax, 4E20h //将16进制立即数4E20h送入寄存器ax,高级语言描述:ax = 4E20h
mov ax, bx //将寄存器bx中的数据送入ax,高级语言描述:ax = bx
mov ah, 78 //将立即数78送入寄存器ah,高级语言描述:ah = 78
add ax, 8 //将寄存器ax中的数值加上8,高级语言描述:ax = ax + 8
add ax, bx //将ax和bx中的数据相加,结果存放在ax中,高级语言描述:ax = ax + bx