微机原理实验二、编写一个程序,要求比较两个字符串STRING1和STRING2所含的字符是否相同,相同则显示“MATCH”,若不同则显示“NO MATCH”
实验目标:
编写一个程序,要求比较两个字符串STRING1和STRING2所含的字符是否相同,相同则显示“MATCH”,若不
同则显示“NO MATCH”
文章目录
- 微机原理实验二、编写一个程序,要求比较两个字符串STRING1和STRING2所含的字符是否相同,相同则显示“MATCH”,若不同则显示“NO MATCH”
- 一、 写在程序开头的段寄存器设置
- 二、 自动进行重复比较--repz cmpsb
- 三、 跳转指令
- LEA 地址传送指令
- 四、 实现的汇编代码
- 实现程序的完整代码一(字符串是程序运行前设置的)
- 4.2 实现程序的完整代码二(字符串是运行后由键盘输入的)
一、 写在程序开头的段寄存器设置
MOV AX,DATAMOV DS,AXMOV ES,AX
这段代码用于设置数据段寄存器(DS)和附加段寄存器(ES)的值。在8086汇编语言中,数据段寄存器(DS)和附加段寄存器(ES)通常需要设置为相同的值,以确保程序能够正确访问数据段中的数据。这是因为在实模式下,DS和ES寄存器通常被用于存储数据段的地址。
具体来说:
MOV AX, DATA
:将数据段的段地址加载到AX寄存器中。MOV DS, AX
:将AX寄存器中的数据段地址设置到DS寄存器,以便程序能够访问数据段中的数据。MOV ES, AX
:将AX寄存器中的数据段地址设置到ES寄存器。在本例中,ES寄存器没有被程序使用,这是一个常见的做法,因为大多数情况下,DS和ES寄存器都被设置为相同的值。
总的来说,这段代码确保了程序在实模式下正确地访问了数据段中的数据。
二、 自动进行重复比较–repz cmpsb
当使用REPZ CMPSB
指令时,通常会结合使用DI
和 SI
寄存器来比较两个字符串。以下是 REPZ CMPSB 指令的一般用法和相关寄存器的作用:
-
DI 寄存器(Destination Index):DI 寄存器通常用于存储目标字符串的地址。在 REPZ CMPSB 指令中,DI 寄存器指向第一个字符串(目标字符串)的起始位置,它会在比较过程中自动递增(如果 DF 标志位未设置)或递减(如果 DF 标志位被设置)。
-
SI 寄存器(Source Index):SI 寄存器通常用于存储源字符串的地址。在 REPZ CMPSB 指令中,SI 寄存器指向第二个字符串(源字符串)的起始位置,它会在比较过程中自动递增(如果 DF 标志位未设置)或递减(如果 DF 标志位被设置)。
-
CX 寄存器(Count):CX 寄存器用于存储重复执行 REPZ CMPSB 指令的次数。在 REPZ CMPSB 指令中,CX 寄存器的值决定了比较操作的重复次数。指令会反复执行直到 CX 寄存器的值减为零,或者比较操作不满足条件时停止。
-
DF 标志位(Direction Flag):DF 标志位决定了 REPZ CMPSB 指令中地址寄存器 DI 和 SI 的自动递增或递减方向。如果 DF 标志位被设置(值为 1),地址寄存器 DI 和 SI 会递减;如果 DF 标志位未设置(值为 0),地址寄存器 DI 和 SI 会递增。在比较字符串时,通常 DF 标志位会被设置为 0,以便使地址寄存器 DI 和 SI 自动递增。
总体来说,REPZ CMPSB 指令用于比较两个字符串的内容。它会从 DI 和 SI 指向的内存位置开始逐字节地比较两个字符串,直到两个字符串中的字节不相等、其中一个字符串的结束标志(通常是空字符或换行符),或者重复比较的次数达到 CX 寄存器的值为止。比较的结果可以根据 ZF 标志位的状态来确定:如果 ZF 标志位被设置(值为 1),则表示两个字符串完全相同;如果 ZF 标志位未设置(值为 0),则表示两个字符串至少有一个字节不相同。
三、 跳转指令
当处理字符串比较时,通常需要根据比较的结果来执行不同的操作。在汇编语言中,使用条件跳转指令来实现这种根据条件执行跳转的功能。jz
和 jnz
就是其中两个条件跳转指令,它们分别代表“跳转如果零标志位被设置”和“跳转如果零标志位未被设置”。
-
JZ(Jump if Zero):
jz
指令用于在零标志位(ZF)被设置时执行跳转。ZF 标志位表示上一条指令的运算结果是否为零。如果 ZF 被设置(值为 1),则表示上一条指令的结果为零,此时jz
指令会跳转到指定的目标地址执行;如果 ZF 未被设置(值为 0),则jz
指令不会跳转,而是继续执行下一条指令。 -
JNZ(Jump if Not Zero):
jnz
指令与jz
相反,它用于在零标志位未被设置时执行跳转。如果 ZF 未被设置(值为 0),则表示上一条指令的结果不为零,此时jnz
指令会跳转到指定的目标地址执行;如果 ZF 被设置(值为 1),则jnz
指令不会跳转,而是继续执行下一条指令。
在字符串比较的例子中,jz match
表示如果两个字符串完全相同(ZF 被设置),则跳转到标签 match
执行相应的操作;而 jnz nomatch
表示如果两个字符串至少有一个字节不相同(ZF 未被设置),则跳转到标签 nomatch
执行相应的操作。这样可以根据比较的结果来决定程序的执行流程。
除了
jz
和jnz
之外,汇编语言还提供了其他条件跳转指令,用于根据不同的条件进行跳转。以下是一些常见的条件跳转指令及其含义:
- JA(Jump if Above):如果无符号数A大于B,则执行跳转。
- JAE(Jump if Above or Equal):如果无符号数A大于等于B,则执行跳转。
- JB(Jump if Below):如果无符号数A小于B,则执行跳转。
- JBE(Jump if Below or Equal):如果无符号数A小于等于B,则执行跳转。
- JE(Jump if Equal):如果两个数相等,则执行跳转。
- JNE(Jump if Not Equal):如果两个数不相等,则执行跳转。
- JG(Jump if Greater):如果有符号数A大于B,则执行跳转。
- JGE(Jump if Greater or Equal):如果有符号数A大于等于B,则执行跳转。
- JL(Jump if Less):如果有符号数A小于B,则执行跳转。
- JLE(Jump if Less or Equal):如果有符号数A小于等于B,则执行跳转。
- JMP:无条件地改变程序的执行流程
这些条件跳转指令可以根据不同的比较条件来进行跳转,从而实现根据不同情况执行不同的操作。
LEA 地址传送指令
LEA
指令(Load Effective Address)是用于加载有效地址的指令,它将某个内存地址的偏移量加载到目标操作数中,而不是将内存地址中的内容加载到目标操作数中。
LEA
指令的语法格式如下:
LEA 目标操作数, 源操作数
其中,目标操作数是一个通用寄存器,用于存储源操作数的有效地址。源操作数可以是一个内存地址、寄存器或常数。
LEA
指令的主要作用是计算内存地址,将地址的偏移量加载到目标操作数中。它不会访问内存,只是执行简单的地址计算。
例如,假设有一个变量 var
存储在内存地址 0x1000
处,要将该地址的偏移量加载到 BX
寄存器中,可以使用以下 LEA
指令:
LEA BX, var
在这个示例中,LEA BX, var
指令将变量 var
的地址 0x1000
的偏移量加载到 BX
寄存器中,而不是将 var
的值加载到 BX
寄存器中。
LEA
指令常用于计算数组元素的地址、构建复杂的内存地址表达式以及进行一些与内存地址相关的操作。
四、 实现的汇编代码
实现程序的完整代码一(字符串是程序运行前设置的)
实现效果图:
;#########################################################################
; @Description: 编写一个程序,要求比较两个字符串STRING1和STRING2所含的字符是否相同,
; 相同则显示“MATCH”,若不同则显示“NO MATCH”
;* @Version: 1.0
;* @Autor: Huining Li777
;* @运行:Please input a string: asd(回车)
; Please input a string: asd(回车)
; MATCH
;#########################################################################; 比较两个字符串所含的字母是否相同,若相同则显示"MATCH",不同显示"NO MATCH"DATA SEGMENT
str1 db 'Hhhhhha'
str2 db 'Hhhhhhh'
str3 db 'match',10,'$'
str4 db 'No match',10,'$' ;10是换行符,13是回车,$表示字符串结束
DATA ENDSCODE SEGMENTASSUME DS:DATA,CS:CODE
START:MOV AX,DATAMOV DS,AXMOV ES,AXmov cx,100;比较100次,若字符串长度大于了一百,则会比较错误lea di,str1;将字符串str1的地址送入dilea si,str2;将字符串str2的地址送入sirepz cmpsb;重复比较,就是比较每一个字符jz match;相同则转移jnz nomatch;不相同则转移
match:lea dx,str3;将提示内容送入dxmov ah,09h;输出int 21hjmp exit
nomatch:lea dx,str4;将提示内容送入dxmov ah,09h;输出int 21hjmp exitexit:;退出mov ah,4chint 21h
code ends
end start
4.2 实现程序的完整代码二(字符串是运行后由键盘输入的)
实现效果图:
DATA SEGMENTinput_buffer DB 100 DUP('$') ; 用于存储输入的字符串,假设最大长度为 100str1 DB 100 DUP('$') ; 存储输入的字符串 str1str2 DB 100 DUP('$') ; 存储输入的字符串 str2str3 DB 'MATCH', 10, '$' ; 匹配提示字符串str4 DB 'NO MATCH', 10, '$' ; 不匹配提示字符串prompt_input DB 'Please input a string: $' ; 输入提示文字
DATA ENDSCODE SEGMENTASSUME DS:DATA, CS:CODE
START:MOV AX, DATAMOV DS, AXMOV ES, AX; 读取第一个字符串MOV DX, OFFSET prompt_inputMOV AH, 09HINT 21HCALL read_input1; 读取第二个字符串MOV DX, OFFSET prompt_inputMOV AH, 09HINT 21HCALL read_input2; 比较两个字符串LEA DI,OFFSET str1LEA SI,OFFSET str2MOV CX, 100 ; 假设最大比较次数为 100REPE CMPSBJZ matchJMP nomatch; 如果循环结束,表示两个字符串完全相等MOV DX, OFFSET str3JMP print_resultmatch:MOV DX, OFFSET str3JMP print_resultnomatch:MOV DX, OFFSET str4print_result:MOV AH, 09HINT 21H; 退出程序MOV AH, 4CHINT 21H
;------------------read1--------------------------------
read_input1 PROCMOV SI, 0
read_loop1:MOV AH, 01HINT 21HCMP AL, 0DHJE end_read1MOV input_buffer[SI], ALINC SIJMP read_loop1
end_read1:MOV CX, SIMOV SI, 0MOV DI, OFFSET str1REP MOVSBRET
read_input1 ENDP
;------------------read2----------------
read_input2 PROCMOV SI, 0
read_loop2:MOV AH, 01HINT 21HCMP AL, 0DHJE end_read2MOV input_buffer[SI], ALINC SIJMP read_loop2
end_read2:MOV CX, SIMOV SI, 0MOV DI, OFFSET str2REP MOVSBRET
read_input2 ENDPCODE ENDS
END START