Loop 是反復執行;
從哪反復? 這要用到 "標號";
反復幾次? 把反復的次數告訴 ECX 寄存器即可.
笨辦法計算 3 * 8 = 24
; Test15_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
val dd 3
.code
main proc
xor eax, eax
add eax, val
add eax, val
add eax, val
add eax, val
add eax, val
add eax, val
add eax, val
add eax, val
PrintDec eax ;24
ret
main endp
end main
使用 LOOP 和標號:
; Test15_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
val dd 3
.code
main proc
xor eax, eax
mov ecx, 8
L1: ;命名為 "L1" 的標號
add eax, val
loop L1 ;反復到指定標號; 每次反復 ecx 會減 1, 直到 ecx 為 0 才向下執行
PrintDec eax ;24
ret
main endp
end main
數組求和的例子:
; Test15_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
ddArr dd 1,2,3,4,5
.code
main proc
lea edi, ddArr ;把數組起始地址給一個寄存器
mov ecx, lengthof ddArr ;把數組元素數(將要反復的次數)給 ECX
xor eax, eax
L1:
add eax, [edi] ;edi 中的地址將不斷變化, 通過 [edi] 獲取元素值
add edi, type ddArr ;獲取下一個元素的地址
loop L1
PrintDec eax ;15
ret
main endp
end main
復制字符串的例子:
; Test15_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
szSource db 'Hello World!', 0 ;定義源字符串
szDest db sizeof szSource dup(0) ;定義相同大小的目的字符串
.code
main proc
mov esi, 0 ;這裡選擇使用 esi 做數組索引
mov ecx, sizeof szSource ;這是要循環的次數
L1:
mov al, szSource[esi] ;mov 的操作數不允許兩個都是變量, 用 al 中轉一下
mov szDest[esi], al ;
inc esi ;調整索引
loop L1
PrintString szDest ;Hello World!
ret
main endp
end main
如果僅僅是復制字符串, 可以使用聲明在 masm32.inc 中的 szCopy 函數:
; Test15_5.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 'Hello World!', 0
szDest db sizeof szSource dup(0)
.code
main proc
invoke szCopy, addr szSource, addr szDest
PrintString szDest ;Hello World!
ret
main endp
end main
關於 @@、@B、@F:
; 如果懶得給標號取名, 可以使用 @@ 做標號;
; @B 表示前面最近的一個標號、@F 表示後面最近的一個標號;
; 使用 @@ 可以把前面 3*8=24 的例子修改如下:
; Test15_6.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
val dd 3
.code
main proc
xor eax, eax
mov ecx, 8
@@:
add eax, val
loop @B
PrintDec eax ;24
ret
main endp
end main
關於全局標號:
; 上面例子中的標號都是局部標號;
; 如果一個標號定義在子過程之外, 那它就是全局標號了.
; 能不能在子過程中定義全局標號呢? 後面加兩個 : 就是了.
; Test15_7.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
val dd 3
.code
MyProc proc
Label1:: ;是 Label1:: 而不是 Label1:
PrintText 'MyProc'
ret
MyProc endp
main proc
PrintText 'main'
jmp Label1 ;jmp 是無條件跳轉指令
ret
main endp
end main