学 Win32 汇编[29] - 串指令: MOVS*、CMPS*、SCAS*、LODS*、REP、REPE、REPNE 等


这里的 "串" 并不单指字符串, 包括所有连续的数据(如数组); 串指令只用于内存操作.


移动串指令: MOVSB、MOVSW、MOVSD ;从 ESI -> EDI; 执行后, ESI 与 EDI 的地址移动相应的单位

比较串指令: CMPSB、CMPSW、CMPSD ;比较 ESI、EDI; 执行后, ESI 与 EDI 的地址移动相应的单位

扫描串指令: SCASB、SCASW、SCASD ;依据 AL/AX/EAX 中的数据扫描 EDI 指向的数据, 执行后 EDI 自动变化

储存串指令: STOSB、STOSW、STOSD ;将 AL/AX/EAX 中的数据储存到 EDI 给出的地址, 执行后 EDI 自动变化

载入串指令: LODSB、LODSW、LODSD ;将 ESI 指向的数据载入到 AL/AX/EAX, 执行后 ESI 自动变化



其中的 B、W、D 分别指 Byte、Word、DWord, 表示每次操作的数据的大小单位.



上述指令可以有重复前缀:

REP             ECX > 0 时

REPE (或 REPZ)  ECX > 0 且 ZF=1 时

REPNE(或 REPNZ) ECX > 0 且 ZF=0 时

;重复前缀可以自动按单位(1、2、4)递减 ECX


 
   

MOVSB: 移动字符串

; Test29_1.asm

.386

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    szSource db 'Delphi 2010', 0 

    len      equ $ - szSource - 1

    szDest   db len dup(?), 0

.code

main proc

    lea esi, szSource

    lea edi, szDest

    mov ecx, len

    cld ;复位标志寄存器的方向标志, 以让串地址由低到高

    rep movsb

    PrintString szDest ;Delphi 2010

    ret

main endp

end main


 
   

上面的例子, 假如不使用重复前缀...

; Test29_2.asm

.386

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    szSource db 'Delphi 2010', 0 

    len      equ $ - szSource - 1

    szDest   db len dup(?), 0

.code

main proc

    lea esi, szSource

    lea edi, szDest

    mov ecx, len

    cld

@@: movsb

    dec ecx

    jnz @B

    PrintString szDest

    ret

main endp

end main


 
   

MOVSD 例:

; Test29_3.asm

.386

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    ddSource dd 11h,22h,33h

    ddDest   dd lengthof ddSource dup(?)

.code

main proc

    lea esi, ddSource

    lea edi, ddDest

    mov ecx, lengthof ddSource

    cld

    rep movsd

    DumpMem offset ddDest, sizeof ddDest ;11 00 00 00 - 22 00 00 00 - 33 00 00 00

    ret

main endp

end main


 
   

MOVSW 例:

; Test29_4.asm

.386

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    ddSource dw 11h,22h,33h

    ddDest   dw lengthof ddSource dup(?)

.code

main proc

    lea esi, ddSource

    lea edi, ddDest

    mov ecx, lengthof ddSource

    cld

    rep movsw

    DumpMem offset ddDest, sizeof ddDest ;11 00 22 00 - 33 00 00 00

    ret

main endp

end main


 
   

CMPSD 例:

; Test29_5.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    ddVal1 dd 1234h

    ddVal2 dd 5678h

.code

main proc

    lea esi, ddVal1

    lea edi, ddVal2

    cmpsd

    je L1

    PrintText '两数不等'

    jmp L2

L1: PrintText '两数相等'

L2: ret

main endp

end main


 
   

CMPSW 例:

; Test29_6.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    dwArr1 dw 1,2,3,4,5

    dwArr2 dw 1,3,5,7,9

.code

main proc

    lea esi, dwArr1

    lea edi, dwArr2

    mov ecx, lengthof dwArr1

    cld

    repe cmpsw

    je L1

    PrintText '两数组不等'

    jmp L2

L1: PrintText '两数组相等'

L2: ret

main endp

end main


 
   

对比数组时, 假如数组长度不一致...

; Test29_7.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    dwArr1 dw 1,2,3,4,5

    dwArr2 dw 1,2,3,4,5,6

.code

main proc

    lea esi, dwArr1

    lea edi, dwArr2

    mov ecx, lengthof dwArr1

    cmp ecx, lengthof dwArr2

    jne L1

    cld

    repe cmpsw

    jne L1

    PrintText '两数组相等'

    jmp L2

L1: PrintText '两数组不等'

L2: ret

main endp

end main


 
   

如果对比的是 0 结束的字符串, 长度不一致也不用考虑

; Test29_8.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    szText1 db 'Delphi 2010', 0

    szText2 db 'Delphi 2011', 0

.code

main proc

    lea esi, szText1

    lea edi, szText2

    mov ecx, lengthof szText1

    cld

    repe cmpsb

    je L1

    PrintText '字符串不同'

    jmp L2

L1: PrintText '字符串相同'

L2: ret

main endp

end main


 
   

SCASB 例:

; Test29_9.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    szText db 'ABCDEFGH', 0

.code

main proc

    lea edi, szText

    mov al, 'F'

    mov ecx, lengthof szText - 1

    cld

    repne scasb

    je L1

    PrintText '没找到'

    jmp L2

L1: sub ecx, lengthof szText - 1

    neg ecx

    PrintDec ecx ;如果找得到, 这里显示是第几个字符; 本例结果是 6

L2: ret

main endp

end main


 
   

STOSB 例:

; Test29_10.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    len = 31

    szText db len dup(0), 0

.code

main proc

    lea edi, szText

    mov al, 'x'

    mov ecx, len

    cld

    rep stosb

    PrintString szText ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    ret

main endp

end main


 
   

LODSW 例: 数组求和

; Test29_11.asm

.386p

.model flat, stdcall



include    windows.inc

include    kernel32.inc

include    masm32.inc

include    debug.inc

includelib kernel32.lib

includelib masm32.lib

includelib debug.lib



.data

    dwArr dw 1,2,3,4,5,6,7,8,9,10

.code

main proc

    lea esi, dwArr

    mov ecx, lengthof dwArr

    xor edx, edx

    xor eax, eax

@@: lodsw

    add edx, eax

    loop @B

    PrintDec edx ;55

    ret

main endp

end main


 
   

你可能感兴趣的:(Win32)