emu8086
ASCII表中13表示回车->回到该行的首部。10表示换行->光标在行中的位置不变,移动到下一行
datas segment
string1 db 'Move the cursor backward'
string2 db 'Move the cursor backward'
mess1 db 'Match.',13,10,'$' ;13是回车符,10是换行符的ASCII码,$是字符串结束的标志
mess2 db 'No match',13,10,'$'
datas ends
codes segment
assume cs:codes ,ds:datas ,es:datas
start:
main proc far
push ds ;将ds压栈
sub ax,ax ;将ax置0
push ax ;将0入栈
;push ds
;mov ax,0
;push ax
;……
;ret
;上述指令时配对出现的,和中断调用mov ax 4c00h/int 21h功能相似,实现返回DOS系统的操作
;原理:作为DOS系统,每个EXE文件在执行时被看作DOS的一个子程序,所以有子程序的入口
;此时EXE文件的入口地址CS值和DS值相同,而IP值等于0,所以前面的push ds相当于cs入栈
;而把AX赋0然后入栈,相当于IP入栈。这样当程序最后再执行ret后,就可以返回原DOS系统了
mov ax,datas
mov ds,ax
mov es,ax ;拷贝到附加段
;load effective address 加载有效地址
lea si,string1 ;将string1的有效地址存储到si寄存器中
lea di,string2 ;同上
cld ;在字符串操作中使变址寄存器SI和DI的地址指针自动增加,字符串处理由前往后
mov cx,25 ;字符串的长度为25,比较25次
repz cmpsb ;如果DS:si和ES:di所指向的两个字节相等则继续比较
;repeat when zero flag ZF为0时重复
jz match ;jump when has zero flag,完全匹配时ZF=1,即上一条指令运算结果为0,则跳转
lea dx,mess2 ;jz没有跳转,将No match字符串存储到寄存器dx中
jmp short disp ;段内短跳转
match:
lea dx,mess1 ;将Match字符串存储到寄存器dx中
disp:
mov ah,09 ;dos系统功能调用代码→显示字符串 DS:DX=串地址,字符串以$结尾
int 21H ;调用dos系统功能,计算机会根据AH寄存器中的值调用相应功能 P471
ret ;栈顶字单元出栈,其值赋给IP寄存器,实现程序的转移
main endp
codes ends
end start
一些指令的解释
代码段
push ds
mov ax,0
push ax
……
ret
上述指令时配对出现的,和中断调用mov ax 4c00h/int 21h功能相似,实现返回DOS系统的操作
原理:作为DOS系统,每个EXE文件在执行时被看作DOS的一个子程序,所以有子程序的入口。此时EXE文件的入口地址CS值和DS值相同,而IP值等于0,所以前面的push ds相当于cs入栈。而把AX赋0然后入栈,相当于IP入栈。这样当程序最后再执行ret后,就可以返回原DOS系统了
cmpsb指令
该指令会取出DS:SI和ES:DI所指向的字节进行比较,如果相等则符号位ZF置1。配合repz(repeat when zero flag)指令使用时,当 ZF=1 且 CX!=0 时会重复cmpsb指令
repz指令
当ZF=1 且 CX!=0时则重复
movsb指令的前面只能使用rep前缀,不用repz或repnz前缀,因为movs指令执行后不影响zf标志位。
换句话说,就是在movsb指令的前面使用3个前缀的功能是一样的,结束movsb指令只受CX取值的控制,与ZF无关
验证:
你将ZF标志位设置为1,你执行REPNZ MOVSB指令看,一样的,只受CX取值的控制,与ZF无关。
附:end start表示整个代码文件的结束,此时不论在end start的后边加什么内容,软件都不会将其编译。