嵌入式系統 - 指令



程式的流程以順序方式進行,從一條指令到下一條指令,除非執行控制轉移指令。組合語言中各種型別的控制轉移指令包括條件或無條件跳轉和呼叫指令。

迴圈和跳轉指令

8051 中的迴圈

重複執行一系列指令一定次數的操作稱為迴圈。指令DJNZ reg, label用於執行迴圈操作。在此指令中,暫存器遞減 1;如果它不為零,則 8051 跳轉到標籤所引用的目標地址。

在迴圈開始之前,暫存器載入計數器以表示重複次數。在此指令中,暫存器遞減和跳轉決策組合成單個指令。暫存器可以是 R0-R7 中的任何一個。計數器也可以是 RAM 位置。

示例

使用重複加法的方法將 25 乘以 10。

解答 - 乘法可以透過重複新增被乘數來實現,次數與乘數相同。例如:

25 * 10 = 250(FAH)

25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 = 250

   MOV A,#0             ;A = 0,clean ACC 
   MOV R2,#10           ; the multiplier is replaced in R2 
   Add A,#25            ;add the multiplicand to the ACC 
	
AGAIN:DJNZ R2, 
AGAIN:repeat  until R2 = 0 (10 times) 

   MOV R5 , A           ;save A in R5 ;R5 (FAH)

8051 的缺點 - 使用指令DJNZ Reg label的迴圈操作僅限於 256 次迭代。如果不進行條件跳轉,則執行跳轉後的指令。

迴圈內的迴圈

當我們在另一個迴圈內使用迴圈時,這稱為巢狀迴圈。當最大計數限制為 256 時,使用兩個暫存器來儲存計數。因此,我們使用此方法來重複比 256 次更多的操作。

示例

編寫一個程式 -

  • 將累加器載入為值 55H。
  • 將 ACC 反碼 700 次。

解答 - 由於 700 大於 255(任何暫存器的最大容量),因此使用兩個暫存器來儲存計數。以下程式碼顯示瞭如何使用兩個暫存器 R2 和 R3 來進行計數。

   MOV A,#55H            ;A = 55H 
	
NEXT: MOV R3,#10         ;R3 the outer loop counter 
AGAIN:MOV R2,#70         ;R2 the inner loop counter 

   CPL A                 ;complement

其他條件跳轉

下表列出了在 8051 中使用的條件跳轉 -

指令 動作
JZ 如果 A = 0 則跳轉
JNZ 如果 A ≠ 0 則跳轉
DJNZ 遞減並跳轉如果暫存器 ≠ 0
CJNE A, data 如果 A ≠ data 則跳轉
CJNE reg, #data 如果位元組 ≠ data 則跳轉
JC 如果 CY = 1 則跳轉
JNC 如果 CY ≠ 1 則跳轉
JB 如果位 = 1 則跳轉
JNB 如果位 = 0 則跳轉
JBC 如果位 = 1 則跳轉並清除位
  • JZ(如果 A = 0 則跳轉) - 在此指令中,檢查累加器的內容。如果為零,則 8051 跳轉到目標地址。JZ 指令僅適用於累加器,不適用於任何其他暫存器。

  • JNZ(如果 A 不等於 0 則跳轉) - 在此指令中,檢查累加器的內容是否非零。如果它不為零,則 8051 跳轉到目標地址。

  • JNC(如果無進位,則跳轉如果 CY = 0) - 標誌(或 PSW)暫存器中的進位標誌位用於決定是否跳轉“JNC 標籤”。CPU 檢視進位標誌以檢視是否已置位 (CY = 1)。如果未置位,則 CPU 開始從標籤地址獲取並執行指令。如果 CY = 1,它不會跳轉,而是會執行 JNC 下面的下一條指令。

  • JC(如果進位,則跳轉如果 CY = 1) - 如果 CY = 1,則跳轉到目標地址。

  • JB(如果位高則跳轉)

  • JNB(如果位低則跳轉)

