8086指令系統(tǒng)---控制轉(zhuǎn)移指令(二)
這一組指令在循環(huán)結(jié)構(gòu)的程序中用來控制一段程序(稱為循環(huán)體)的重復(fù)執(zhí)行,在匯編指令中循環(huán)的轉(zhuǎn)向地址用標(biāo)號來表示,而在機(jī)器指令中給出的是位移量,所以執(zhí)行循環(huán)指令時(shí),若滿足循環(huán)條件,CPU就計(jì)算轉(zhuǎn)向地址:(IP)當(dāng)前+8位位移量→(IP),即實(shí)現(xiàn)循環(huán)。
若不滿足循環(huán)條件,即退出循環(huán),程序繼續(xù)順序執(zhí)行。
循環(huán)指令都是短轉(zhuǎn)移格式的指令,也就是說,位移量是用8位帶符號數(shù)來表示的,轉(zhuǎn)向地址在相對于當(dāng)前IP值的-128 ~ +127字節(jié)范圍之內(nèi)。
對條件循環(huán)指令LOOPZ(LOOPE)和LOOPNZ(LOOPNE),除測試CX中的循環(huán)次數(shù)外,還將ZF的值作為循環(huán)的必要條件,因此,要注意將條件循環(huán)指令緊接在形成ZF的指令之后。
在多重循環(huán)的程序結(jié)構(gòu)中,如果各層循環(huán)都使用循環(huán)指令來控制,則應(yīng)注意對CX中循環(huán)計(jì)數(shù)值的保存與恢復(fù)。
循環(huán)指令均不影響條件碼。
LOOP label 循環(huán)(loop)
執(zhí)行操作:① (CX)←(CX)-1
?、?若(CX)≠0,則(IP)←(IP)當(dāng)前+位移量,否則循環(huán)結(jié)束
LOOPZ/LOOPE label 為零/相等時(shí)循環(huán)(loop while zero,or equal)
執(zhí)行操作:① (CX)←(CX)-1
② 若ZF=1且(CX)≠0,則(IP)←(IP)當(dāng)前+位移量,否則循環(huán)結(jié)束
LOOPNZ/LOOPNE label 不為零/不等時(shí)循環(huán)(loop while nonzero,or not equal)
執(zhí)行操作:① (CX)←(CX)-1
?、?若ZF=0且(CX)≠0,則(IP)←(IP)當(dāng)前+位移量,否則循環(huán)結(jié)束
DATA SEGMENT
BLOCK1 DW 100 DUP(?)
BLOCK2 DW 100 DUP(?)
DATA ENDS
; - - - - - - - - - - - - - - - - - -
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA
START:MOV AX,DATA
MOV DS,AX ; initialize the data segment
MOV ES,AX ; initialize the extra segment
CLD ; DF=0 for autoincrement
MOV CX,100 ; load the counter
MOV SI,OFFSET BLOCK1 ; address of block1
MOV DI,OFFSET BLOCK2 ; address of block2
NEXT: LODSW ; load the data of block1 into AX
ADD AX,ES:[DI] ; add the data of block2 to AX
STOSW ; store the sum to block2
LOOP NEXT ; repeat 100 times
MOV AX,4C00H ; return to DOS
INT 21H
CODE ENDS
END START
子程序是一種非常重要的計(jì)算機(jī)編程結(jié)構(gòu),它存儲在存儲器中,可供一個(gè)或多個(gè)調(diào)用程序(主程序)反復(fù)調(diào)用。主程序調(diào)用子程序時(shí)使用CALL指令,由子程序返回主程序時(shí)使用RET指令。由于調(diào)用程序和子程序可以在同一個(gè)代碼段中,也可以在不同的代碼段中,因此,CALL指令和RET指令也有近調(diào)用、近返回及遠(yuǎn)調(diào)用、遠(yuǎn)返回兩類格式。
?、?CALL NEAR PTR SUBPROUT 近調(diào)用(near call)
近調(diào)用是CALL指令的缺省格式,可以寫為"CALL subrotine"。它調(diào)用同一個(gè)代碼段內(nèi)的子程序(子過程),因此,在調(diào)用過程中不用改變CS的值,只需將子程序的地址存入IP寄存器。CALL指令中的調(diào)用地址可以用直接和間接兩種尋址方式表示。
?、?CALL FAR PTR SUBPROUT 遠(yuǎn)調(diào)用(far call)
遠(yuǎn)調(diào)用適用于調(diào)用程序(也稱為主程序)和子程序不在同一段中的情況,所以也叫做段間調(diào)用。和近調(diào)用指令一樣,遠(yuǎn)調(diào)用指令中的尋址方式也可用直接方式和間接方式。
?、?RET 返回指令(return)
RET指令執(zhí)行的操作是把保存在堆棧中的返回地址出棧,以完成從子程序返回到調(diào)用程序的功能。
● CALL SUBROUT 段內(nèi)直接調(diào)用
執(zhí)行操作:① (SP) ← (SP)-2,((SP)) ← (IP)當(dāng)前
② (IP) ← (IP)當(dāng)前+16位位移量(在指令的第2、3個(gè)字節(jié)中)
● CALL DESTIN 段內(nèi)間接調(diào)用
執(zhí)行操作:① (SP) ← (SP)-2,((SP)) ← (IP)當(dāng)前
?、?(IP) ← (EA) ; (EA)為指令尋址方式所確定的有效地址
● CALL FAR PTR SUBROUT 段間直接調(diào)用
執(zhí)行操作:① (SP) ← (SP)-2,((SP)) ← (CS)當(dāng)前
(SP) ← (SP)-2,((SP)) ← (IP)當(dāng)前
?、?(IP) ← 偏移地址(在指令的第2、3個(gè)字節(jié)中)
(CS) ← 段地址(在指令的第4、5個(gè)字節(jié)中)
● CALL WORD PTR DESTIN 段間間接調(diào)用
執(zhí)行操作:① (SP) ← (SP)-2,((SP)) ← (CS)當(dāng)前
(SP) ← (SP)-2,((SP)) ← (IP)當(dāng)前
?、?(IP) ← (EA) ; (EA)為指令尋址方式所確定的有效地址
(CS) ← (EA+2)
從CALL指令執(zhí)行的操作可以看出,第一步是把子程序返回調(diào)用程序的地址保存在堆棧中。對段內(nèi)調(diào)用,只需將IP的當(dāng)前值,即CALL指令的下一條指令的地址存入SP所指示的堆棧字單元中。對段間調(diào)用,保存返回地址則意味著要將CS和IP的當(dāng)前值分別存入堆棧的兩個(gè)字單元中。
CALL指令的第二步操作是轉(zhuǎn)子程序,即把子程序的入口地址交給IP(段內(nèi)調(diào)用)或CS:IP(段間調(diào)用)。對段內(nèi)直接方式,調(diào)轉(zhuǎn)的位移量,即子程序的入口地址和返回地址之間的差值就在機(jī)器指令的2、3字節(jié)中。對段間直接方式,子程序的偏移地址和段地址就在操作碼之后的兩個(gè)字中。對間接方式,子程序的入口地址就從尋址方式所確定的有效地址中獲得。
● RET 段內(nèi)返回(近返回)
執(zhí)行操作:(IP) ← ((SP)),(SP) ← (SP)+2
● RET 段間返回(遠(yuǎn)返回)
執(zhí)行操作:(IP) ← ((SP)),(SP) ← (SP)+2
(CS) ←((SP)),(SP) ← (SP)+2
● RET N 帶立即數(shù)返回
執(zhí)行操作:① 返回地址出棧(操作同段內(nèi)或段間返回)
?、?修改堆棧指針:(SP) ← (SP)+N
子程序的最后一條指令必須是RET指令,以返回到主程序。如果是段內(nèi)返回,只需把保存在堆棧中的偏移地址出棧存入IP即可,如果是段間返回,則要把偏移地址和段地址都從堆棧中取出送到IP和CS寄存器中。
帶立即數(shù)返回指令,除完成偏移地址出?;蚱频刂泛投蔚刂烦鰲5牟僮魍?,還要再使SP的內(nèi)容加上一個(gè)立即數(shù)N,使堆棧指針SP移動到新的位置。指令中的N可以是一個(gè)常數(shù),也可以是一個(gè)表達(dá)式。帶立即數(shù)返回指令適用于C或PASCAL的調(diào)用規(guī)則,這些規(guī)則在調(diào)用過程(子程序)前先把參數(shù)壓入堆棧,子程序使用這些參數(shù)后,如果在返回時(shí)丟棄這些已無用的參數(shù),就在RET指令中包含一個(gè)數(shù)字,它表示壓入到堆棧中參數(shù)的字節(jié)數(shù),這樣堆棧指針就恢復(fù)到參數(shù)入棧前的值。
CALL指令和RET指令都不影響條件碼。
0000 B8 001E MOV AX,30
0003 BB 0028 MOV BX,40
0006 50 PUSH AX ; push data1 into stack
0007 53 PUSH BX ; push data2 into stack
0008 E8 0066 CALL ADDM ; call subroutine
000B B4 02 MOV AH,2
… … …
0071 ADDM PROC NEAR ; entry point (IP)←0071=000b+0066
0071 55 PUSH BP ; save BP
0072 8B E4 MOV BP,SP ; addressing the stack with BP
0074 8B 46 04 MOV AX,[BP+4] ; get data2 from stack
0077 03 46 06 ADD AX,[BP+6] ; add data1
007A CD POP BP ; get back BP
007B C2 0004 RET 4 ; return and revert SP
007E ADDM ENDP
如圖3.12所示,主程序中的兩條PUSH指令將數(shù)據(jù)30和40壓入堆棧,CALL指令執(zhí)行后,返回地址000B又壓入堆棧,緊接著程序控制轉(zhuǎn)移到子程序ADDM。子程序中的PUSH指令又使BP的值進(jìn)棧,此時(shí)SP指向棧頂0FFA。MOV指令將0FFA傳送給BP,使BP作為尋址堆棧數(shù)據(jù)的指針。(BP+4)指向的是40,(BP+6)指向的是30,取出數(shù)據(jù)后用POP指令恢復(fù)了BP原先的值,此時(shí),(SP)=0FFC,這是RET 4指令執(zhí)行前的堆棧狀態(tài)。
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號放大器
評論