MOV
传送指令,通过对第二个操作数(源操作数)直接寻址或间接寻址,放到第一个操作数(目的操作数)直接寻址或者间接寻址的位置
示例1:将常量2放到eax寄存器中
mov eax,2
示例:将eax中的内容,放到ebx寄存器中
mov ebx,eax
示例2:ebx中的内容是个地址,将eax中的值,放到ebx这个地址处
.data
value1 byte 1
.code
mov ebx,offset s
mov eax,11;十六进制的A
mov [ebx],eax;间接寻址
MOVSB(32位CPU)
若想使用MOVSB指令,则ESI,EDI两个寄存器中必须存放的是内存地址,将ESI指向的地址数据,复制到EDI指向的地址,具体复制多长的数据,取决于ECX中的值,MOVSB中的’B’表示byte,一次复制1个字节,复制ECX个字节
示例3:按照单字节将字符串"ABCDE"从一个地址复制到另一个地址
.data
s1 byte "abcde"
s2 byte sizeof s1 dup(1)
.code
mov esi,offset s1
mov edi,offset s2
mov ecx, sizeof s1
;rep叫做重复前缀,配合movsb,因为就movsb本身来说,它只是处理一次
;rep重复次数取决于ecx里的值
;如果删掉rep,则会发现只复制了一个字母'A'
rep movsb;本行走完可查看edi的间接地址
示例4:按照单字节将字符串"ABCD"从一个地址复制到另一个地址
.data
s1 dword "abcd"
s2 byte 0
.code
mov esi,offset s1
mov edi,offset s2
mov ecx, 4
;执行完毕之后会发现依然成功的复制了s1,虽然s1和s2初始类型不同
;毕竟是单字节,可以组成任何字节
rep movsb
MOVSB(16位CPU)
使用DS:SI和ES:DI,稍有不同的是DI使用ES作为段地址,下面的代码会在电脑开机的时候屏幕上显示“FUCK-Xuyan”
jmp showFuckXuyan
xuyan db 'F',7fh,'U',7fh,'C',7fh,'K',7fh,'-',7fh
db 'X',7fh,'u',7fh,'Y',7fh,'a',7fh,'n',7fh
showFuckXuyan:
mov ax,0b800h
mov es,ax;段寄存器不能直接放立即数,必须通过通用寄存器才行
mov di,0
mov ax,7c0h
mov ds,ax
mov si,xuyan
mov cx,20
rep movsb
jmp $
times 510-($-$$) db 0
dw 0AA55h
MOVSW
若想使用MOVSW指令,则ESI,EDI两个寄存器中必须存放的是内存地址,将ESI指向的地址数据,复制到EDI指向的地址,具体复制多长的数据,取决于ECX中的值,MOVSW中的’W’表示word,一次复制2个字节,复制的字节数=ECX乘以2
示例5:按照双字节将字符串"CD"从一个地址复制到另一个地址
.data
s1 dword "abcd"
s2 byte 0
.code
mov esi,offset s1
mov edi,offset s2
mov ecx, 1
;下面这行代码走完,观察edi处,可发现只复制了dc
;因为只复制一次,且movsw是双字节复制
rep movsw
MOVSD
若想使用MOVSD指令,则ESI,EDI两个寄存器中必须存放的是内存地址,将ESI指向的地址数据,复制到EDI指向的地址,具体复制多长的数据,取决于ECX中的值,MOVSD中的’D’表示dword,一次复制4个字节,复制的字节数=ECX乘以4
示例6:按照4字节将字符串"ABCD"从一个地址复制到另一个地址
.data
s1 dword "abcd"
s2 byte 0
.code
mov esi,offset s1
mov edi,offset s2
;下面这行代码走完,观察edi处,可发现只复制了abcd
;没有rep指令,所以只复制一次,4个字节
movsw
REP/REPZ/REPE/REPNZ/REPNE
上述示例中使用了REP,可以得知,REP会取ECX寄存器中的值作为复制次数,所以可以说,ECX>0就是REP成立的条件
指令名称 | 条件 |
---|---|
REP | ECX>0 |
REPZ/REPE | 依次对比每一位,当遇到不同,或者ECX=0,则计算结果 |
REPNZ/REPNE | 依次对比每一位,当遇到相同,或者ECX=0,则计算结果 |