偽指令分類
在ARM的彙編程式中,有如下幾種偽指令:符號定義偽指令、數據定義偽指令、彙編控制偽指令、宏指令及其他偽指令。
和指令的區別
指令是在執行階段發揮作用的,由CPU(Intel、AMD等)來執行。
偽指令是在編譯階段發揮作用的,由彙編器(MASM、TASM等)來解釋。
Note
彙編版本老於 ARMv6T2 的處理器的 Thumb 指令時,ADRL 是無效的 。
語法
ADRL Rd,label
其中:
cond
是一個可選的條件代碼(請參閱條件執行)。
Rd
是要載入的暫存器。
label
表達式,與程式或暫存器相關。 有關詳細信息,請參閱相對暫存器和程式相對的表達式。
用法
ADRL 始終彙編為兩個 32 位指令。 即使使用單個指令就可完成地址訪問,也會生成多餘的第二個地址。
如果彙編程式無法將地址構建為兩個指令,則它將生成一條錯誤訊息,彙編將失敗。 有關載入更寬範圍地址的信息,請參閱LDR 偽指令(另請參閱將常數載入到暫存器)。
ADRL 可生成與位置無關的代碼,因為地址與程式或暫存器有關。
如果 label 與程式有關,則其表示的地址必須要與 ADRL 偽指令在同一彙編程式區域內,請參閱AREA。
如果使用 ADRL 來為 BX 或 BLX 指令生成目標,則當目標中包含 Thumb 指令時,您就要自己設定地址的 Thumb 位(位 0)。
體系結構和範圍
可用範圍取決於所用的指令集:
ARM
±64KB 到位元組或半字對齊的地址。
±256KB 位元組,字對齊地址。
32 位 Thumb
±1MB 位元組,位元組、半字或字對齊地址。
16 位 Thumb
ADRL 不可用。
上面給出的範圍是相對於位於當前指令後的、離當前指令有四個位元組(在 Thumb 代碼中)或兩個字(在 ARM 代碼中)間隔的點而言的。 在 ARM 和 32 位 Thumb 中,如果地址為 16 位元組對齊,或與該點的相對性更高,則相對地址的範圍可更大。
MOV32 偽指令
將以下項之一載入到暫存器:
一個 32 位常數值
任何地址。
MOV32 始終會生成兩個 32 位指令,即一個 MOV、MOVT 對。 您可利用它載入任何 32 位常數或訪問整個地址空間。
如果用 MOV32 載入地址,則所生成的代碼將與位置有關。
語法
MOV32 Rd, expr
其中:
cond
是一個可選的條件代碼(請參閱條件執行)。
Rd
是要載入數據的暫存器。Rd 不可為 sp 或 pc。
expr
可以是下列項之一:
symbol
程式區域中的標籤。
constant
任何 32 位常數。
symbol + constant
標籤加上 32 位常數。
用法
MOV32 偽指令的主要功能有:
當單個指令中無法生成立即數時,生成文字常數。
將相對於程式的地址或外部地址載入暫存器中。 無論連結器將包含 MOV32 的 ELF 代碼段置於何處,該地址始終有效。
Note
以這種方式載入的地址是在連結時確定的,因此代碼不是位置無關的。
如果所引用的標籤位於 Thumb 代碼中,則 MOV32 將會設定該地址的 Thumb 位(位 0) 。
體系結構
此偽指令在 ARMv6T2 和 ARMv7 中的 ARM 和 Thumb 狀態下均有效。
LDR 偽指令
將以下項之一載入暫存器:
一個 32 位常數值
一個地址。
Note
本節僅介紹 LDR 偽 指令。 有關 LDR 指令 的詳細信息,請參閱 記憶體訪問指令。
有關使用 LDR 偽指令載入常數的信息,請參閱用 LDR Rd, =const 載入。
語法
LDR{.w} Rt,=[expr | label‑expr]
其中:
cond
是一個可選的條件代碼(請參閱條件執行)。
.W
是可選的指令寬度說明符。
Rt
是要載入的暫存器。
expr
取值為一個數值常數:
如果 expr 的值位於範圍內,則彙編程式將會生成一個 MOV 或 MVN 指令。
如果 expr 的值不在 MOV 或 MVN 指令的範圍內,則彙編程式會將常數放入文字池中,並會生成一個相對於程式的 LDR 指令,該指令可從文字池中讀取此常數。
label‑expr
是一個與程式相關的表達式或外部表達式。 彙編程式會將 label‑expr 的值放入文字池中,並會生成一個與程式有關的 LDR 指令,該指令可從文字池中載入該值。
如果 label‑expr 是一個外部表達式,或未包含在當前代碼段內,則彙編程式將會在目標檔案中放入一個連結器重新定位指令。 連結器將在連結時生成該地址。
如果 label‑expr 是一個局部標籤(請參閱局部標籤),則彙編程式會在目標檔案中放入一個連結器重新定位指令,並會為該局部標籤生成一個符號。 該地址將在連結時生成。 如果局部標籤引用了 Thumb 代碼,則還會設定該地址的 Thumb 位(位 0)。
Note
在 RVCT2.2 中,沒有對地址的 Thumb 位進行設定。 如果此設定會影響您的代碼,則請使用命令行選項 ‑‑untyped_local_labels 迫使彙編程式在引用 Thumb 代碼中的標籤時不設定 Thumb 位。
用法
LDR 偽指令的主要功能如下:
當立即數由於超出了 MOV 和 MVN 指令的範圍,而不能被移入暫存器中時,生成文字常數。
將相對於程式的地址或外部地址載入暫存器中。 無論連結器將包含 LDR 的 ELF 代碼段置於何處,該地址始終有效。
pc 到文字池中的值的偏移量必須小於 ±4KB(ARM、32 位 Thumb‑2),或在 0 到 +1KB(Thumb、16 位 Thumb‑2)範圍內。 您必須確保有一個滿足範圍要求的文字池。 有關詳細信息,請參閱LTORG。
如果所引用標籤在 Thumb 代碼中,LDR 偽指令將會設定 label‑expr 的 Thumb 位(位 0)。
有關如何使用 LDR 的詳細說明,以及有關 MOV 和 MVN 的詳細信息,請參閱將常數載入到暫存器。
Thumb 代碼中的 LDR
對於 ARMv6T2 及更高版本的 Thumb 代碼,您可以使用 .W 寬度說明符強制 LDR 生成 32 位指令。LDR.W 始終生成 32 位指令,即使利用 16 位 MOV 就可完成常數的載入,或在 16 位 pc 相對載入範圍內有文字池。
如果在第一次彙編時,彙編程式尚不知道常數值的相關信息,則不帶 .W 的 LDR 將會在 Thumb 代碼中生成 16 位指令,即使這會導致對於可在 32 位 MOV 或 MVN 指令中生成的常數,會通過 16 位 pc 相對載入來完成其載入。 但是,如果在第一次彙編時彙編程式就已經知道了該常數,並且該常數可以通過 32 位 MOV 或 MVN 指令生成,則將會使用 MOV 或 MVN 指令。
LDR 偽指令不會生成 16 位標記設定 MOV 指令。 可使用 ‑‑diag_warning 1727 彙編程式命令行選項來檢查是否使用了 16 位指令。
有關如何在不利用文字池載入的情況下來生成常數或地址的信息,請參閱MOV32 偽指令。
示例
LDR r3,=0xff0 ; loads 0xff0 into r3
; => MOV.W r3,#0xff0
LDR r1,=0xfff ; loads 0xfff into r1
; => LDR r1,[pc,offset_to_litpool]
; ...
; litpool DCD 0xfff
LDR r2,=place ; loads the address of
; place into r2
; => LDR r2,[pc,offset_to_litpool]
; ...
UND 偽指令
生成無體系結構定義的指令。 執行未定義指令會引發未定義指令異常。 請讓無體系結構定義的指令保持在未定義狀態。
語法
UND{.w} {#expr}
其中:
cond
是一個可選的條件代碼(請參閱條件執行)。對於 ARM 代碼或 16 位 Thumb 代碼,不允許此偽指令使用 cond。
.W
是可選的指令寬度說明符。
expr
取值為一定範圍內的數值常數:
對於 ARM 代碼,為 0-65535
對於 32 位 Thumb 代碼,為 0-4095
對於 16 位 Thumb 代碼,為 0-255。
如果省略了 expr,則使用的值為 0。
Thumb 代碼中的 UND
對於 ARMv6T2 及更高版本處理器的 Thumb 代碼,您可利用 .W 寬度說明符強制 UND 生成 32 位指令。UND.W 始終生成 32 位指令,即使 expr 在 0-255 範圍之內。
反彙編
此偽指令生成的編碼將反彙編為 DCI。
; litpool DCD place
大學彙編課本中主要介紹的偽指令:
(1)assume 段暫存器名:段名 假設 (將段與CPU中段暫存器聯繫起來)
(2)段名 segment 開始
段名 ends 結束 (成對出現)
(3)ends (整個程式結束)
51彙編偽指令
1、DS ---預留存儲區命令 格式: 〔標號:〕 DS 表達式值 其功能是從指定地址開始,定義一個存儲區,以備源程式使用。 存儲區預留的存儲單元數由表達式的值決定。 TMP: DS 1 從標號TEP地址處開始保留1個存儲單元(位元組)。
2、BIT---定義位命令 格式: 字元名稱 BIT 位地址 其功能用於給字元名稱定義位地址。 SPK BIT P3.7 經定義後,允許在指令中用SPK代替P3.7。
3、USING指令 USING指令通知彙編器使用8051的哪一個工作暫存器組。 格式: USING 表達式 (值必須為0-3,默認值為0。) USING 0 使用第0組工作暫存器。
4、SEGMENT指令 SEGMENT 指令用來聲明一個再定位段和一個可選的再定位類型。 格式: 再定位段名 SEGMENT 段類型〔再定位類型〕 其中,“再定位段名”用於指明所聲明的段。 “段類型”用於指定所聲明的段將處的存儲器地址空間。 可用的段類型有 CODE、XDATA、DATA、IDATA和BIT。 STACK_SEG SEGMENT IDATA DATA_SEG SEGMENT DATA。
5、RSEG---再定位段選擇指令 再定位段選擇指令為RSEG,用於選擇一個已在前面定義過的再定位段作為當前段。 格式: RSEG 段名 段名必須是在前面已經聲明過的再定位段。 DATA_SEG SEGMENT DATA ;聲明一個再定位DATA段 RSEG DATA_SEG ;選擇前面聲明的再定位DATA段作為當前段。
6、絕對段選擇指令 CSEG---絕對代碼段 DSEG---內部絕對數據段 XSEG---外部絕對數據段 ISEG ---內部間接定址數據段 BSEG---絕對位定址數據段 格式: CSEG [AT 絕對地址表達式] DSEG [AT 絕對地址表達式] XSEG [AT 絕對地址表達式] ISEG [AT 絕對地址表達式] BSEG [AT 絕對地址表達式] 括弧內是可選項,用來指定當前絕對段的基地址。 CSEG AT 0000H AJMP MAIN。
7、ORG指令 ORG指令用來改變彙編器的計數器,從而設定一個新的程式起始地址。 格式: ORG 表達式 表達式必須是絕對或簡單再定位表達式。 ORG 0000H AJMP MAIN 設定 MAIN 程式的起始地址為 0000H。
8、END指令 END指令用來控制彙編結束。在每個彙編程式的最後一行必須有一條END指令, 並且END指令只能出現一次。
9、EQU指令 EQU 指令用於將一個數值或暫存器名賦給一個指定的符號名。 格式: 符號名 EQU 表達式 或 符號名 EQU 暫存器名 表達式必須是一個簡單再定位表達式。 用 EQU 指令賦值以後的字元名,可以用作數據地址、代碼地址、位地址或者 直接當做一個立即數使用。
LIMIT EQU 1200 COUNT EQU R5。
10、DATA 指令 DATA 指令用於將一個內部 RAM 的地址賦給指定的符號名。 格式: 符號名 DATA 表達式 數值表達式的值在 0-255 之間,表達式必須是一個簡單再定位表達式。 PORT1 DATA 40H。
11、DB 指令 DB 指令以表達式的值的位元組形式初始化代碼空間。 格式: [標號:] DB 表達式表 表達式中可包含符號、字元串、或表達式等項,各個項之間用逗號隔開,字元串套用引號括起來。 括弧內的標號是可選項,如果使用了標號,則標號的值將是表達式表中第一位元組的地址。 DB 指令必須位於 CODE 段之內,否則將會發生錯誤。 TABLE: DB 0C0H, 0F9H, 0A4H TABLE1: DB " WEINA 。