大家好,欢迎来到IT知识分享网。
一. cmp 指令
1. cmp 指令功能
cmp (compare) 是比较指令,cmp 的功能相当于减法指令,只是不保存结果,但会根据结果对标志寄存器进行设置,其它相关指令就可以通过识别这些被影响的标志寄存器的位来得知比较结果。
2. cmp指令格式
cmp 操作对象1, 操作对象2。
3. cmp 指令的 CPU 工作原理
对于指令:cmp ax, bx
CPU 执行该指令,会计算 (ax) – (bx) ,然后根据结果对 CPU 的标志寄存器进行设置,那么,我们可以做以下分析:
- 1. 如果 ax = bx,那么 ax – bx = 0,所以,ZF = 1
- 2. 如果 ax != bx,那么 ax – bx != 0,所以,ZF = 0
- 3. 如果 ax < bx,那么 ax – bx < 0,ax 的最高有效位将向假想的更高位借位,所以,CF = 1
- 4. 如果 ax >= bx,那么 ax – bx >= 0,不用借位,所以,CF = 0
- 5. 如果 ax > bx,那么 ax – bx > 0,所以,ZF = 0,不用借位,所以,CF = 0
- 6. 如果 ax <= bx,那么 ax – bx <= 0,这时可能结果为 0 或可能要借位,所以 ZF = 1 或 CF = 1
tips:
关于标志寄存器相关位表示的含义,可以看链接里博文的介绍汇编语言:标志寄存器ZF、PF、SF、CF、OF、DF、IF、AF_汇编pf标志位-CSDN博客
那么对于CPU来说,执行 cmp ax bx 指令后,CPU 就可以通过标志寄存器对应位的值,从而知道比较 ax,bx 的大小的结果。
- 1. 如果 ZF = 1,那么 ax = bx
- 2. 如果 ZF = 0,那么 ax != bx
- 3. 如果 CF = 1,那么 ax < bx
- 4. 如果 CF = 0,那么 ax >= bx
- 5. 如果 CF = 0 && ZF = 0,那么 ax > bx
- 6. 如果 ZF = 1 || CF = 1,那么 ax <= bx
二. je 指令
je(jump equal),等于则转移,检测的相关的标志:ZF = 1。
指令格式:je 标号
示例:
je s ;等于则跳转到 s 标号处执行指令,CPU实际是检测 ZF = 1
assume cs:code, ds:data data segment db 'ax = bx',0 db 'ax != bx',0 data ends code segment start: mov ax, data mov ds, ax mov ax, 3 ;ax = 3 mov bx, 3 ;bx = 3 cmp ax, bx ;计算 ax - bx,并根据结果设置标志寄存器 je ax_e_bx ;等于则跳转,CPU实际是检测 ZF = 1 mov cl, 4 ;红色 call size_str ;计算第一个显示的字符串占用的字节数,结果放在 ax 中 mov si, ax ;si = ax,指向第二个字符串的首地址 jmp short ok ;jmp短转移指令,相当于当前 IP,能转移的范围在:-128 ~ 127,即:IP - 128 ~ IP + 127 这个偏移地址 ax_e_bx: mov cl, 2 ;绿色 mov si, 0 ;指向第一个字符串的首地址 ok: mov dh, 14 ;14行 mov dl, 32 ;32列 call show_str ;显示字符串 mov ax, 4c00h int 21h ;名称:size_str ;功能:求一个以0结尾的字符串的字节数 ;参数:ds:si指向字符串的首地址 ;返回:求的字符串长度存储在 ax 中 size_str: push cx mov ch, 0 mov ax, 1 loop_size_str: mov cl, ds:[si] jcxz ok_size_str inc ax inc si loop loop_size_str ok_size_str: pop cx ret ;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串 ;参数:dh=行号(取值范围:0-24),dl=列号(取值范围:0-79) ; cl=颜色,ds:si指向字符串的首地址 ;返回值:无 show_str: ;B8000h-BFFFFh共32kb,是80 * 25彩色字符模式的显示缓冲区,每页4kb(4000字节),显示器可以显示任意一页的内容。 ;一般情况下,显示第0页的内容, 也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。每行80个字, ;每个字占2个字节,低字节存放字符的assii码,高字节为属性字节。所以每行占160个字节 mov ax, 0B800h ;显示缓冲区段地址 mov es, ax ;行 mov al, 160 ;每行160个字节 mul dh ;8位乘法,一个数默认在al中,另一个在dh中,结果放在ax中 mov bx, ax ;行偏移字节 ;列 mov al, 2 ;一个字占2个字节,低字节存放字符的assii码,高字节为属性字节 mul dl ;8位,乘法,一个数默认在al中,另一个在dl中,结果放在ax中 add bx, ax ;行偏移字节 + 列偏移字节 = 相对于显示缓冲区段地址总的偏移地址 mov ch, 0 mov dl, cl ;循环中需要用到cx寄存器,所以把存放字体属性的字节存放在dl中 loop_show_str: mov cl, ds:[si] jcxz ok_show_str ;cx = 0,跳转到标号处执行,否则,继续顺序往下执行 mov es:[bx], cl mov es:[bx+1], dl inc si add bx, 2 loop loop_show_str ok_show_str: ret code ends end start
三. jne 指令
jne(jump not equal),不等于则转移,检测的相关的标志:ZF = 0。
指令格式:jne 标号
示例:
jne s ;不等于则跳转到 s 标号处执行指令,CPU实际是检测 ZF = 0
assume cs:code, ds:data data segment db 'ax = bx',0 db 'ax != bx',0 data ends code segment start: mov ax, data mov ds, ax mov ax, 3 ;ax = 3 mov bx, 4 ;bx = 4 cmp ax, bx ;计算 ax - bx,并根据结果设置标志寄存器 jne ax_ne_bx ;不等于则跳转,CPU实际是检测 ZF = 0 mov cl, 2 ;绿色 mov si, 0 ;指向第一个字符串的首地址 jmp short ok ;jmp短转移指令,相当于当前 IP,能转移的范围在:-128 ~ 127,即:IP - 128 ~ IP + 127 这个偏移地址 ax_ne_bx: mov cl, 4 ;红色 call size_str ;计算第一个显示的字符串占用的字节数,结果放在 ax 中 mov si, ax ;si = ax,指向第二个字符串的首地址 ok: mov dh, 14 ;14行 mov dl, 32 ;32列 call show_str ;显示字符串 mov ax, 4c00h int 21h ;名称:size_str ;功能:求一个以0结尾的字符串的字节数 ;参数:ds:si指向字符串的首地址 ;返回:求的字符串长度存储在 ax 中 size_str: push cx mov ch, 0 mov ax, 1 loop_size_str: mov cl, ds:[si] jcxz ok_size_str inc ax inc si loop loop_size_str ok_size_str: pop cx ret ;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串 ;参数:dh=行号(取值范围:0-24),dl=列号(取值范围:0-79) ; cl=颜色,ds:si指向字符串的首地址 ;返回值:无 show_str: ;B8000h-BFFFFh共32kb,是80 * 25彩色字符模式的显示缓冲区,每页4kb(4000字节),显示器可以显示任意一页的内容。 ;一般情况下,显示第0页的内容, 也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。每行80个字, ;每个字占2个字节,低字节存放字符的assii码,高字节为属性字节。所以每行占160个字节 mov ax, 0B800h ;显示缓冲区段地址 mov es, ax ;行 mov al, 160 ;每行160个字节 mul dh ;8位乘法,一个数默认在al中,另一个在dh中,结果放在ax中 mov bx, ax ;行偏移字节 ;列 mov al, 2 ;一个字占2个字节,低字节存放字符的assii码,高字节为属性字节 mul dl ;8位,乘法,一个数默认在al中,另一个在dl中,结果放在ax中 add bx, ax ;行偏移字节 + 列偏移字节 = 相对于显示缓冲区段地址总的偏移地址 mov ch, 0 mov dl, cl ;循环中需要用到cx寄存器,所以把存放字体属性的字节存放在dl中 loop_show_str: mov cl, ds:[si] jcxz ok_show_str ;cx = 0,跳转到标号处执行,否则,继续顺序往下执行 mov es:[bx], cl mov es:[bx+1], dl inc si add bx, 2 loop loop_show_str ok_show_str: ret code ends end start
四. jb 指令
jb(jump below),小于则转移,检测的相关的标志:CF = 1。
指令格式:jb 标号
示例:
jb s ;小于则跳转到 s 标号处执行指令,CPU实际是检测 CF = 1
assume cs:code, ds:data data segment db 'ax < bx',0 db 'ax >= bx',0 data ends code segment start: mov ax, data mov ds, ax mov ax, 3 ;ax = 3 mov bx, 4 ;bx = 4 cmp ax, bx ;计算 ax - bx,并根据结果设置标志寄存器 jb ax_b_bx ;小于则跳转,CPU实际是检测 CF = 1 mov cl, 4 ;红色 call size_str ;计算第一个显示的字符串占用的字节数,结果放在 ax 中 mov si, ax ;si = ax,指向第二个字符串的首地址 jmp short ok ;jmp短转移指令,相当于当前 IP,能转移的范围在:-128 ~ 127,即:IP - 128 ~ IP + 127 这个偏移地址 ax_b_bx: mov cl, 2 ;绿色 mov si, 0 ;指向第一个字符串的首地址 ok: mov dh, 14 ;14行 mov dl, 32 ;32列 call show_str ;显示字符串 mov ax, 4c00h int 21h ;名称:size_str ;功能:求一个以0结尾的字符串的字节数 ;参数:ds:si指向字符串的首地址 ;返回:求的字符串长度存储在 ax 中 size_str: push cx mov ch, 0 mov ax, 1 loop_size_str: mov cl, ds:[si] jcxz ok_size_str inc ax inc si loop loop_size_str ok_size_str: pop cx ret ;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串 ;参数:dh=行号(取值范围:0-24),dl=列号(取值范围:0-79) ; cl=颜色,ds:si指向字符串的首地址 ;返回值:无 show_str: ;B8000h-BFFFFh共32kb,是80 * 25彩色字符模式的显示缓冲区,每页4kb(4000字节),显示器可以显示任意一页的内容。 ;一般情况下,显示第0页的内容, 也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。每行80个字, ;每个字占2个字节,低字节存放字符的assii码,高字节为属性字节。所以每行占160个字节 mov ax, 0B800h ;显示缓冲区段地址 mov es, ax ;行 mov al, 160 ;每行160个字节 mul dh ;8位乘法,一个数默认在al中,另一个在dh中,结果放在ax中 mov bx, ax ;行偏移字节 ;列 mov al, 2 ;一个字占2个字节,低字节存放字符的assii码,高字节为属性字节 mul dl ;8位,乘法,一个数默认在al中,另一个在dl中,结果放在ax中 add bx, ax ;行偏移字节 + 列偏移字节 = 相对于显示缓冲区段地址总的偏移地址 mov ch, 0 mov dl, cl ;循环中需要用到cx寄存器,所以把存放字体属性的字节存放在dl中 loop_show_str: mov cl, ds:[si] jcxz ok_show_str ;cx = 0,跳转到标号处执行,否则,继续顺序往下执行 mov es:[bx], cl mov es:[bx+1], dl inc si add bx, 2 loop loop_show_str ok_show_str: ret code ends end start
五. jnb 指令
jnb(jump not below),不小于则转移,检测的相关的标志:CF = 0。
指令格式:jnb 标号
示例:
jnb s ;不小于则跳转到 s 标号处执行指令,CPU实际是检测 CF = 0
assume cs:code, ds:data data segment db 'ax < bx',0 db 'ax >= bx',0 data ends code segment start: mov ax, data mov ds, ax mov ax, 3 ;ax = 3 mov bx, 3 ;bx = 3 cmp ax, bx ;计算 ax - bx,并根据结果设置标志寄存器 jnb ax_nb_bx ;不小于则跳转,CPU实际是检测 CF = 0 mov cl, 2 ;绿色 mov si, 0 ;指向第一个字符串的首地址 jmp short ok ;jmp短转移指令,相当于当前 IP,能转移的范围在:-128 ~ 127,即:IP - 128 ~ IP + 127 这个偏移地址 ax_nb_bx: mov cl, 4 ;红色 call size_str ;计算第一个显示的字符串占用的字节数,结果放在 ax 中 mov si, ax ;si = ax,指向第二个字符串的首地址 ok: mov dh, 14 ;14行 mov dl, 32 ;32列 call show_str ;显示字符串 mov ax, 4c00h int 21h ;名称:size_str ;功能:求一个以0结尾的字符串的字节数 ;参数:ds:si指向字符串的首地址 ;返回:求的字符串长度存储在 ax 中 size_str: push cx mov ch, 0 mov ax, 1 loop_size_str: mov cl, ds:[si] jcxz ok_size_str inc ax inc si loop loop_size_str ok_size_str: pop cx ret ;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串 ;参数:dh=行号(取值范围:0-24),dl=列号(取值范围:0-79) ; cl=颜色,ds:si指向字符串的首地址 ;返回值:无 show_str: ;B8000h-BFFFFh共32kb,是80 * 25彩色字符模式的显示缓冲区,每页4kb(4000字节),显示器可以显示任意一页的内容。 ;一般情况下,显示第0页的内容, 也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。每行80个字, ;每个字占2个字节,低字节存放字符的assii码,高字节为属性字节。所以每行占160个字节 mov ax, 0B800h ;显示缓冲区段地址 mov es, ax ;行 mov al, 160 ;每行160个字节 mul dh ;8位乘法,一个数默认在al中,另一个在dh中,结果放在ax中 mov bx, ax ;行偏移字节 ;列 mov al, 2 ;一个字占2个字节,低字节存放字符的assii码,高字节为属性字节 mul dl ;8位,乘法,一个数默认在al中,另一个在dl中,结果放在ax中 add bx, ax ;行偏移字节 + 列偏移字节 = 相对于显示缓冲区段地址总的偏移地址 mov ch, 0 mov dl, cl ;循环中需要用到cx寄存器,所以把存放字体属性的字节存放在dl中 loop_show_str: mov cl, ds:[si] jcxz ok_show_str ;cx = 0,跳转到标号处执行,否则,继续顺序往下执行 mov es:[bx], cl mov es:[bx+1], dl inc si add bx, 2 loop loop_show_str ok_show_str: ret code ends end start
六. ja 指令
ja(jump above),高于则转移,检测的相关的标志:CF = 0 && ZF = 0。
指令格式:ja 标号
示例:
ja s ;高于则跳转到 s 标号处执行指令,CPU实际是检测 CF = 0 && ZF = 0
assume cs:code, ds:data data segment db 'ax > bx',0 db 'ax <= bx',0 data ends code segment start: mov ax, data mov ds, ax mov ax, 3 ;ax = 3 mov bx, 2 ;bx = 2 cmp ax, bx ;计算 ax - bx,并根据结果设置标志寄存器 ja ax_a_bx ;高于则跳转,CPU实际是检测 CF = 0 && ZF = 0 mov cl, 4 ;红色 call size_str ;计算第一个显示的字符串占用的字节数,结果放在 ax 中 mov si, ax ;si = ax,指向第二个字符串的首地址 jmp short ok ;jmp短转移指令,相当于当前 IP,能转移的范围在:-128 ~ 127,即:IP - 128 ~ IP + 127 这个偏移地址 ax_a_bx: mov cl, 2 ;绿色 mov si, 0 ;指向第一个字符串的首地址 ok: mov dh, 14 ;14行 mov dl, 32 ;32列 call show_str ;显示字符串 mov ax, 4c00h int 21h ;名称:size_str ;功能:求一个以0结尾的字符串的字节数 ;参数:ds:si指向字符串的首地址 ;返回:求的字符串长度存储在 ax 中 size_str: push cx mov ch, 0 mov ax, 1 loop_size_str: mov cl, ds:[si] jcxz ok_size_str inc ax inc si loop loop_size_str ok_size_str: pop cx ret ;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串 ;参数:dh=行号(取值范围:0-24),dl=列号(取值范围:0-79) ; cl=颜色,ds:si指向字符串的首地址 ;返回值:无 show_str: ;B8000h-BFFFFh共32kb,是80 * 25彩色字符模式的显示缓冲区,每页4kb(4000字节),显示器可以显示任意一页的内容。 ;一般情况下,显示第0页的内容, 也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。每行80个字, ;每个字占2个字节,低字节存放字符的assii码,高字节为属性字节。所以每行占160个字节 mov ax, 0B800h ;显示缓冲区段地址 mov es, ax ;行 mov al, 160 ;每行160个字节 mul dh ;8位乘法,一个数默认在al中,另一个在dh中,结果放在ax中 mov bx, ax ;行偏移字节 ;列 mov al, 2 ;一个字占2个字节,低字节存放字符的assii码,高字节为属性字节 mul dl ;8位,乘法,一个数默认在al中,另一个在dl中,结果放在ax中 add bx, ax ;行偏移字节 + 列偏移字节 = 相对于显示缓冲区段地址总的偏移地址 mov ch, 0 mov dl, cl ;循环中需要用到cx寄存器,所以把存放字体属性的字节存放在dl中 loop_show_str: mov cl, ds:[si] jcxz ok_show_str ;cx = 0,跳转到标号处执行,否则,继续顺序往下执行 mov es:[bx], cl mov es:[bx+1], dl inc si add bx, 2 loop loop_show_str ok_show_str: ret code ends end start
七. jna 指令
jna(jump not above),不高于则转移,检测的相关的标志:CF = 1 || ZF = 1。
指令格式:jna 标号
示例:
jna s ;不高于则跳转到 s 标号处执行指令,CPU实际是检测 CF = 1 || ZF = 1
assume cs:code, ds:data data segment db 'ax > bx',0 db 'ax <= bx',0 data ends code segment start: mov ax, data mov ds, ax mov ax, 3 ;ax = 3 mov bx, 3 ;bx = 3 cmp ax, bx ;计算 ax - bx,并根据结果设置标志寄存器 jna ax_na_bx ;不高于则跳转,CPU实际是检测 CF = 1 || ZF = 1 mov cl, 2 ;绿色 mov si, 0 ;指向第一个字符串的首地址 jmp short ok ;jmp短转移指令,相当于当前 IP,能转移的范围在:-128 ~ 127,即:IP - 128 ~ IP + 127 这个偏移地址 ax_na_bx: mov cl, 4 ;红色 call size_str ;计算第一个显示的字符串占用的字节数,结果放在 ax 中 mov si, ax ;si = ax,指向第二个字符串的首地址 ok: mov dh, 14 ;14行 mov dl, 32 ;32列 call show_str ;显示字符串 mov ax, 4c00h int 21h ;名称:size_str ;功能:求一个以0结尾的字符串的字节数 ;参数:ds:si指向字符串的首地址 ;返回:求的字符串长度存储在 ax 中 size_str: push cx mov ch, 0 mov ax, 1 loop_size_str: mov cl, ds:[si] jcxz ok_size_str inc ax inc si loop loop_size_str ok_size_str: pop cx ret ;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串 ;参数:dh=行号(取值范围:0-24),dl=列号(取值范围:0-79) ; cl=颜色,ds:si指向字符串的首地址 ;返回值:无 show_str: ;B8000h-BFFFFh共32kb,是80 * 25彩色字符模式的显示缓冲区,每页4kb(4000字节),显示器可以显示任意一页的内容。 ;一般情况下,显示第0页的内容, 也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。每行80个字, ;每个字占2个字节,低字节存放字符的assii码,高字节为属性字节。所以每行占160个字节 mov ax, 0B800h ;显示缓冲区段地址 mov es, ax ;行 mov al, 160 ;每行160个字节 mul dh ;8位乘法,一个数默认在al中,另一个在dh中,结果放在ax中 mov bx, ax ;行偏移字节 ;列 mov al, 2 ;一个字占2个字节,低字节存放字符的assii码,高字节为属性字节 mul dl ;8位,乘法,一个数默认在al中,另一个在dl中,结果放在ax中 add bx, ax ;行偏移字节 + 列偏移字节 = 相对于显示缓冲区段地址总的偏移地址 mov ch, 0 mov dl, cl ;循环中需要用到cx寄存器,所以把存放字体属性的字节存放在dl中 loop_show_str: mov cl, ds:[si] jcxz ok_show_str ;cx = 0,跳转到标号处执行,否则,继续顺序往下执行 mov es:[bx], cl mov es:[bx+1], dl inc si add bx, 2 loop loop_show_str ok_show_str: ret code ends end start
参考
《汇编语言(第4版)》- 王爽
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/158491.html