《汇编语言》笔记
学习完王爽的《汇编语言》确实有一种豁然开朗的感觉,书中很多实践例题,感觉是他带着我们一步一步做实验,非常容易理解,是不可多得的好书!
本书汇编语言的环境是8086CPU为中央处理器的PC机,原因是它常用而且结构简洁。
一、计算机的结构
最核心的部件有三个:CPU、内存、I/O设备。CPU负责运算加工数据,这些数据处理好后存入内存,I/O设备通过端口可以显示存储器中的内容,也可以向CPU传输数据,实现人机交互。
内存
8086的内存有1MB,需要20位的地址才能访问(),而每个地址保存了8bit的数据。地址相当于每家每户的门牌号,里面住着不同的人家,最多住8个人。现在我们熟知的内存有4G、8G,而且价格还便宜,可见半导体的发展是多么迅猛!
段地址和偏移地址
计算机访问内存通常不是直接用物理地址,前面说了内存空间有20位,但CPU内部寄存器只有16位,要访问一个123C8(16进制数)的地址,用一个寄存器是不够的,如何解决呢?用两个寄存器,分别储存短地址和偏移地址:
物理地址=段地址×16+偏移地址
123C8=123C(十六进制)×16(十进制)+8=1230×16+C8
这里的段地址可以是123C,偏移地址为8,也可以是1230和C8,可见同一个地址表示方法不唯一。这种表示其实也很好理解,比如有人向你问路,复旦大学怎么走,你可以直接说东经121°,北纬31°(物理地址),但是更常有的是沿着江湾体育场地铁站(段地址)向西走三百米(偏移地址)。
内存分配
那么内存的空间是如何分配的呢?
地址0~7FFFH的32KB空间为主随机存储器RAM地址;
地址8000H~9FFFH的8KB空间为显存地址;
地址A000H~FFFFH的24K为各个ROM的地址空间;
显存地址好理解,如果把数据写在显存地址上,通过显示器端口的转换,数据会呈现在显示屏上。
ROM(Read Only Memory)翻译是只读存储器,在计算机允许时,这部分的数据只能读取,不能写入。它是由非挥发性MOS管构成,要通过加压产生电子隧穿效应才能实现其写入,很多开发板,如单片机、FPGA等在编好程序后,都需要“烧写”,就是将启动程序写入ROM中,这样在开机时,计算机从第一条指令开始逐条读取并执行。
24KB的ROM空间包含系统启动程序,显卡启动程序,网卡启动程序。
这里的网卡和显卡属于I/O设备,它需要端口才能与CPU连接,因为CPU允许速度太快,8086是每秒8M次左右,而人键盘输入最快撑死每秒10下。端口相当于助教,等待学生(显卡)完成作业后通知教授(CPU),在等待的过程中,教授可以做其他事情,而不用教授亲自不停询问学生是否作业,大大提高效率。
开机后,CPU自动进入FFFF:0(段地址FFFF,偏移地址0,物理地址FFFF0)单元执行,此处由一条跳转指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。
初始化后,调用int 19h进入操作系统的引导,如果设置为软盘启动,则int 19h 主要完成以下工作:
(1)控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00;
(2)将CS:IP指向0:7c00,开始执行程序。
如果没有软盘,则读取C盘:
(1)读取C盘的0道0面1扇区的内容到0:7c00;
(2)将CS:IP指向0:7c00,开始执行程序。
中断向量表
这里的CS寄存器保存了指令的段地址,IP表示指令的偏移地址。int表示中断指令(interruption),如果计算机允许是碰到int指令,它会先“保护现场”:保存CS,IP和当前进位等状态值,然后跳转进入某个地址,该地址又保存了下个指令要执行的CS、IP值。int 19h表示跳转到00:19h×4=64h的地址,00:64h和00:65h共保存了16位(分别8位)的待跳转IP值,00:66h和00:67h保存了待跳转的CS值。中断实际上就是高权限的跳转指令。
8086CPU的内存0000:0000到0000:03FF的1024个单元存放着256个中断入口对应的跳转地址,比如0000:0000处放置int 0时跳转的数据:68 10 A7 00,运行后CS=00A7,IP=1068,继续执行指令。可以看出每个中断需要4个8bit的存储单元,256个中断入口就需要1024个单元。这些单元存储的指令跳转地址就是中断向量表。
内存中有一段安全空间:00:200~0:2ff,它里面没有系统或其他程序或代码,用户可以写入自己的程序,此处为BASIC保留,提供BASIC解释程序使用,没有中断入口。
二、CPU
寄存器相当于草稿纸
备忘
A、寄存器寻址总结:[bx][bp][si][di]
正确寻址指令:
mov ax,[bx]
mov ax,[bp] (默认段地址为ss)
mov ax,[si]
mov ax,[di]
mov ax,[bx+si] (默认段地址为ds)
mov ax,[bx+di] (默认段地址为ds)
mov ax,[bp+si] (默认段地址为ss)
mov ax,[bp+di] (默认段地址为ss)
mov ax,[bx+si+idata] (默认段地址为ds)
mov ax,[bx+di+idata] (默认段地址为ds)
mov ax,[bp+si+idata] (默认段地址为ss)
mov ax,[bp+di+idata] (默认段地址为ss)
错误寻址指令:
mov ax,[ax] (累加器不可)
mov ax,[cx]
mov ax,[dx]
mov ax,[ds] (段寄存器不可)
mov ax,[bx+bp] (这种组合不可)
mov ax,[si +di ] (这种组合不可)
B、跳转总结
- jmp,无条件跳转
- jcxz,有条件跳转
- loop,循环
- call ,调用函数
- int ,中断
jmp short s ;偏移量范围-128~127
jmp near ptr s; 偏移量范围-32768~32767
jmp far ptr s;不是偏移量,而是s指令的段地址+偏移地址
jmp word ptr ds:[0];跳转地址的IP存储在ds:[0][1]
jmp dword ptr ds:[0];跳转地址的IP存储在ds:[0][1],CS存储在ds:[2][3]
loop s (cx--), if ((cx)≠0) jmp short s
ret pop IP
retf pop IP, pop CS
call s push IP, jmp near ptr s
call far ptr s push CS, push IP,jmp far ptr s
call word ptr ds:[0]push IP, jmp word ptr ds:[0]
call dword ptr ds:[0]push CS,push IP, jmp dword ptr ds:[0]
int 9 pushf,push CS,push IP;TF=0,IF=0,(IP)=(9×4),(CS)=(9×4+2)
iret pop IP,pop CS,popf
C、常用中断程序
1、int 0 为除法溢出时的中断入口
2、int 7ch 可供用户自行设计
3、int 10h BIOS设置光标中断:
mov bh,0 ;第0页(总共4页,0~3,一般用第0页)
mov dh,5 ;第5行(总共有25行,0~24)
mov dl,12 ;第12列(总共有80列,0~79)
mov ah,2 ;第10h号中断2号子程序
int 10h
光标位置显示字符:
mov bh,0 ;第0页
mov bl,7 ;字符颜色属性
mov cx,3 ;字符重复个数
mov al,'a' ;显示字符
mov ah,9 ;第10h号中断9号子程序
int 10h
`补充:颜色属性格式
bit位置 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
含义 | BL | R | G | B | I | R | G | B |
解释 | 闪烁 | 背景 | 高亮 | 前景 |
4、int 21h
mov al,0 ;返回值
mov ah,4ch ;调用第21h中断4ch号子程序
int 21h
ds:dx ;要先显示字符串的起始地址,用"$"作为结束符
mov ah,9h ;调用第21h中断9h号子程序
int 21h
D、标志寄存器
标识 | OF | DF | IF | TF | SF | ZF | AF | PF | CF |
---|---|---|---|---|---|---|---|---|---|
flag寄存器中位置 | 11 | 10 | 9 | 8 | 7 | 6 | 4 | 2 | 0 |
debug中1显示 | ov | dn | ei | 无 | ng | zr | ac | pe | cy |
0显示 | nv | up | di | 无 | pl | nz | na | po | nc |
英文 | over flow | Direction | Interrupt | trace | Sign | Zero | Auxiliary carry | Parity | Carry flag |
中文 | 是否溢出 | 方向标志 | 是否允许中断 | 是否单步追踪 | 符号正负 | 是否为零 | 辅助进位 | 是否为偶 | 是否进位 |