第九章 转移指令
1、什么是转移指令: 可以修改ip,或同时修改cs和ip的指令。8086cpu转移指令分为:无条件转移指令(jmp),条件转移指令,循环指令(loop),过程,中断
2、offset操作符: 取得标号的偏移地址。 start: mov ax,offset start 等价于mov ax,0
3、无条件转移指令: jmp
依据位移进行转移: 【cpu在执行jmp时并不需要转移的目的地址】
(1)段内短转移: jmp short 标号(修改ip,转移到标号处执行指令,对ip的修改范围是-128~127)
【汇编中的idata一定会出现在对应的机器码中】
(2)段内近转移: jmp near ptr 标号 (对ip的修改范围是-32768~32767)
转移目的地址在指令中:
(3)段间远转移: jmp far ptr 标号 (用标号的段地址和偏移地址修改cs和ip)
转移地址在寄存器中:
(4)jmp 16位reg (修改ip的值为16位寄存器值)
转移地址在内存中:
(5)段内转移:jmp word ptr 内存单元地址
(6)段间转移:jmp dword ptr 内存单元地址(内存单元地址处放两个字,高字存放目的段地址,低字存放目的偏移地址)
4、有条件转移指令:
【!所有有条件转移指令和循环指令都是短转移,在机器码中包含转移的位移,对ip的修改范围是-128~127】
jcxz 标号(如果cx值=0,转移到标号处执行)
5、循环指令:
loop 标号(cx=cx-1,如果cx值不为0,转移到标号处执行)
6、自增inc和自减dec:
inc ax : (ax)=(ax)+1
dec ax : (ax)=(ax)-1
第十章 CALL和RET
1、ret和retf: ret用栈中的数据,修改ip的内容,实现近转移 pop ip
retf用栈中的数据,修改cs和ip的内容,实现远转移 pop ip pop cs
2、call命令: 将当前的ip或cs和ip压入栈中,转移。【call和jmp的转移方法相同,但call不能实现短转移(jmp short 标号,jcxz,loop)】
依据位移进行转移: call 标号(将当前的ip压栈,转移到标号处执行指令)相当于 push ip jmp near ptr 标号
目的地址在指令中: call far ptr 标号(将cs和ip压栈,转移到标号处执行指令) 相当于 push cs push ip
jmp far ptr 标号
转移地址在寄存器: call 16位寄存器 相当于 push ip jmp 16位reg
转移地址在内存中: call word ptr 内存单元地址 相当于 push ip jmp word ptr 内存单元地址
call dword ptr 内存单元地址 相当于 push cs push ip jmp dword ptr 内存单元地址(内存单元高16位放cs,低16位放ip)
3、子程序: 一个具有一定功能的程序段。在需要的时候,用call指令转去执行,子程序最后使用ret返回call指令后面代码处继续执行
4、乘法指令mul:
mul reg或mul 内存单元
两个乘数:都是8位或都是16位。(8位时一个放在AL中,另一个放在8位reg或内存字节单元中;16位时一个放在ax中,另一个放在16位reg或内存字单元中)
结果:如果是8位乘法,结果默认放在ax;如果是16位乘法,结果默认高位放在dx,低位放在ax
【默认16位相乘肯定不会错】
mov ax,100h
mov bx,10000h
mul bx;计算100hx10000h 结果(ax)=4240h(dx)=000fh 5、避免寄存器冲突:
在子程序的开始将子程序中所有用到的寄存器的内容都保存在栈中,在子程序返回前再恢复
子程序标准框架:
子程序开始:
子程序中使用的寄存器入栈 push
子程序内容
子程序中使用的寄存器出栈 pop
返回 ret或retf
第十一章 标志寄存器
1、什么是标志寄存器:
(1)用来存储相关指令的某些执行结果
(2)用来为cpu执行相关指令提供行为依据
(3)用来控制cpu的相关工作方式
2、8086cpu标志寄存器:
8086标志寄存器有16位,存储的信息称为程序状态字。每一位都有专门的含义,记录特定的信息。
详见8086标志寄存器.png
【!注意,在8086cpu的指令集中,运算指令(add,sub,mul,div,inc,or,and)执行可能会影响标志寄存器,传送指令(mov,push,pop)执行不会影响】
3、带进位加法指令adc:
adc 对象1,对象2 (对象1=对象1+对象2+CF)
mov ax,1
add ax,ax
adc ax,3 ;计算2+3+cf,2+3+0=5,(ax)=5
【sub ax,ax可以将cf置零】
4、带借位减法指令sbb:
sbb 对象1,对象2 (对象1=对象1-对象2-CF)
5、cmp比较指令:
cmp 对象1,对象2【cmp指令不保存结果】(比较两个对象的值)
进行无符号比较 cmp 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 (ax)<=(bx)
有符号比较 cmp ah,bh
sf=1而of=0 (ah)<(bh)
sf=1而of=1 (ah)>(bh)
sf=0而of=1 (ah)<(bh)
sf=0而of=0 (ah)>=(bh)
6、检测比较结果的条件转移指令
(1)根据无符号数的比较结果进行转移的条件转移指令(检测zf、cf的值)
详见无符号比较转移指令.png
(2)根据有符号数的比较结果进行转移的条件转移指令(检测sf、of和zf的值)
7、串传送指令
(1)以字节为单位传送:movsb
功能:将ds:si指向的内存单元中的字节送入es:di中,然后根据标志寄存器df位的值,将si和di递增或递减
mov es:[di],byte ptr ds:[si]
如果df=0: inc si inc di
如果df=1: dec si dec di
(2)以字为单位传送:movsw
功能:将ds:si指向的内存单元中的字送入es:di中,然后根据标志寄存器df位的值,将si和di递增2或递减2
mov es:[di],word prt ds:[si]
如果df=0: add si,2 add di,2
如果df=1: sub si,2 sub di,2
9、rep指令
根据cx的值,重复执行后面的串传送指令
rep movsb(循环cx个字符的传送)
10、df设置指令
cld:将标志寄存器的df位置0(正向传送)
std:将标志寄存器的df位置1(逆向传送)
11、pushf和popf
pushf:将标志寄存器的值压栈 popf:从栈中弹出数据,送入标志寄存器中
12、标志寄存器在debug中的表示
第十二章 内中断
1、中断向量表
中断向量表在内存中保存,存放着256个中断源所对应的中断处理程序的入口
【8086cpu中断向量表必须放在0000:0000~0000:03ff 单元中,(0:200~0:2ff 是安全内存)】
2、中断处理程序和iret指令
中断处理程序步骤:
(1)保存用到的寄存器
(2)处理中断
(3)恢复用到的寄存器
(4)iret返回
iret指令:
pop ip ; pop cs ; popf
【!在中断过程中,寄存器入栈的顺序是标志寄存器,cs,ip,iret出栈的顺序是ip,cs,标志寄存器】
3、改写0号中断(除法中断)
(1)编写显示的中断处理程序(类似子程序)
(2)将程序送入0000:0200处 (安装)
(3)设置中断向量表(将程序的入口地址0000:0200 存储在中断向量表0号表项中)
具体程序:
assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset do0 ;设置 ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h ;设置es:di指向目标地址
mov cx,offset do0end-offset do0 ;传输长度
cld ;设置正向传送
rep mov sb
mov ax,0 ;设置中断向量表,将do0的入口地址0:200写入中断向量表的0号表项中
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0
mov ax,4c00h
int 21h
do0:
jmp short do0start
db "overflow!"
do0start:
mov ax,cs
mov ds,ax
mov si,202h ;设置ds:si指向字符串
mov ax,0b800h ;显存
mov es,ax
mov di,12*160+36*2 ;设置es:di指向显存空间中间位置
mov cx,9;设置cx为字符串长度
s:
mov al,[si]
mov es:[di],al
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:
nop
code ends
end start
4、单步中断
CPU在执行完一条指令后,如果检测到标志寄存器tf位为1,则产生单步中断,引发中断过程:
(1)取得中断类型码1
(2)标志寄存器入栈,tf、if设置为0
(3)cs,ip入栈
(4)(ip)=(14),(cs)=(14+2)
5、响应中断的特殊情况
CPU在执行完向ss寄存器传送数据的指令时,即使发生中断,cpu也不会响应,包括单步中断(mov ss,ax)