注意 - 必須注意,所有條件跳轉都是短跳轉,即目標地址必須在程式計數器內容的 –128 到 +127 位元組以內。

無條件跳轉指令

8051 中有兩個無條件跳轉 -

  • LJMP(長跳轉) - LJMP 是 3 位元組指令,其中第一個位元組表示操作碼,第二個和第三個位元組表示目標位置的 16 位地址。2 位元組目標地址是為了允許從 0000 到 FFFFH 的任何記憶體位置跳轉。

  • SJMP(短跳轉) - 它是一個 2 位元組指令,其中第一個位元組是操作碼,第二個位元組是目標位置的相對地址。相對地址範圍為 00H 到 FFH,分為向前和向後跳轉;也就是說,相對於當前 PC(程式計數器)地址的記憶體空間在 –128 到 +127 位元組內。對於向前跳轉,目標地址可以在距當前 PC 127 位元組的空間內。對於向後跳轉,目標地址可以在距當前 PC –128 位元組的空間內。

計算短跳轉地址

所有條件跳轉(JNC、JZ 和 DJNZ)都是短跳轉,因為它們是 2 位元組指令。在這些指令中,第一個位元組表示操作碼,第二個位元組表示相對地址。目標地址始終相對於程式計數器的值。要計算目標地址,將第二個位元組新增到跳轉指令正下方的指令的 PC。請檢視下面給出的程式 -

Line   PC    Op-code   Mnemonic   Operand 
1      0000               ORG       0000 
2      0000  7800         MOV       R0,#003  
3      0002  7455         MOV       A,#55H0 
4      0004  6003         JZ        NEXT 
5      0006  08           INC       R0 
6      0007  04   AGAIN:  INC       A 
7      0008  04           INC       A 
8      0009  2477 NEXT:   ADD       A, #77h 
9      000B  5005         JNC       OVER 
10     000D  E4           CLR       A
11     000E  F8           MOV       R0, A 
12     000F  F9           MOV       R1, A 
13     0010  FA          MOV       R2, A 
14     0011  FB           MOV       R3, A 
15     0012  2B   OVER:   ADD       A, R3 
16     0013  50F2         JNC       AGAIN 
17     0015  80FE HERE:   SJMP      HERE 
18     0017             END

向後跳轉目標地址計算

對於向前跳轉,位移值是 0 到 127(十六進位制為 00 到 7F)之間的正數。但是,對於向後跳轉,位移是 0 到 –128 的負值。

CALL 指令

CALL 用於呼叫子程式或方法。子程式用於執行需要頻繁執行的操作或任務。這使程式更結構化並節省記憶體空間。有兩條指令 - LCALL 和 ACALL。

LCALL(長呼叫)

LCALL 是一條 3 位元組指令,其中第一個位元組表示操作碼,第二個和第三個位元組用於提供目標子程式的地址。LCALL 可用於呼叫在 8051 的 64K 位元組地址空間內可用的子程式。

為了成功返回到呼叫子程式執行後的點,CPU 將 LCALL 下方指令的地址儲存到堆疊中。因此,當呼叫子程式時,控制將轉移到該子程式,處理器將 PC(程式計數器)儲存在堆疊中,並開始從新位置獲取指令。指令 RET(返回)在完成子程式執行後將控制轉移回呼叫方。每個子程式都使用 RET 作為最後一條指令。

ACALL(絕對呼叫)

與 LCALL 為 3 位元組相比,ACALL 是一條 2 位元組指令。子程式的目標地址必須在 2K 位元組內,因為只有 2 位元組的 11 位用於定址。ACALL 和 LCALL 之間的區別在於 LCALL 的目標地址可以在 8051 的 64K 位元組地址空間中的任何位置,而 CALL 的目標地址在 2K 位元組範圍內。

廣告
© . All rights reserved.