汇编学习笔记(二)
mul指令:乘法指令
1.两个相乘的数,位数必须相同:
8位乘法:一个默认放在al中,另一个放在8位reg或内存字节单元中。
16位乘法:一个默认在ax中,另一个放在16位reg或内存字单元中。
2.结果:
8位乘法:结果默认放在ax中。
16位乘法:结果高位默认放在dx,低位默认ax。
div指令:除法指令
1.除数:有8位和16位两种,在一个reg或内存单元中
2.被除数:默认放在ax或ax和dx中,若除数位8位,被除数则为16位,默认在ax中存放。若除数位16位,被除数则为32位,在ax和dx中存放,dx存放高16位,ax存放低16位。
3.结果:若除数为8位,则al存储除法操作的商,ah存储除法操作的余数。若除数位16位,ax存放除法操作的商,dx存储除法操作的余数。
div byte ptr ds:[0]
含义:
(al)=(ax)/((ds)*16+0)的商
(ah)=(ax)/((ds)*16+0)的余数
div word ptr es:[0]
含义:
(ax)=((dx)*10000h+(ax))/((es)*16+0)的商
(al)=((dx)*10000h+(ax))/((es)*16+0)的余数
db、dw、dd
均是由编译器识别处理的符号
1.db:定义字节型数据
2.dw:定义字型数据
3.dd:定义双字(double word,4字节)型数据
dup
db 重复的次数 dup (重复的字节型数据)
db 重复的次数 dup (重复的字型数据)
db 重复的次数 dup (重复的双字型数据)
db 3 dup (0)
定义3个字节,均为0,相当于 db 0,0,0
db 3 dup (‘abc’,’‘ABC’)
定义18个字节,为’abcABCabcABCabcABC’,相当于 db ‘abcABCabcABCabcABC’
转移指令
1.offset:取得标号的偏移地址。
start:mov ax,offset start //相当于mov ax,0 因为start是代码段中的标号,它所标记的指令时代码段中的第一条指令,偏移地址为0.
s: mov ax,offset s //相当于mov ax,3。因为第一条指令长度3个字节,则s的偏移地址为3.
2.jmp:无条件转移指令。
jmp short 标号 //在CPU中不需要目的地址,需要的是偏移地址
(1)8位位移=标号处的地址-jmp指令后的第一个字节的地址。
(2)short指明此处的位移位8位位移(段内短转移),范围为-128~127,8位位移由编译程序在编译时算出。
jmp near ptr 标号 //在CPU中不需要目的地址,需要的是偏移地址
(1)16位位移=标号处的地址-jmp指令后的第一个字节的地址。
(2)near ptr指明此处的位移位16位位移(段内近转移),范围为-32768~32767,16位位移由编译程序在编译时算出。
jmp far ptr 标号 //在CPU指出目标地址
功能:(CS)=标号所在段的段地址;(IP)=标号在段中的偏移地址。
jmp 16位reg //转移地址在寄存器中
功能:(IP)=(16位reg)
jmp word ptr 内存单元地址(段内转移)
功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。
jmp dword ptr 内存单元地址 (段间转移)
功能,从内存单元地址处开始存放着两个字,高地址处的字是转移目的段地址,低地址处是转移目的偏移地址。
3.jcxz:有条件转移指令(所有的有条件转移指令都是短转移:-128~127)。
jcxz 标号 (如果(cx)=0,转移到标号处执行,(cx)≠0,什么也不做,程序向下执行)
4.loop:循环指令(所有的循环指令都是短转移:-128~127)
操作(1)(cx)=(cx)-1
(2)如果(cx)≠0, 继续循环
5.ret、retf:
ret:用栈中的数据修改IP的内容,实现近转移。
CPU执行ret时的操作:
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
实际上相当于:
pop IP
retf:用栈中的数据,修改CS和IP的内容,实现远转移。
CPU执行retf指令时的操作:
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
(3)(CS)=((ss)*16+(sp))
(4)(sp)=(sp)+2
实际上相当于:
pop IP
pop CS
6.call
6.1 call 标号 //是将该指令后的第一个字节偏移地址入栈,再转到标号处执行指令。
CPU执行call指令时的操作:
(1)(sp)=(sp)-2
(2)((ss)*16+(sp))=(IP) //push IP
(3)(IP)=(IP)+16位位移
16位位移=标号处的地址-call指令后的第一个字节的地址。
6.2 call far ptr 标号:实现段间转移
CPU执行此格式call指令时的操作:
(1)(sp)=(sp)-2
(2)((ss)*16+(sp))=(CS) //push CS
(3)(sp)=(sp)-2 //push IP
(4)((ss)*16+(sp))=(IP)
(5)(CS)=标号所在段的段地址
(6)(IP)=标号在段中的偏移地址
6.3 call 16位reg
CPU执行此格式call指令时的操作:
(1)(sp)=(sp)-2
(2)((ss)*16+(sp))=(IP)
(3)(IP)=(16位reg)
6.4 call word ptr 内存地址:
相当于:
push IP
jmp word ptr 内存地址
call dword ptr 内存地址:
相当于:
push CS
push IP
jmp dword ptr 内存地址
call和ret可以配合使用,call调用某一程序,ret回到call指令后面一条指令继续执行下去
编写子程序的标准框架
子程序开始:子程序中使用的寄存器入栈
子程序内容
子程序使用的寄存器出栈
返回(ret、retf)
显示缓冲区
内存地址中,B8000H~BFFFFH 共32KB的空间,为80X25彩色字符模式的显示缓冲区,向这个地址空间写入数据,写入的内容将立即出现在显示器上。
80X25 表示显示器可以显示25行 每行80个字符,每个字符256种属性(背景色、前景色、闪烁、高亮等),每个字符在显示缓冲区中占两个字节,分别存放字符的ASCII码和属性。80X25模式下,一屏的内容在显示缓冲区中共占4000个字节。
显示缓冲区分8页,每页4KB(≈4000B),显示器可以显示任意一页的内。例如,第0页将会将 B8000H~B8F9FDE 4000个字节显示在显示器上。
第一页 :
偏移000~09F对应显示器上第1行(80个字符占160个字节)
偏移0A0~13F对应显示器上第2行
……
属性字节的格式
7 6 5 4 3 2 1 0
BL R G B I R G B
BL表示闪烁
第一组R G B 表示红绿蓝背景色
I表示高亮
第二组RGB表示红绿蓝前景色
例 红底绿字 属性字节为:01000010B
红底闪烁绿字 属性字节为:11000010B
flag标志寄存器
8086CPU标志寄存器flag有16位,其中存储的信息通常被称为程序状态字(PSW),flag与其他寄存器不同的是,flag寄存器按位起作用,每一位有专门的含义:
8086CPU 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 |
标志含义如下:
ZF:零位标志。记录相关指令执行后,其结果是否为0。如果为0,ZF=1;否则ZF=0.
PF:奇偶标志位。记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数。如果1的个数为偶数,PF=1;否则PF=0。
SF:符号标志位。记录相关指令执行后,其结果是否为负。如果为负SF=1;否则SF=0。
CF:进位标志位。进行无符号数运算时,记录运算结果的最高有效为向更高位的进位或借位。如果有进位或借位,CF=1;否则CF=0.
OF:溢出标志位。记录有符号数运算的结果是否发生溢出。如果发生溢出,OF=1;否则OF=0.
DF:方向标志位。在串处理指令中,控制每次操作后si、di的增减
DF=0:每次操作后si、di递增
DF=1:每次操作后si、di递减
TF :TF=1表示单步中断。
IF:当CPU检测到可屏蔽中断,如果IF=1,则CPU执行完当前指令后响应中断,如果IF=0,则不响应可屏蔽中断。
与Flag寄存器有关的指令
adc指令
带进位加法指令,利用了CF上记录的进位值。
例:
adc ax,bx
实现的功能为(ax)=(ax)+(bx)+CF
例:
mov ax,2
mov bx,1
sub bx,ax
adc ax,1
执行后,(ax)=4.因为(ax)=(ax)+1+CF=2+1+1=4
sbb指令
带进位减法指令,利用了CF位上记录的借位值。
例:
sbb ax,bx
实现的功能为(ax)=(ax)-(bx)-CF
cmp指令
比较指令。
指令格式:cmp 操作对象1,操作对象2
含义:计算操作对象1-操作对象2,但不保存结果,而是根据结果修改flag寄存器。
当cmp进行无符号数比较时:
cmp ax,bx
1) (ax)=(bx),则ZF=1
2) (ax)≠(bx),则ZF=0
3) (ax)<(bx),则CF=1((ax)-(bx)产生了借位)
4) (ax)≥(bx),则CF=0
5) (ax)>(bx),则CF=0,ZF=0
6) (ax)≤(bx),则CF=1,ZF=1
当cmp进行有符号数比较时:
cmp ax,bx
1)如果SF=1,OF=0
OF=0表没有溢出,则实际结果正负=逻辑结果正负,(ax)<(bx)
2)SF=1,OF=1
OF=1表发生溢出,则实际结果正负≠逻辑结果正负,如果溢出导致实际结果为负,那么逻辑上真正的结果为正。(ax)>(bx)
3)SF=0,OF=1
OF=1表发生溢出,则实际结果正负≠逻辑结果正负,如果溢出导致实际结果为正,那么逻辑上真正的结果为负。(ax)<(bx)
4)SF=0,OF=0
(ax)≥(bx)
条件转移指令
只列出无符号条件下的指令
指令 | 含义 | 检测的相关标志位 |
---|---|---|
je | 等于则转移 | ZF=1 |
jne | 不等于则转移 | ZF=0 |
jb | 低于则转移 | CF=1 |
jnb | 不低于则转移 | CF=0 |
ja | 高于则转移 | CF=0且ZF=0 |
jna | 不高于则转移 | CF=1且ZF=1 |
cld、std
cdl指令:将标志寄存器的df位置0
std指令:将标志寄存器的df位置1
sti、cli
sti指令:设置IF=1
cli指令:设置IF=0
串传送指令
1)movsb指令
格式:movsb
功能:(1)((es)*16+(di))=((ds)*16+(si))
(2)如果DF=0,(si)=(si)+1,(di)=(di)+1
如果DF=1,(si)=(si)-1,(di)=(di)-1
2)movsw指令
格式:movsw
功能:(1)((es)*16+(di))=((ds)*16+(si))
(2)如果DF=0,(si)=(si)+2,(di)=(di)+2
如果DF=1,(si)=(si)-2,(di)=(di)-2
通常movsb和movsw与rep配合使用
格式:rep movsb
功能形如:
s:movsb
loop s
pushf、popf
pushf指令:将标志寄存器的值压栈
popf指令:从栈中弹出数据,送入标志寄存器中。