文中提到的指令为8086指令,环境为emu8086,本文若有不当之处欢迎提出,共同探讨!
指令[1]:movsb 与rep指令结合使用
曾有一头傻狗问我:mov指令是干啥用的捏?
我如此回答他:mov可以移动立即数到内存(除CS/DS可能还有其他)/寄存器,或者把内存移到寄存器(可以互换),或者把寄存器移到寄存器(这里面mov指令的移动方向可能出错,如果有疑问请提出!)
傻狗继续说道:建议你写个博客哇
我:本文遂产生
在mov指令使用时,俺总是觉得在内存之间移动数据非常复杂,需要使用寄存器作为中间媒介,但是今天学到了movsb指令,感觉还不错哈哈!废话少说,请移步下文:
movsb格式为:
movsb
没有操作数,而移动的东西是事先放在SI和DI寄存器里面的东西,S 可以理解为source也就是源操作数,而D 可以理解成destination,也就是目的操作数
注意:这里的SI和DI是源地址是DS:SI,目的地址是ES:DI
移动错误需要重新检查DS 和ES
将数据段地址取出放在里面就可以
形如
lea si data1
lea di data2
lea是取有效地址的意思(Load Effective Address)
data1,data2可以如下定义
data segment
data1 db 12h
db 34h
db 56h
db 78h
db 12h
db 34h
db 56h
db 78h
data2 db 10h
db 12h
db 56h
db 13h
db 10h
db 12h
db 56h
db 13h
ends
在比较的过程中需要设置行进方向,是增方向还是减方向
也就是是按照从小到大的顺序赋值,还是从大到小
由于8086的栈是向大地址方向增长的所以,增方向就是从小到大,D标志如果是0是增方向,是1为减,利用指令CLD为清零(clear D)利用STD是置位1
接下来有个疑问是,他每一次操作要么移动一个字节,要么是一个字,万一我想移动100个字节,每次都写循环(LOOP ,JMP)不是很麻烦,所以发明出了rep指令
和Loop差不多,在cx里面放置要循环的次数,然后执行即可,形如
mov cx,50
rep movsb;执行50次
他的循环是while循环(非do while)也就是
while(cx!=0);CX==1的时候能执行,0的时候就跳出来了
指令[2]: cmpsb与rep指令结合使用
cmpsb是用来比较的指令,有cmpsw和cmpsb分别是比较字节
使用repe循环是相等循环,repne是不相等循环,同样是while循环,条件是cx!=0&&(e或ne)
下面代码实现的功能是扫描,将不相等的di全部换成si
; multi-segment executable file template.
data segment
; add your data here!
pkey db "press any key...$"
data1 db 12h
db 34h
db 56h
db 78h
db 12h
db 34h
db 56h
db 78h
data2 db 10h
db 12h
db 56h
db 13h
db 10h
db 12h
db 56h
db 13h
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data;这里data算是一个立即数
mov ds, ax
mov es, ax
; add your code here
mov cx,8
lea si,data1
lea di,data2
CLD
x:
rep cmpsb
dec si;这里是找到刚才不相等的字符
dec di
movsb
jcxz y;这句话不能放在rep后面,是因为最后一个字符可能不相等,如果放在rep后面可能就赋不了值了
inc cx;因为在rep里面废掉了一个cx
Loop x
y:
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start ; set entry point and stop the assembler.