学习参考资料:《汇编语言》(第三版)清华大学出版社 王爽著
总线
地址总线的宽度决定CPU的寻址能力。一个CPU有N根地址总线,最多可以寻找2N内存单元(B)。
例如:地址总线宽度分别为16根、20根、24根、32根的CPU,寻址能力分别为:64KB,1MB,16MB,4GB.
数据总线的宽度决定CPU与其他器件进行数据传送时的一次数据传送量。一个CPU有N根数据总线,一次可传送一个N位二进制数据。
例如:数据总线宽度分别为8根、16根、32根的CPU,一次可以传送的数据分别为:1B,2B,4B.
控制总线的宽度决定CPU对系统中其他器件的控制能力。有多少根控制总线,意味着CPU提供了多少种对外部器件的控制。
寄存器
8086CPU有14个寄存器:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。都是16位的。
通用寄存器
AX、BX、CX、DX
常用来存放一般性的数据。每个都能存储一个16位的数据,也可以分成两个独立的8位寄存器使用,如AX可以分成AH和AL。高8位构成AH,低8位构成AL。
寄存器 | 寄存器中的数据 | 表示的值 |
---|---|---|
AX | 0100111000100000 | 20000(0x4E20) |
AH | 01001110 | 78(0x4E) |
AL | 00100000 | 32(0x20) |
在8086CPU中,只有BX、SI、DI、BP这四个寄存器可以用在“[…]”中来进行内存单元的寻址。这四个寄存器可以单独出现,或只能以四种组合出现:BX和SI,BX和DI,BP和SI,BP和DI。而只要在“[…]”中使用BP且没有显性给出段地址,段地址默认在SS中。
段寄存器
CS、DS、SS、ES
8086CPU访问物理内存时,地址加法器采用物理地址=段地址*16+偏移地址的方法用段地址和偏移地址合成物理地址。
本质上的寻址模式是物理地址=基础地址+偏移地址。
CS是代码段寄存器,IP是指令指针寄存器。8086CPU从内存CS*16+IP单元开始读取指令并执行,即CPU将CS:IP指向的内容当作指令执行。读取一条指令后,IP中的值会自动增加所读取指令的长度,从而指向下一条指令。
修改CS和IP寄存器可以使用jmp指令,形如“jmp CS:IP”。
DS通常存放要访问的数据的段地址。比如读取0x10000单元的内容。
// Read 0x10000 to al
mov bx, 0x1000
mov ds, bx
mov al, [0]
“[address]”表示一个内存单元,当中的address表示偏移地址,执行指令时,CPU自动取ds的数据作为内存单元的段地址。0x10000用段地址和偏移地址表示为0x1000:0。8086CPU不支持将数据直接送入段寄存器的操作,“mov ds,0x1000”这条指令是非法的。
SS存放栈顶的段地址,SP存放偏移地址,任意时刻,SS:SP指向栈顶元素。8086CPU中,入栈时栈顶从高地址向低地址方向增长。出栈后,SS:SP指向新的栈顶,pop前的栈顶元素依然存在,但已经不在栈中,当再次执行push操作时,SS:SP又指回那个内存单元并在里面写入数据覆盖原有的。8086CPU没有检测栈顶超界问题的机制,需要编程时注意。
一段内存,可以既是代码段,又是数据段,还可以是栈段,也可以什么都不是,关键在于寄存器的设置,即CS、IP、SS、SP、DS的指向。
标志寄存器
PSW 程序状态字。标志寄存器简称flag。结构如下:
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OF | DF | IF | TF | SF | ZF | AF | PF | CF |
OF:在进行有符号数运算时,如果结果超过了机器所能表示的范围称为溢出,则of=1;否则of=0。
DF:在串处理指令中,控制每次操作后si、di的增减。df=0每次操作后递增,df=1每次操作后递减。
SF:相关指令执行后,其结果是否为负。为负则sf=1;否则sf=0。
ZF:相关指令执行后,其结果是否为0。为0则zf=1;否则zf=0。
PF:相关指令执行后,其结果的所有bit位中1的个数是否为偶数。为偶数则pf=1;否则pf=0。
CF:在无符号数运算时,运算结果的最高有效位是否向更高位进位或从更高位借位。是则cf=1;否则cf=0。
汇编指令
汇编指令是机器码的助记符,有对应的机器码。
mov add sub指令
(简单使用)都带有两个操作对象,结果保存在前一个里。
程序返回
mov ax, 0x4c00
int 0x21
伪指令
没有对应的机器码,由编译器执行,计算机并不执行。
segment ends
段名 segment
:
段名 ends
用来定义一个段
end
标记汇编程序结束
assume
含义是“假设”,假设某一段寄存器和程序中的某一个用segment … ends定义的段相关联。比如:
assume cs:codesg
codesg segment
...
codesg ends
end
codesg是一个自己定义的标号,指代了一个地址,这里作为一个段的名称,最终会被编译、连接程序处理为一个段的段地址。
其他符号
如+、-、*、/等,由编译器识别,没有对应的机器码。
寻址方式
()表示一个寄存器或者一个内存单元中的内容。
EA表示偏移地址。
SA表示段地址。
idata表示常量。
寻址方式 | 含义 | 名称 | 常用格式举例 |
---|---|---|---|
[idata] | EA=idata;SA=(ds) | 直接寻址 | [idata] |
[bx] | EA=(bx);SA=(ds) | 寄存器间接寻址 | [bx] |
[si] | EA=(si);SA=(ds) | 寄存器间接寻址 | [bx] |
[di] | EA=(di);SA=(ds) | 寄存器间接寻址 | [bx] |
[bp] | EA=(bp);SA=(ss) | 寄存器间接寻址 | [bx] |
[bx+idata] | EA=(bx)+idata;SA=(ds) | 寄存器相对寻址 | 用于结构体 [bx].idata |
[si+idata] | EA=(si)+idata;SA=(ds) | 寄存器相对寻址 | 用于数组 idata[si] |
[di+idata] | EA=(di)+idata;SA=(ds) | 寄存器相对寻址 | 用于数组 idata[di] |
[bp+idata] | EA=(bp)+idata;SA=(ss) | 寄存器相对寻址 | 用于二维数组 [bx][idata] |
[bx+si] | EA=(bx)+(si);SA=(ds) | 基址变址寻址 | 用于二维数组 [bx][si] |
[bx+di] | EA=(bx)+(di);SA=(ds) | 基址变址寻址 | 用于二维数组 [bx][si] |
[bp+si] | EA=(bp)+(si);SA=(ss) | 基址变址寻址 | 用于二维数组 [bx][si] |
[bp+di] | EA=(bp)+(di);SA=(ss) | 基址变址寻址 | 用于二维数组 [bx][si] |
[bx+si+idata] | EA=(bx)+(si)+idata;SA=(ds) | 相对基址变址寻址 | 用于表格(结构)中的数组项 [bx].idata[si] |
[bx+di+idata] | EA=(bx)+(di)+idata;SA=(ds) | 相对基址变址寻址 | 用于表格(结构)中的数组项 [bx].idata[si] |
[bp+si+idata] | EA=(bp)+(si)+idata;SA=(ss) | 相对基址变址寻址 | 用于二维数组 idata[bx][si] |
[bp+di+idata] | EA=(bp)+(di)+idata;SA=(ss) | 相对基址变址寻址 | 用于二维数组 idata[bx][si] |