9-常用的彙編指令
1. 邏輯運算指令
在組合語言中邏輯運算指令有:與運算指令,或運算指令,非運算指令,異或運算指令。分別用and、or、not、xor來表示。
以and指令舉例:
mov ax,0xFFFF ;ax=1111 1111 1111 1111 mov bx,0xF0F0 ;bx=1111 0000 1111 0000 and ax,bx ;ax和bx進行與運算,將結果賦值給ax 上面三條指令相當於: 1111 1111 1111 1111 and 1111 0000 1111 0000 ___________________________ 1111 0000 1111 0000
ax的結果轉換為十六進位制0xF0F0。
以xor指令為例:
mov ax,0x1234 ;ax=0001 0010 0011 0100
xor ax,ax ;將ax與自己做異或運算,將結果賦值給ax
上面的指令相當於:
0001 0010 0011 0100
xor 0001 0010 0011 0100
_______________________________
0000 0000 0000 0000
ax的結果為0x0000
or指令和not指令都是類似的......
2. 算術運算指令
我們知道add指令是用於加法運算的,而sub指令則正好相反,它是用於做減法運算的。
dec指令是用於自減一的
mov ax 0x001
dec ax ;執行完這條指令後,暫存器ax的內容就會減一
inc指令同dec指令相反,是用於自增一的,也就是說,執行完inc指令後,對應的暫存器裡的內容就會+1。
3. 用於重複執行的指令——loop
loop指令可以把一段程式碼重複執行多次。
執行loop指令的時候會做兩件事:
- 將暫存器CX的內容減一
- 如果CX的內容不為0,轉移到指定的位置處執行,如果cx中的值為0則向下執行其他的指令
彙編程式碼如下:
;檔名004.asm ;說明:loop指令示例 mov ax,0x00 ;ax的初值為0 mov cx,0x5 ;暫存器cx裡存放的就是迴圈次數 mark: ;inc指令會讓暫存器ax的內容每次自增1,這一段就是我們要重複執行的程式碼,即迴圈體 inc ax ;判斷cx , 如果不為0那麼跳轉到迴圈體繼續執行 loop mark ;如果cx為0,則往下順序執行其他指令 times 510-($-$$) db 0x00 db 0x55,0xAA
執行結果:
我們可以看到暫存器AX的內容以及自增到5了,當暫存器cx的值為0後就不再跳轉到迴圈體執行了,而是往下順序執行其他指令。
另外,loop指令每次跳轉的時候都會修改IP暫存器裡的值,大家在除錯的時候注意觀察,當執行loop,-3指令時就會跳轉到0x7c06的位置執行迴圈體,那到底是怎麼跳轉的呢?
首先我們知道loop,-3指令佔用2位元組,並且它的起始地址為0x7c07,當執行完這條指令後,IP暫存器就會變成0x7c09,然後0x7c09減3就可以得出相對位置0x7c06了,因為這裡cs地址為0,所以把cs和ip組合計算出實體地址就是0x7c06。當然,這個相對地址實際上是由編譯器計算出來的。
4. 用loop指令優化程式碼
之前學習了一個loop指令,loop指令是目前為止比較複雜的一個指令,說它複雜是相對jmp、mov、add、inc、dec這樣的指令來說。loop指令在執行時會把cx減1,檢測cx是否為0,決定接下來是否要修改IP暫存器的值來實現跳轉。
計算機本來就非常擅長做一些重複性高的事情,有時候我們在編寫程式時為了完成某一件事情會出現很多重複性的程式碼,例如第7篇我們寫的第一個彙編程式,其中有些程式碼是完全可以優化的,而接下來我們要學習如何使用loop指令進行優化程式碼。
在此之前,我們需要用到兩個新的暫存器:si (Source Index)和di (Destination Index) 。si暫存器表示源地址的意思,di表示目的地址的意思。
彙編程式碼如下:
;檔名:005.asm
;說明:loop指令優化
;指定視訊記憶體段
mov ax,0xB800
mov es,ax
;指定資料段
mov ax,0x07C0
mov ds,ax
mov cx,code-string ;指定迴圈次數
mov si,0 ;初始化資料段 偏移暫存器
mov di,0 ;初始化顯示段 偏移暫存器
jmp 0x07C0:code
string:
db 'hello world'
;因為我們最終是要把資料段裡的資料存到視訊記憶體段裡
;所以在si源地址指定為資料段,di目的地址指定為視訊記憶體段
;而下面這段程式碼就是從資料段中迴圈取出資料放到視訊記憶體段裡
code:
mov al,[ds:string+si]
mov byte [es:di],al
inc di
mov byte [es:di],0x07 ;白底黑字
inc si
inc di
loop code ;繼續迴圈
end:
jmp 0x07C0:end
times 510-($-$$) db 0x00
db 0x55,0xAA
執行結果如下: