1、debug 调试工具
参数:
-r 显示所有寄存器状态,可以修改寄存器内容(形如-r ax)
-d 显示从当前cs:ip位置之后的128个字节,可以指定地址打印(形如: -d 段地址:偏移地址)
-u 将cs:ip位置后续的字节翻译成汇编指令,可以制定地址翻译(形如: -u 段地址:偏移地址)
-a 在当前cs:ip位置处写指令,可以制定地址(形如: -a 段地址:偏移地址)
-t 执行当前cs:ip所指向的指令
-p 将当前循环体执行结束
-e 段地址:偏移地址 修改指定位置处开始后续的字节
-g 偏移地址 从cs:ip位置处开始,执行指令到指定位置处
2、
Byte = 8bit (字节型数据) => 一个内存地址就能保存一个字节
Word = 2Byte = 16bit (字型数据) => 一个字需要2个连续的内存单元来存放 高位地址存放高位字节 低位地址存放低位字节
3、寄存器
段地址 : 偏移地址
ds si
es di
ss bp
cs ip
sp
bx
cs:ip 所指向的内容为指令
ds:[0] 所指向的内容为数据(也可以为采用显式的表达方式: ds:[bx]等)
ds:[si] 数据从哪里来,一般的默认组合,也可以是ds:[bx+si+2]、ds:[bx+di]等
es:[di] 数据放到哪里去,同上
ss:sp 指向栈的栈顶数据,栈是以字为单位存放数据的
bx默认和ds是一对,ds:[bx]
bp默认是和ss是一对,ss:[bp]
4、指令执行的过程
<1> CPU从cs:ip所组成的地址中读取指令,将这个指令放到指令缓存器中
<2> IP = IP + 所读指令的字节数
<3> 执行指令缓存器中的内容,回到<1>继续执行
5、push、pop
push sp - 2,将指定的数据放到ss:sp所指向的内存空间
pop 将ss:sp处的数据弹出到指定位置,pop + 2
6、loop
loop s s 位标号
loop 条件转移指令(短转移),运行到loop指令时,cx -= 1,如果 cx == 0 循环结束,否则跳转到标号处继续执行
cx 存放循环的次数
7、数据不能以字母开头,如:FFFFH需要写成0FFFFH
8、安全的内存
0:200H ~ 0:2FFH 256个字节
0:7E00H之后
9、内存的分配是按16字节的倍数分配的
10、
db(define byte) 定义字节型数据,占1个字节
dw(define word) 定义字型数据,占2个字节
dd(define double) 定义双字型数据,占4个字节
11、定义data segment和stack segment后,数据和栈存放的内存与指令存放的内存相邻(不足16字节要补齐),即与cs:ip位置相邻,但是ds和ss还需要人为设置
12、大小写转换问题
字符 ASCII码 二进制形式
A 41H 0100 0001B
B 42H 0100 0010B
C 43H 0100 0011B
a 61H 0110 0001B
b 62H 0110 0010B
c 63H 0110 0011B
大写 –> 小写 or 0010 0000B
小写 –> 大写 and 1101 1111B
小写 or 0010 0000B = 小写
大写 and 1101 1111B = 大写
13、
//以字的形式处理数据
mov word ptr ds:[0],1
//以字节的形式处理数据
mov byte ptr ds:[0],1
//以双字型的形式处理数据
mov dword ptr ds:[0],1
14、div
<1>除数 8bit或者16bit,存放在内存单元或者寄存器(一般bl/bx)中
<2>被除数 AX或者 AX和DX中
如果除数为8bit,被除数则为16bit,存放在AX中
如果除数为16bit,被除数则为32bit,AX存放低16bit,DX存放高16bit
<3>结果 如果除数为8bit,则AL存放商,AH存放余数
如果除数为16bit,则AX存放商,DX存放余数
语法:
div bl(bx) ;即根据除数存放在哪里来决定被除数存放的位置
15、dup 重复指令
db 256 dup (0) 重复0这个字节256次
16、地址标号和数据标号
<1>地址标号
形如
s: db '1234'
表示了内存单元的地址
mov ax,OFFSET s 得到标号s位置处的偏移地址
<2>数据标号
形如
s db '1234'
不但表示了内存单元的地址,还表示了内存单元的长度
mov ds:[0],s 将字符'1'存放到指定位置,不需要特别指定长度
17、JMP 无条件转移指令
jmp word ptr ds:[0] 短转移: 修改ip
jmp dword ptr ds:[0] 段间转移: 修改cs:ip,cs存放高位数据,ip存放低位数据
18、转移指令
jmp、jcxz、loop、call等
标号处的地址 - 转移指令后的第一个字节的地址 = 位移
转移指令记录的不是目标地址,而是需要跳转的字节数
19、jcxz 条件转移指令(短转移)
jcxz s s 位标号
jcx(j => jmp cx => cx寄存器 z => zero)
当 cx == 0 时才进行跳转
20、inc、dec
inc ax ;ax = ax + 1
dec bx ;bx = bx - 1
21、nop
cpu什么都不做,占用一个字节
22、屏幕显示
在显存中(B800:0开始),偶数地址存放的是ascii码,奇数地址存放的是前面字符的颜色
一行可以存放80个字符,占用160个字节
一共有25行
所以可以存放的字符数为 80 * 25
占用的字节数为 160 * 25
颜色编码
7 6 5 4 3 2 1 0
0 1 0 0 0 0 0 1 ===> 红底蓝字
7号位置 => 闪烁
6号位置 => R red 背景
5号位置 => G green 背景
4号位置 => B blue 背景
3号位置 => 高亮
2号位置 => R red 前景
1号位置 => G green 前景
0号位置 => B blue 前景
23、ret、retf
ret 近转移 pop栈中的元素给 ip
retf 段间转移 pop栈中的两个元素分别给 ip 和 cs
24、call 转移指令
将当前ip(ip = ip + ip所读字节数) push 入栈,然后跳转到标号地址
call s s为标号,与ret配合使用,push ip
call far ptr s 与retf配合使用,push cs, push ip
注意:
call s 指令记录的是位移,不是目标地址
call far ptr s 指令记录的是目标地址,不再是位移
25、mul 乘法指令
<1> 8bit乘法
一个数存放在al中,另一个数存放在其他8bit寄存器或内存中,结果存放在ax中
<2> 16bit乘法
一个数存放在ax中,另一个数存放在其他16bit寄存器或内存中,结果的高16bit存放在dx中,低16bit存放在ax中
语法:
mul byte ptr ds:[0]
mul word ptr ds:[0]
26、标志位寄存器/程序状态字(PSW)
和运算指令有关,移动指令等不影响标志位
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 OV NV O = overflow,OV = overflow,NV = not overflow
判断运算过程中是不是溢出,有符号运算
DF DN UP DN = down,UP = up
与串传送指令配合使用
IF
TF
SF NG PL S = sign,NG = negative,PL = positive ?
判断运算结果是不是负数,mul不影响标志位
ZF ZR NZ Z = zero,ZR = zero,NZ = not zero
判断运算结果是不是0,mul、div不影响标志位
AF
PF PE PO P = parity,PE = parity even,PO = parity odd
判断运算结果中1的个数是不是偶数
CF CY NC C = carry,CY = carry yes,NC = not carry
判断运算结果是不是有进位,无符号运算
27、adc、sbb
adc ax,bx ax == ax + bx + carry
sbb ax,bx ax == ax - bx - carry
28、cmp
cmp ax,bx 两数相减,修改标志位,不记录结果
如果ax == bx zf = 1
如果ax != bx zf = 0
如果ax < bx cf = 1
如果ax >= bx cf = 0
如果ax > bx cf = 0 && zf = 0
如果ax <= bx cf = 1 || zf = 1
无符号比较,一般配合如下短转移指令使用
je 标号 ==> jmp equal
jne 标号 ==> jmp not equal
jb 标号 ==> jmp below
jnb 标号 ==> jmp not below
ja 标号 ==> jmp above
jna 标号 ==> jmp not above
有符号比较,结论如下
cmp al,bl
;SF = 1 OF = 0
;al < bl
;SF = 1 OF = 1
;al > bl
;SF = 0 OF = 0
;al > bl
;SF = 0 OF = 1
;al < bl
如果因为溢出导致实际结果为负,那么逻辑上真正的结果必然为正
如果因为溢出导致实际结果为正,那么逻辑上真正的结果必然为负
29、串传送指令
rep movsb 字节传送
rep movsw 字传送
mov cx,**
mov ds,**
mov si,**
mov es,**
mov di,**
cld //设置DF = UP(0),相当于执行inc si, inc di
rep movsb //将ds:[si]处的数据以字节为单位复制到es:[di]位置处
复制次数由cx决定
cld //add si,2 add di,2
rep movsw //将ds:[si]处的数据以字为单位复制到es:[di]位置处
30、pushf、popf
push、pop标志位寄存器 f ==> flag
31、中断
中断是CPU处理外部突发事件的一个重要技术。它能使CPU在运行过程中对外部事件发出的中断请求及时地进行处理,处理完成后又逻辑返回断点,继续进行CPU原来的工作。
<一> 内部中断
不可屏蔽,硬件出错或者运算出错所引起的中断,例如:
<1> 除法错误 divide overflow
<2> 单步执行
<3> 执行into指令
<4> 执行int指令
<二> 外部中断
可以屏蔽也可以不屏蔽,一般是指由计算机外设所发出的中断请求
例如:键盘中断,打印机中断,定时器中断等
可以通过cli和sti指令修改IF标志位,屏蔽外部中断请求
cli IF = 0,屏蔽外部中断
sti IF = 1,不屏蔽外部中断
31、中断向量表
记录中断处理程序入口的 CS:IP
表存在的位置: 0000:0000 ~ 0000:03FFH
IP = 0000:[中断类型码] * 4
CS = 0000:[中断类型码] * 4 + 2
32、中断过程
<1> 取得中断类型码
<2> 保存标志位寄存器到栈中 pushf
<3> 将标志位寄存器的第8位 TF 和 第9位 IF 设置为0
<4> push cs
<5> push ip
<6> cs = N * 4 + 2 ip = N * 4
中断处理返回的方法: iret (完成 pop ip、 pop cs、 popf)
33、shl、shr
逻辑移动指令
shl 往左边移动一位
shr 往右边移动一位
过程:
<1> 将一个寄存器或者内存单元中的数据向 左/右 移动一位
<2> 将移出的这一位放到CF中
<3> 最 低/高 位用0补充
mov al,1
shl a,1
执行之后,al == 0000 0010B,CF == 0
mov cl,3
shr al,cl
向右移动3位,必须使用cl寄存器来指定移动的位数
35、通码 断码
通码是键盘按键按下的状态编码
断码是键盘按键松开的状态编码
36、直接定址表
可以根据数据,直接计算出所要找的元素的位置的表,我们称其为直接定址表
37、键盘处理的过程
<1> 键盘的输入到达 60H 端口
<2> 相关芯片向CPU发出中断类型码为9的可屏蔽中断信息
<3> 如果IF = 1,那么执行 int 9 中断
38、int 9
<1> 读出 60H端口的扫描码
<2> 如果是字符键的扫描码,将这个扫描码和对应的ASCII放到BIOS中的键盘缓冲区
如果是控制键,将其转变为状态字节,记录到一个存储状态的字节单元中(0040:0017)
<3> 对键盘系统的相关控制,比如说,向相关芯片发出应答事情
键盘缓冲区
可以存放15个字型数据,高位存放扫描码,低位存放ASCII码
39、int 16H
从键盘缓存区读取数据
mov ah,0 设置功能号
int 16H
过程:
<1> 检测键盘缓冲区是否有数据
<2> 如果没有数据继续检测
<3> 读取缓存区第一个字型数据的键盘输入
<4> AH = 高位(扫描码) Al = 低位(ASCII码)
<5> 删除键盘缓存区中被读取的字型数据
40、ret、retf、iret
ret 弹出一个参数,给ip
retf 弹出两个参数,一个给ip,一个给cs
iret 弹出三个参数,一个给ip,一个给cs,一个给flag标志位
41、软盘
分为上下两面(0 ~ 1),一面有80个磁道(0 ~ 79),一个磁道有18个扇区(1 ~
18),一个扇区有512个字节
2 * 80 * 18 * 512B = 1440KB
1440KB / 1024 约等于 1.44MB
42、int 13H
;软盘 ==>> 0:200H
mov ax,0
mov es,ax
mov bx,200H ;es:[bx]
mov al,1 ;读取的扇区数
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dl,0 ;驱动器号 软驱A: 0 软驱B: 1
mov dh,0 ;面号/磁头号
mov ah,2 ;设置状态为 读取
int 13H
;0:200H ==>> 软盘
mov ax,0
mov es,ax
mov bx,200H ;es:[bx]
mov al,1 ;读取的扇区数
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dl,0 ;驱动器号 软驱A: 0 软驱B: 1
mov dh,0 ;面号/磁头号
mov ah,3 ;设置状态为 写入
int 13H