Assembly Language
資料轉移指令
加法和減法
資料相關的運算子與指引
間接定址
JMP和LOOP指令
運算元型別
相關指令
立即運算元
◦ Immediate,
◦ 標記方式:imm
◦ 例: mov ecx,0
暫存器
◦ Register
◦ 標記方式:reg
◦ 例: mov ecx,0
記憶體
◦ Memory
◦ 標記方式:mem
◦ 例: mov AL,var1
運算元 說明
r8 8-bit通用暫存器,AH,AL,BH,BL,CH,CL,DH,DL r16 16-bit通用暫存器,AX,BX,CX,DX,SI,DI,SP,BP
r32 32-bit通用暫存器,EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP
reg 任何通用暫存器
sreg 16-bit區段暫存器,CS,DS,SS,ES,FS,GS imm 8,16,32-bit立即值。
imm8 8-bit立即值。
imm16 16-bit立即值。
imm32 32-bit立即值。
r/m8 8-bit運算元,可以是8-bit通用暫存器或記憶體位元組。
r/m16 16-bit運算元,可以是16-bit通用暫存器或記憶體字組。
r/m32 32-bit運算元,可以是32-bit通用暫存器或記憶體雙字組。
mem 8,16,32-bit記憶體運算元。
記憶體運算元的一種。
直接指出運算元所在處之記憶體有效位址。
◦ 有效位址可以透過變數名稱表示。
變數名稱
其參照(reference)資料區段的位移值。
◦ 例:
.data
val1 BYTE 10h
假設,val1是位於位移值10400h處,欲將其內容 搬移到AL暫存器。
◦ mov al,val1 ;MASM組譯結果: A0 00010400
表示直接記憶體運算元,也可以使用方括號。
例如:
◦ mov al,[val1] ;等於 mov al,val1
將資料由來源運算元,複製到目地運算元。
◦ 類同於高階語言中,比如C語言中的 “=” 運算子。
基本格式:
◦ MOV destination, source ; destination = source
destination: 目的運算元
source: 來源運算元
◦ Note:
destination 和 source必須要有相同大小。
不能destination 和 source都是記憶體運算元。
目地運算元不可以是CS,EIP,IP
保護模式下,常用合法MOV指令語法
◦ (不含區段暫存器)
◦ MOV reg,reg ;暫存器間的資料搬移
◦ MOV mem,reg ;將資料由暫存器搬移到記憶體
◦ MOV reg,mem ;將資料由記憶體搬移到暫存器
◦ MOV mem,imm ;為某特定記憶體位置設定一個值。
◦ MOV reg,imm ;為暫存器設定一個值。
保護模式下
◦ 不能夠直接由程式修改區段暫存器的內容。
實體模式下,可修改區段暫存器內容,
下列為合法存取區段暫存器的MOV指令語法
◦ (Note:但是不可使用CS為目的運算元)
◦ MOV r/m16,sreg
◦ MOV sreg,r/m16
要實現高階語言中,將變數a的資料複製給變數b
◦ b = a
因為mov不能夠兩個運算元都是記憶體運算元。
解決方式:
◦ 將資料先搬到暫存器
◦ 再由暫存器般到記憶體
程式片段範例
◦ .data
◦ a WORD 10h
◦ b WORD ?
◦ .code
◦ ; b = a
◦ mov ax,a
◦ mov b,ax
要實現高階語言中,將變數a的資料複製給變數b
◦ b = a
使用mov
要實現高階語言中,將變數a的資料複製給變數b
◦ b = a
問題:mov不能夠兩個運算元都是記憶體運算元。
要實現高階語言中,將變數a的資料複製給變數b
◦ b = a
因為mov不能夠兩個運算元都是記憶體運算元。
解決方式:
◦ 將資料先搬到暫存器
◦ 再由暫存器般到記憶體
程式片段範例
◦ .data
◦ a WORD 10h
◦ b WORD ?
◦ .code
◦ ; b = a
◦ mov ax,a
◦ mov b,ax
情況:欲將記憶體中16-bit值複製到32-bit暫存器
存放。
情況:欲將記憶體中16-bit值複製到32-bit暫存器 存放。
問題:MOV不能直接將較小值複製到較大值。
情況:欲將記憶體中16-bit值複製到32-bit暫存器 存放。
問題:MOV不能直接將較小值複製到較大值。
解法:
◦ 無號數/正數:
先將目的暫存器的內容清為0。
再將資料搬移到該暫存器的低16-bit處。
◦ 例:欲將16-bit變數count的(正)數值複製到ECX
◦ 程式碼:
例: 欲將16-bit變數count的(正)數值複製到ECX
◦ 程式碼:
.data
count WORD 1 ; count變數,大小為16-bit,初值為1。
.code
;將16-bit變數count的值複製到ECX。
mov ecx,0 ;將目的暫存器的內容清除為0。
mov cx,count ;將資料搬移到該暫存器的低16-bit處。
情況:欲將記憶體中16-bit值複製到32-bit暫存器 存放。
解法:
◦ 負數:
先將目的暫存器的內容設為FFFFFFFF。
再將資料搬移到該暫存器的低16-bit處。
◦ 例:欲將16-bit變數count的負值複製到ECX
◦ 程式碼:
例:欲將16-bit變數count的負值複製到ECX
◦ 程式碼:
.data
count SWORD -16 ; count變數,大小為16-bit,初值為 -16。
.code
;將16-bit變數count的負值複製到ECX 。
mov ecx,0ffffffffh ;將目的暫存器的內容設為FFFFFFFF 。
mov cx,count ;將資料搬移到該暫存器的低16-bit處。
討論
◦ 上述解法對於有號數,要先判讀數值的正負號才能據此採用正 確的程式。
◦ 需要使用兩個mov指令來達成
Intel提供特定的指令,可以不需要使用兩個mov指令。
◦ MOVZX
以0擴展
適用無號整數或正數
語法:
MOVZX r32,r/m8
MOVZX r32,r/m16
MOVZX r16,r/m8
0 10001111 來源運算元
↓ ↓
00000000 10001111 目的運算元
討論
◦ 上述解法對於有號數,要先判讀數值的正負號才能據此採用正 確的程式。
◦ 需要使用兩個mov指令來達成
Intel提供特定的指令,可以不需要使用兩個mov指令。
◦ MOVSX
將來源運算元的最大有效位元擴展
適用有號整數
語法:
MOVSX r32,r/m8
MOVSX r32,r/m16
MOVSX r16,r/m8
10001111 來源運算元
↓
11111111 10001111 目的運算元
LAHF
◦ Load Status Flags into AH
◦ 將狀態旗標載入到AH
◦ 動作:
將EFLAGS暫存器的低位元組複製到AH中,被複製旗標如下:
符號旗標
零值旗標
輔助進位旗標
同位旗標
進位旗標
可用於將旗標值複製到變數中,例
.data
saveflags BYTE ? ;宣告一個位元組大小的變數,saveflags .code
; saveflags = 旗標狀態 lahf ;將旗標放置到AH
mov saveflags, ah ; saveflags = 旗標狀態@AH
將AH暫存器的值存回到旗標暫存器
是LAHF的反向操作
應用:將保管存放於記憶體中的旗標狀態回存到旗 標(恢復先前的旗標狀態)
例:
;恢復先前的旗標狀態
mov ah,saveflags ;旗標狀態保管於變數saveflags內 sahf ;回存到flags內
資料交換指令
eXCHanGe data
語法:
XCHG reg,reg ;將兩個一般暫存器的內容交換
XCHG reg,mem ;將一個一般暫存器內容與記憶體中一個相 等容量大小的內容相交換。
XCHG mem,reg ;同上
例
XCHG ax,bx ;暫存器資料交換,16-bit XCHG ah,al ;暫存器資料交換,8-bit
XCHG var1,bx ;暫存器與記憶體資料交換,16-bit XCHG eax,ebx ;暫存器資料交換,32-bit
交換兩個變數的內容
問題:xchg不能夠直接交換記憶體內容
交換兩個變數的內容
問題:xchg不能夠直接交換記憶體內容
解法:將其中一個記憶體內容先複製到暫存器,然
後再分別執行記憶體與暫存器內容的交換動作即可。
交換兩個變數的內容
問題:xchg不能夠直接交換記憶體內容
解法:將其中一個記憶體內容先複製到暫存器,然後再 分別執行記憶體與暫存器內容的交換動作即可。
程式碼:
.data
var1 WORD 1234h var2 WORD 5678h .code
;交換變數var1和var2的內容
mov ax,var1 ;將其中一個記憶體內容先複製到暫存器 xchg ax,var2 ;分別執行記憶體與暫存器內容的交換動作 xchg ax,var1 ;完成交換。 Swap var1 and var2.
直接對一個變數名稱進行算術運算,取得新的有效位址,
也就是相對於該變數位址進行位移。
例如,相對於變數var1的位址位移一個位元組處存取資 料:
◦ .data
◦ var1 BYTE 3,4
◦ .code
◦ mov al,var1+1
注意
◦ 位移量為一個位元組。
應用
◦ 陣列元素的存取
.data
arrayB BYTE 10h,20h,30h,40h,50h arrayW WORD 100h,200h,300h,400h
arrayD DWORD 10000h,20000h,30000h .code
mov al,[arrayB+1] ;存取arrayB的第二個元素,20h mov al,arrayB+1 ;同上
mov bx,arrayW+4 ;存取arrayW的第三個元素,300h
mov edx,[arrayD+4] ;存取arrayD的第二個元素,20000h
搬移的範例程式
◦ 觀察每個指令執行前後,暫存器內容的變化與預期是否相 符。
◦ pp. 103
pp. 103~104, 4.1.10 自我評量
請使用A4紙張,
要寫題目,答案跟著題目,例如
◦ 1.試問運算元有哪三種基本類型?
◦ 答:立即值、暫存器、記憶體。
下周上課時繳交。逾期不收。
組合語言課程
INC
DEC
ADD
SUB
NEG
重點
◦ 要瞭解這些指令對旗標的影響
INC
◦ 遞增指令
DEC
◦ 遞減址令
語法
◦ INC reg/mem
◦ INC reg/mem
影響旗標
◦ 溢位、符號、零值、輔助進位、同位旗標
不影響旗標
◦ 進位
例
◦ .data
◦ myWord WORD 1000h
◦ .code
◦ inc myWord ;1001h
◦ mov bx,myWord ;bx = 1001h
◦ dec bx ;bx = 1000h
加法
◦ 將來源運算元的值加到目的運算元
語法
◦ ADD dest,source ; dest = dest+source
◦ 可用運算元與MOV指令相同
影響旗標
◦ 進位、溢位、符號、零值、輔助進位、同位旗標
◦ 依據目地運算元的值變化。
例:相加兩個32-bit整數
◦ .data
◦ var1 DWORD 10000h
◦ var2 DWORD 20000h
◦ .code
◦ mov eax,var1 ;EAX=10000h
◦ add eax,var2 ;EAX=30000h
減法
◦ 目的運算元減去(扣掉)來源運算元的值
語法
◦ SUB dest,source ;dest <- dest – source
◦ 運算元同ADD和MOV
影響旗標
◦ 進位、溢位、符號、零值、輔助進位、同位旗標
◦ 依據目地運算元的值變化。
例:相減兩個32-bit整數
◦ .data
◦ var1 DWORD 30000h
◦ var2 DWORD 10000h
◦ .code
◦ mov eax,var1 ;EAX=30000h
◦ sub eax,var2 ;EAX=20000h
將一個數值轉換成其2’s補數
語法
◦ NEG reg
◦ NEG mem
影響旗標
◦ 進位、溢位、符號、零值、輔助進位、同位旗標
◦ 依據目地運算元的值變化。
例
◦ .data
◦ var1 BYTE 01h
◦ .code
◦ neg var1 ;var1 = FFh = -1
將下列算術運算式以組合語言表示
◦ Rval = -Xval + (Yval – Zval);
Xval = 26, Yval=30, Zval = 40
解
將下列算術運算式以組合語言表示
◦ Rval = -Xval + (Yval – Zval);
Xval = 26, Yval=30, Zval = 40
解
◦ ;定義出此式所需使用的四個變數:Rval, Xval, Yval, Zval
◦ .data
◦ Rval SDWORD ? ;定義有號雙字組大小整數變數Rval。
◦ Xval SDWORD 26 ;定義有號雙字組大小整數變數Xval,初值為26。
◦ Yval SDWORD 30 ;定義有號雙字組大小整數變數Yval,初值為30。
◦ Zval SDWORD 40 ;定義有號雙字組大小整數變數Zval,初值為40。
將下列算術運算式以組合語言表示
◦ Rval = -Xval + (Yval – Zval);
Xval = 26, Yval=30, Zval = 40
解
◦ ;此式含有四個變數
◦ .data
◦ Rval SDWORD ?
◦ Xval SDWORD 26
◦ Yval SDWORD 30
◦ Zval SDWORD 40
◦ .code
◦ mov eax,Yval
◦ sub eax,Zval ; Yval-Zval
◦ mov ebx,Xval
◦ neg ebx ; -Xval
◦ add ebx,eax ; -Xval + (Yval – Zval)
◦ mov Rval,ebx ; Rval = -Xval + (Yval – Zval)
進位旗標
◦ 假設指令所處理之資料為整數,其運算元的大小為x-bit, x=8,16,32
◦ 若產生的結果需要增加一個位元才能夠表示,
◦ 則進位旗標會被設定。
例
◦ 某指令具有8位元的目的運算元,但是此指令運算的結果 大於11111111b,則進位旗標被設定。
溢位旗標
◦ 指出有號整數的溢位狀態
例
◦ 某指令具有16位元的目地運算元,但是此指令產生的負數
>-32768,則溢位旗標被設定。
零值旗標
◦ 指出運算是否產生零值。
例
◦ 某運算元減去具有相同值的另一個運算元,則零值旗標被 設定。
符號旗標
◦ 指出一個運算是否產生的結果是負值。
例
◦ 如果目的運算元的最大有效位元是1,則符號位元會被設 定。
同位旗標
◦ 計算目的運算元中,最小有效位元組具有位元值為1的位 元數目,當數目為偶數,其值被設定。
輔助進位旗標
◦ 目的運算元中,最小有效位元組中,bit-3產生進位時,
此旗標被設定。
◦ 例如
目的運算元的值00000100b被加1100b時, bit-3產生進位
有興趣的旗標
◦ 零值, ZF
◦ 進位, CF
◦ 輔助進位, AC
mov al,0FFh
add al,1 ;AL=00h, CF=1
CF
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
+
0 0 0 0 0 0 0 0
mov ax,00FFh
add ax,1 ;AX=0100h, CF=0
mov ax,0FFFFh
add ax,1 ;AX=0000h, CF=1
當一個較小的無號整數減去一個較大的無號整數時,
此減法運算會使進位旗標被設定。(表示有借位)
例: 1 – 2
◦ 1-2=1+(-2)
CF
1 0
0 0 0 0 0 0 0 1 (1)
1 1 1 1 1 1 1 0 (-2)
+
1 1 1 1 1 1 1 1 (-1)
NOT
常用於BCD
◦ Ref Ch7.6
例
◦ mov al,0Fh
◦ add al,1 ;AC=1, AL=10h
例
◦ mov al,00101100b ;
◦ add al,00000010b ;AL=00101110b, PF=1
◦ sub al,00001000b ;AL=00100110b, PF=0, CF=0
00101110b-00001000b
= 00101110b+11111000b
= 00100110b
符號旗標,SF
◦ 當有號數算術運算的結果是負值,符號旗標會設定,例:
◦ mov eax,4
◦ sub eax,5 ;EAX = -1, SF=1
EAX 0000 0000 0000 0000 0000 0000 0000 0100 b
( 5) 0000 0000 0000 0000 0000 0000 0000 0101 b
(-5) 1111 1111 1111 1111 1111 1111 1111 1011 b
EAX – 5 = EAX + (-5)
EAX 1111 1111 1111 1111 1111 1111 1111 1111 b
F F F F F F F F h
CF = 1
SF = 1
溢位旗標, OF
◦ 當有號數算術運算結果使目地運算元溢位或欠位時設定。
例
◦ mov al,+127
◦ add al,1 ;OF=1
◦ mov al,-128
◦ sub al,1 ;OF=1
硬體判別OF方式
◦ MSB的進位 XOR 次MSB的進位
0111 1111b (+127) 0000 0001b (+1) 1000 0000b (-128)
1000 0000b (-128) 1111 1111b (-1) CF=0,
0111 1111b (+127溢位)
XOR 0 1
0 0 1
1 1 0
若執行NEG指令時,目地運算元不能夠正確表示結 果時,溢位旗標會被設定,例如
◦ mov al,-128 ;AL=10000000b
◦ neg al ;AL=10000000b, OF=1
◦ mov al,+127 ;AL=01111111b
◦ neg al ;AL=10000001b, OF=0
CPU不知道要執行的運算是有號還是無號數運算,
◦ CPU是依據一套布林規則來設定所有的狀態旗標。
程式設計者需要根據自己對所執行的運算類型,自
行判別哪些旗標是有意義,哪些可以忽略。
請將程式鍵入並執行
目的
◦ 觀察狀態旗標如何受到影響。
◦ 使用DEBUG的旗標視窗觀察。
P111
P112, 4.2.8
題目
◦ 1,2,3,4,5,6,7,8,9,10,11,12