BCD码的十进制调整指令
可直接得到十进制数的结果
用四位二进制数表示一位十进制数 8421码
daa 加法的十进制调整指令
以al为目的操作数做加法运算后,可以把和调整为bcd码格式
若al低四位>9,或af=1,则al=al+6
若al高4位>9或cf=1,则al=al+60h,cf=1
例
al=28h=28(bcd),bl=65h=65(bcd)
add al,bl //al=8dh
daa //al=al+6h=8dh+6h=93(bcd)
例
ax=88h=88(bcd),bx=89h=89(bcd)
add al,bl //al=11h,af=1,cf=1
daa //al=al+66h=77h=77(bcd),cf=1
adc ah,0 //带进位加法,固定用法,加上进位cf ax=177h=177(bcd)
das减法的十进制调整指令
若al低4位>9,或af=1,则al=al-6h,af=1
若al高4位>9,或cf=1,则al=al-60h,cf=1
例
al=93h=93(bcd),bl=65h=65(bcd)
sub al,bl //al=93h-65h=2eh
das //al=al-6h=28h(bcd)
非压缩bcd码的十进制调整指令
非压缩bcd码用8位二进制数表示一位十进制数,低4位为8421码,高四位无意义。如ascii码,所以又叫ascii码调整指令
aaa 加法的调整
aas 减法的调整
aam 乘法的调整
aad 除法的调整
aaa 调整后非压缩bcd码的高四位无意义所以al的高四位为0,同时将调整产生的进位加到ah中
例
如ax=0039h=9(bcd),bl=35h=5(bcd)
add al,bl //al=39h+35h=6eh
aaa //ax=0014h=14(bcd)
aas al高四位置0,将调整产生的借位从ah中减去
例
ax=3835h=85(bcd),bl=39h=09(bcd)
sub al,bl //al=35h-39h=fch,cf=1
aas //ax=3706h=76(bcd)
aam
先做乘法,把两个一字节且高四位为0的非压缩bcd码相乘,然后使用aam指令把ax内容调整为2字节非压缩bcd码
例
al=05h=5(bcd),bl=09h=9(bcd)
mul bl //ax=002dh
aam //ax=0405h=45(bcd)
aad
先做aad调整指令,把ax中两个一字节且高4位为0的非压缩bcd码调整为二进制形式,然后使用除法指令除以一个字节的非压缩bcd码(高四位为0),即可得到二进制结果
例
ax=0206h=26(bcd),bl=02h=2(bcd)
add //ax=001ah
div bl //ax=001ah/02h=000dh
逻辑与移位指令
用于对操作数的某些位进行处理,如屏蔽某些位(将这些位置0),或使某些位置1,或测试某些位等
test 两个操作数相与的结果不保存,只根据其特征置标志位
not指令不影响标志位,其他指令将使cf位和of位为0
例
屏蔽al寄存器的高4位,如al=36h
and al,0fh //al=06h
例
对al寄存器的最低两位置1,如al=36h
or al,03h //al=37h
例
对al寄存器最低两位取反,如al=36h
xor al,03h //al=35h
例
测试al寄存器中的数,如果是负数则转到标号next执行,如al=86h
test al,80h
js next //flags标志寄存器的sf=1,所以程序转到next执行
移位指令
shl 逻辑左移
sal 算术左移
shr 逻辑右移
sar 算术右移
rol 循环左移
ror 循环右移
rcl 带进位循环左移
rcr 带进位循环右移
shl 寄存器/内存单元 移位次数
移位次数大于1,需要先把移位次数送到cl寄存器
例 对ax中的内容实现半字交换,即交换al和ah的内容
mov cl,8
rol ax,cl
串操作指令
movs 串传送
cmps 串比较
scas 串扫描
stos 存入串
lods 从串取
串操作指令每次只能处理字或字节,因此需要重复执行串操作指令才能处理完一个数据串,所以需要和以下前缀配合
rep(repeat)
repe/repz(repeat while equal/zero)相等/为0则重复
repne/repnz(repeat while not equal/not zero)不相等/不为0则重复
rep前缀表示重复执行到cx=0为止
repe除了cx=0时终止操作,还增加了cx!=0且zf=1时,重复执行,与repz一致,如,两数比较,相等即zf=1时,继续执行
repne只有当cx!=0且zf=0时,重复执行串操作指令,如两数比较,不相等即zf=0时重复执行,与repnz一致
movs串传送指令
movsb 字节
movsw 字
movs 目的串地址(es:[di]) 源串地址(ds:[si])
movs es:byte ptr[di],ds:[si] 指出了是字节的传送,如果源串不在数据段,也可加前缀,如es:[si]
方向标志df决定si,di方向
movs指令可以把由源变址寄存器si指向的数据段中的一个字节或字传送到目的变址器di指向的附加段的一个字节或字中,该指令与rep前缀联用,可传递完整数据串到si附加段
为实现串传输要准备
1 数据段中的源串首地址(如反向传送则为末地址)送往ds和si
2 附加段的目的串地址送es和di
3 串长度送计数器cx
4 设方向标志df
方向标志df的设置有两条指令
cld 正向(向前,使df=0,si或di自动加)
std 反向(使df=1,si或di自动减)
例 在数据段有一个字符串mess,长度为19,要求传输到附加段中一个名为buff的缓冲区,并显示出buff字符串
data segment
mess db 'com on$'
data ends
ext segment
buff db 19dup(?) //初始化19字节的缓冲区 db表示字节
ext ends
code segment
assume cs:code,ds:data,es:ext
start:
mov ax,data //赋段地址
mov ds,ax //data段地址送入ds
mov ax,ext //ext段地址送入es
mov es,ax
lea si,mess //赋偏移地址
lea di,buff
mov cx,19 //si di自动加
cld
rep movsb //开始并完成串传送
mov bx,es
mov ds,bx //ds指向待显示串的段地址
lea dx,buff //dx指向偏移地址
mov ah,9 //显示字符串功能,ds:dx=串地址
int 21h
mov ah,4ch
int 21h
code ends
end start
cmps串比较指令
cmpsb 字节
cmpsw 字
cmps 目的[es:di] 源[ds:si]
把两个串的对应位置的字节或字相减,不保存结果,只根据结果设置标志位,指令与前缀repe联用时,可比较两个串是否相等,一旦不相等,zf=0,终止重复执行
例
在数据段中有一个长度为19的字符串mess1,还有一个长度为19的字符串mess2,比较他们是否相等,相等显示y,否则显示no
data segment
mess1 db 'uuuuooi\$'
mess2 db 'uuuuooo\$'
data ends
code segment
assume cs:code,ds:data
start:
mov ax,data
mov ds,ax
mov es,ax //ds=es
lea si,mess1 //mess1送到ds:si mess2送到es:di
lea di,mess2
mov cx,19
cld
repe compsb //repe表示cx=0 或zf=0时终止,与compsb配合
jz yes //zf=1说明相等,跳转到标号yes
mov dl,'N' //不相等时
jmp disp //跳到disp
yes:mov dl,'Y'
disp:mov ah,2 //输出dl内容
int 21h
mov ah,4ch
int 21h
code ends
end start
scas串扫描指令
scasb 字节
scasw 字
scas目标串es:[di]
把累加器的内容与附加段中的由目的变址器di所指向的内存单元内容相比较,不保存结果,根据结果设置标志位,与前缀repne联用时,可在目的串中寻找有无与累加器中的内容相同的字节或字,一旦相等,zf=1,终止执行
例
在附加段中有一个字符串mess,长度为19,要求查找有无空格符,有空格即把首次发现的空格符改为“#”,存回该单元,并显示“y”,否则显示“n”
ext segment
mess db 'comjdid kk$'
ext ends
code segment
assume cs:code,es:ext
start:
mov ax,ext //送入字符串物理地址
mov es,ax
lea di,mess
mov cx,19
mov al,20h //空格符的ascii码为32=20h
cld
repne scasb //找到空格时zf=1,zf=1或cx=0时终止程序
jz yes //找到空格时跳到yes
mov dl,'n'
jmp disp
yes:dec di //di自减一
mov byte ptr es:[di],23h //#送到原空格位置
mov dl,'y'
disp:mov ah,2
int 21h
mov ah,4ch
int 21h
code ends
end start
stos串存入指令
stosb (字节)
stosw(字)
stos 目的串es:[di]
把累加器的内容存入由目的变址器指向的附加段的某单元中,并根据df的值及数据类型修改目的变址寄存器的内容。与rep联用时,可把累加器的内容存入一个连续的内存缓冲区,缓冲区长度由cx指定
初始化某一块内存区时可用stos串指令
例 写出把附加段ext中的首地址为mess,长度为9个字节的缓冲区置为0值的程序片段
mov ax,ext
mov es,ax
lea di,mess
mov cx,9 //9个字节的串
mov ax,0 //存入
cld
rep stosw //每次执行di自动加2
lods从串取指令
lodsb (字节)
lodsw (字)
lods 源串ds:[si]
程序转移指令
jmp
无条件跳转到指定地址(转向地址)
转移目标地址和本指令在一个代码段,跳转后cs寄存器值不变,只是ip寄存器改变,叫段内转移,cs变化叫段间转移
转移的目标地址直接给出,叫直接转移,否则为间接转移
段内直接转移:ip寄存器被加上16位位移量,该位移量是带符号数,位移量为负数时,ip+16位移量后,ip值反而减小,程序向后跳,位移量为正数时,ip值增加,程序向前跳
jmp nearptr opr 近段间转移
jmp short opr 短转移指令 目标地址opr距离跳转指令-128~+127字节范围内时
段内间接转移 把有效地址值送入ip
jmp wordptr opr
例
若bx=2000h,ds=4000h,(4200h)=6050h,(44000h)=8090h,table的偏移地址为2000h,则
jmp bx //寄存器寻址,ip=bx=2000h
jmp wordptr [bx] //寄存器间接寻址,ip=[ds:bx]=(40000h+2000h)=(42000h)=6050h
jmp wordptr table //直接寻址,ip=[ds:table], 与上同
jmp table[bx] //寄存器相对寻址,ip=[ds:(table+bx)]=(44000h)=8090h
段间直接转移 把偏移地址送入ip 把段地址送入cs
jmp far ptr opr
段间间接转移 有效地址送入ip 有效地址+2地址送入cs
jmp dword ptr opr
根据寻址方式求出有效值后,把指定内存字单元内容送入ip寄存器,并把下个字内容送入cs寄存器
例
若bx=2000h,ds=4000h,(42000h)=6050h,(42002h)=1234h
jmp dword ptr [bx] //ip=(ds:2000h)=(40000h+2000h)=(42000h)=6050h,cs=(42002h)=1234h
条件转移指令
根据上一条指令所设置的标志位判别测试条件,使用前有一条能产生标志位的前导指令,如cmp,满足测试条件即跳转到转向地址,不满足则执行下条指令,转向地址由标号表示,条件转移指令不影响标志位
根据单个条件标志的设置情况转移(10种)
1 格式指令 jz opr 结果为0则跳转
等效指令 je opr 结果相等则跳转
测试条件 zf=1则转移
2 格式指令 jnz opr 结果不为0则跳转
等效指令 je opr 结果不相等则跳转
测试条件 zf=0则转移
3 格式指令 js opr 结果为负则跳转
测试条件 sf=1则转移
4 格式指令 jns opr 结果为正则跳转
测试条件 sf=0则转移
5 格式指令 jo opr 结果溢出则跳转
测试条件 of=1则转移
6 格式指令 jno opr 结果为0则跳转
测试条件 of=0则转移
7 格式指令 jc opr 进位位为1则跳转
等效指令 jb opr 低于则跳转
等效指令 jnae opr 不高于等于则跳转
测试条件 cf=1则转移
8 格式指令 jnc opr 进位位为0则跳转
等效指令 jnb opr 不低于则跳转
等效指令 jae opr 高于等于则跳转
测试条件 cf=0则转移
9 格式指令 jp opr 奇偶位为1则跳转
等效指令 jpe opr 偶数个1则跳转
测试条件 pf=1则转移
10 格式指令 jnp opr 奇偶位为0则跳转
等效指令 jpo opr 奇数个1则跳转
测试条件 pf=0则转移
测试cx寄存器值为0则转移
指令格式:jcxz opr //cx寄存器为0则转移
比较两个无符号数,据比较结果转移
jc(jb,jnae) opr //cf=1则转移
jnc(jnb,jae) opr //cf=0转移
jbe(jna) opr //cf或zf=1转移
jnbe(ja) opr //cf或zf=0转移
比较两个带符号数,据比较结果转移
jl(jnge) opr //小于转移 sf,of=1则转移