匯編語言程序語句除指令以外還可以由偽操作和宏指令組成.偽操作又稱偽指令,它不像機器指令那樣是在程序運行期間由計算機來執行的,它是在匯編程序對源程序匯編期間由匯編程序處理的操作,這們可以完成如數據定義、分配存儲區、指示程序結束等功能。
一、數據定義及存儲器分配偽操作
這一類偽操作的格式是:
[Variable] Mnemonic Operand,...,Operand[;Comments]
其中變量(Variable)字段是可有可無的,它用符號地址表示,其作用與指令語句前的標號相同,但它的後面不跟冒號.如果語句中有變量則匯編程序使其記以第一個字節的偏移地址.
注釋(Comments)字段用來說明該偽操作的功能,它也是可有可無的.
助記符(Mnemonic)字段說明所用偽操作的助記符,常用的有以下幾種:
DB偽操作用來定義字節,其後的每個操作數都占有一個字節.
DW偽操作用來定義字,其後的每個操作數都占有一個字(低位字節在第一個字節地址中,高位字節在第二個字節地址中).
DD偽操作用來定義雙字,其後的每個操作數占有二個字.
DQ偽操作用來定義四個字,其後的每個操作占有四個字.
DT偽操作用來定義十個字節(五個字),其後的每個操作數占有十個字節,形成壓縮的BCD碼.
操作數字段還可以使用復制操作符(duplication opreator)來復制某個操作數,例:
ARRAY1 DB 2 DUP(0,1,2,?)
注1:使用PTR屬性操作符,可以指定操作數的類型屬性.
例:
MOV AX,WORD PTR OPER1
注2:使用LABEL偽操作可以使同一變量具有不同的類型屬性.
例:
BYTE_ARRAY LABEL BYTE
WORD_ARRAY DW 50 DUP(?)
二、表達式賦值偽操作EQU
格式:變量名 EQU 表達式
例:
CONST EQU 256 數賦以符號名
DATA EQU HEIGHT+12 地址表達式賦以符號名
ALPHA EQU 7
BETA EQU ALPHA-2
B EQU [BP+8] 變址引用賦以符號名B
P8 EQU DS:[BP+8]
另有一個與EQU類似的=偽操作也可以作為賦值操作使用.這們之間的區別是EQU偽操作中的表達式名是不允許重復定義的,而=偽操作則允許重復定義.
例:
EMP=7
EMP=EMP+1
三、段定義偽操作
存儲器的物理地址是由段地址和偏移地址組合而成的,匯編程序在把源程序轉換為目標程序時,必須確定標號和變量的偏移地址,並且需要把有關信息通過目標模塊傳送給連接程序,以便連接程序把不同的段和模塊連接在一起形成一個可執行程序.為此,需要用到段定義偽操作,段定義偽操作的格式如下:
segment_name SEGMENT
...
segment_name ENDS
其中刪節號部分,對於數據段、附加段和堆棧段來說,一般是存儲單元的定義、分配等偽操作;對於代碼段則是指令及偽操作。
此外,還必須明確段和段寄存儲器的關系,這可用ASSUME偽操作來實現,其格式為:
ASSUME assignment,...,assignment
其中assignment說明分配情況,其格式為:
segment_register_name:segment_name
其中段寄存器名必須是CS、DS、ES和SS中的一個,而段名必須是由SEGMENT定義的段中的段名。而ASSUME NOTHING則可取消前面由ASSUME所指定的段寄存器。
由於ASSUME偽操作只是指定某個段分配給哪一個段寄存器,它並不能把段地址裝入段寄存器中,所以在代碼段中,還必須把段地址裝入相應的段寄存器中。但是,代碼段不需要這樣做,代碼段的這一操作是在程序初始化時完成的。
SEGMENT偽操作還可以增加類型及屬性的說明,格式如下:
segname SEGMENT [align_type]
[combine_type]
['class']
...
segname ENDS
一般情況下,這些說明可以不用.但是,如果需要用連接程序把本程序與其他程序模塊相連接時,就需要使用這些說明.分別敘述如下:
.定位類型(align_type)可以是:
PARA 指定段的起始地址必須從小段邊界開始,即段地址的最低的16進制數位必須為0.
BYTE 該段可以從任何地址開始
WORD 該段必須從字的邊界開始,即段地址必須為偶數
PAGE 該段必須從頁的邊界開始,即段地址的最低兩個16進制數位必須為0(該地址能被256整除)
.組合類型(combine_type)可以是:
PUBLIC 該段連接時將與有相同名字的其他分段連接在一起.其連接次序由連接命令指定.
COMMON 該段在連接時與其他同名分段有相同的起始地址,所以會產生覆蓋.COMMON的連接長度是各分段中最大長度.
AT expression 使段的起始地址是表達式所計算出來的16位段地址.但它不能用來指定代碼段.
STACK 指定該段在運行時為堆棧段的一部分.
MEMORY 指定該將分配在所有其他連接在一起的段的前面(在高地址上),如果連接時有幾個指定MEMORY的段,則遇到的第一個段作為MEMORY段,其他段則作為COMMON段.
.類別('class') 連接時用於組成段組的名字.
四、程序開始和結束偽操作
在程序的開始可以用NAME或TITLE為模塊取名字,NAME的格式是:
NAME module_name
匯編程序將以給出的module_name作為模塊的名字.如果程序中沒有NAME偽操作,則也可使用TITLE偽操作,其格式為:
TITLE text
TITLE偽操作可指定每一頁上打印的標題.同時,如果程序中沒有使用NAME偽操作,則匯編程序將用text中的前六個字符作為模塊名.text最多可以60個字符.如果程序既無NAME又無TITLE偽操作,則將用源程序文件名作為模塊名.
表示源程序結束的偽操作的格式為:
END [label]
其中標號指示程序開始執行的起始地址.如果多個程序模塊相連接,則只有主程序要使用標號,其他子程序模塊則只用END而不必指定標號.
五、對准偽操作
.EVEN偽操作使下一個字節地址成為偶數.一個字的地址最好從偶地址開始,所以對於字數組為保證其從偶地址開始,可以在它前面用EVEN偽操作來達到這一目的,例如:
DATA SEGMENT
...
EVEN
WORDAY DW 100 DUP(?)
...
DATA ENDS
.ORG Constant expression
如常數表達式的值為n,則ORG偽操作可以使下一個字節的地址為常數表達式的值n.
地址計數器的值可以用$來表示,匯編語言允許用戶直接用$來引用地址計數器的值,因此:
ORG $+8
可以表示跳過8個字節的存儲區.
JMP $+2
可以表示一條空指令,該指令只是延遲處理機的一些時間,而無其他功能.
六、基數控制偽操作
匯編程序默認的數為十進制數,因而除非專門指定,匯編程序把程序中出現的數均看作十進制數,為此,當使用其他基數表示的常數時,需要專門以標記如下:
.二進制數:由一串0、1組成其後跟以字母B,如00101100B
.十進制數:由0~9的數字組成。一般情況下後面不必加上標記,在指定其他基數的情況下,後面可跟字節字母D,如178D。
.十六進制數:由0~9及A~F組成的數,後面跟字母H。這個數的第一個字符必須是0~9,所以如果第一個字符是A~F時,應在其前加上數字0,如0FFFFH。
.八進制數:由數字0~7組成的數,後面可跟字母O或Q,如1777Q。
.RADIX偽操作,可以把默認的基數改變為2~16范圍內的任何基數,其格式如下:
.RADIX expression
其中表達式用來表示基數值(用十進制表示)。
例如:
MOV BX,OFFH
MOV BX,178
與
.RADIX 16
MOV BX,0FF
MOV BX,178D
是等價的。應當注意,在用.RADIX 16把基數定為十六進制後,十進制數後都應跟字母D。在這種情況下,如果某個十六進制數的末字符為D,則應在其後跟字母H,以免與十進制數發生混淆。
.字符串可以看成串常,可以用單引號或雙引號把字符串放在其中,得到的是字符串的ACSII值,例如:‘ABCD’。
六、過程定義偽操作
格式為:
procedure_name PROC Attribute
.
.
.
procedure_name ENDP
其中過程名為標識符,它又子程序入口的符號地址,它的寫法與標號的寫相同.屬性(Attribute)是指類型屬性,它可以是NEAR或FAR.段內調用使用NEAR屬性,段間調用使用FAR屬性