Assembly Loop
我覺得循環指令是程序的核心,是計算機不厭其煩地執行機械、重復枯燥勞動的基礎。本文來學習下匯編程序中的LOOP指令。Loop指令的格式是:loop 標號,CPU執行loop指令的時候,要進行兩步操作:
v (cx)=(cx)-1
v 判斷cx中的值,不為零則轉到標號處執行程序,如果為零則向下執行。
由上可知,cx中的值影響著loop指令的執行結果。通常我們用loop指令來實現循環功能,用cx來存放循環次數。類似于C中的for循環:
for (int i = cx; i != 0; --i)
{
}
{
}
學習了loop后,想著把原來那個輸出WELCOME TO ASM!的程序修改下,利用循環來實現。
assume cs:codeseg
codeseg segment
;WELCOME TO ASM! (15)
dw 0257h,0245h,034ch,0443h,054fh,064dh,0745h,0220h,0854h,094fh,0220h,1241h,1353h,144dh,1521h
mov bx,0b800h
mov ds,bx
mov bx,0
mov cx,15
output: mov ax,cs:[bx]
mov ds:[bx],ax
add bx,2
loop output
mov ax,4c00h
int 21h
codeseg ends
end
codeseg segment
;WELCOME TO ASM! (15)
dw 0257h,0245h,034ch,0443h,054fh,064dh,0745h,0220h,0854h,094fh,0220h,1241h,1353h,144dh,1521h
mov bx,0b800h
mov ds,bx
mov bx,0
mov cx,15
output: mov ax,cs:[bx]
mov ds:[bx],ax
add bx,2
loop output
mov ax,4c00h
int 21h
codeseg ends
end
改成這樣后,編譯、連接成功,但是程序運行時好像進入了死循環。最后看書中的描述才找到了原因:那是因為用dw在代碼段定義了數據后,當程序運行時IP指向的是數據部分,并不是指令部分,所以導致運行出錯。使程序成功運行的方法有可以在debug中手動修改IP,使其指向真正的指令開始的地方,可是這樣一來程序只能在debug中才能正確運行。如何讓程序編譯、連接后可以在系統中直接運行呢?我們可以在源碼中指定程序的入口所在,即在源碼的第一條指令的前面加上一個標號main,而這個標號在偽指令end的后面出現。因為我覺得這有點像C中的main函數,所以將這個標號命名為main,修改程序后程序運行正確:
assume cs:codeseg
codeseg segment
;WELCOME TO ASM! (15)
dw 0257h,0245h,034ch,0443h,054fh,064dh,0745h,0220h,0854h,094fh,0220h,1241h,1353h,144dh,1521h
main: mov bx,0b800h
mov ds,bx
mov bx,0
mov cx,15
output: mov ax,cs:[bx]
mov ds:[bx],ax
add bx,2
loop output
mov ax,4c00h
int 21h
codeseg ends
end main
codeseg segment
;WELCOME TO ASM! (15)
dw 0257h,0245h,034ch,0443h,054fh,064dh,0745h,0220h,0854h,094fh,0220h,1241h,1353h,144dh,1521h
main: mov bx,0b800h
mov ds,bx
mov bx,0
mov cx,15
output: mov ax,cs:[bx]
mov ds:[bx],ax
add bx,2
loop output
mov ax,4c00h
int 21h
codeseg ends
end main
程序運行結果如下圖所示:
綜上所述,將數據放到代碼段CS中時,會導致IP還是指向的CS的開始部分,而起始部分并不是指令,而是數據,從而導致程序直接運行時出現問題。為了解決這個問題,可以在指令起始的地方加個標號,這樣就好了。