§4.3 偽指令(指示性語(yǔ)句)
本節(jié)概述
在ASM 86中有多種偽指令,它們是符號(hào)定義語(yǔ)句、數(shù)據(jù)定義語(yǔ)句、段定義語(yǔ)句、過(guò)程定義語(yǔ)句和終止語(yǔ)句。
教學(xué)目標(biāo)
掌握各種偽指令。
學(xué)習(xí)內(nèi)容
符號(hào)常數(shù)定義語(yǔ)句
變量定義語(yǔ)句(數(shù)據(jù)定義語(yǔ)句)
存儲(chǔ)單元的類型
分析運(yùn)算符和合成運(yùn)算符
段定義語(yǔ)句
子程序定義語(yǔ)句
匯編結(jié)束語(yǔ)句
重點(diǎn)難點(diǎn)
各種語(yǔ)句定義的格式。
學(xué)習(xí)方法
掌握各種語(yǔ)句的定義格式。
關(guān)鍵字
偽指令
參考資料
1、《微型計(jì)算機(jī)技術(shù)及應(yīng)用》,戴梅萼等編著,第二版,清華大學(xué)出版社
2、《微型計(jì)算機(jī)原理》,季維法等編著,第一版,電子科技大學(xué)出版社
3、《微型計(jì)算機(jī)原理—常見(jiàn)題型解析及模擬題》,武自芳主編,西北工業(yè)大學(xué)出版社
4、《80X86/80X87匯編語(yǔ)言程序設(shè)計(jì)》,洪志全等編著,電子科技大學(xué)出版社
§4.3.1 符號(hào)定義語(yǔ)句
EQU偽指令給一個(gè)符號(hào)定義一個(gè)值,或定義一個(gè)符號(hào),該語(yǔ)句有如下兩種形式:
名字 EQU 表達(dá)式
新名字 EQU 老名字
該偽指令功能是給名字(符號(hào))定義一個(gè)值或其他符號(hào)。
符號(hào)定義語(yǔ)句不能重新定義,即在同一個(gè)程序中,用EQU定義的符號(hào),不能再賦以不同值。但可以用一個(gè)解除語(yǔ)句對(duì)某符號(hào)的定義,以便給符號(hào)重新定義。解除語(yǔ)句格式為:
PUREG 符號(hào)1,符號(hào)2,……,符號(hào)n
該語(yǔ)句本身不允許有名字。
與符號(hào)定義語(yǔ)句類似,還有一個(gè)等號(hào)語(yǔ)句,所不同的是允許對(duì)符號(hào)進(jìn)行再定義。
“=”偽指令的功能類似EQU,不同之處是EQU偽指令不允許對(duì)符號(hào)重復(fù)定義,而“=”偽指令則允許對(duì)同一符號(hào)多次重復(fù)定義,即可對(duì)符號(hào)名再定義,其格式為:
符號(hào)名=表達(dá)式。
§4.3.2 變量定義語(yǔ)句(數(shù)據(jù)定義語(yǔ)句)
這類語(yǔ)句用于為數(shù)據(jù)分配存儲(chǔ)單元,并可以用一個(gè)符號(hào)與這個(gè)存儲(chǔ)單元相聯(lián)系,也可以為存儲(chǔ)單元分配初值,并為數(shù)據(jù)提供一個(gè)任選初值。其格式為:
符號(hào) DX 表達(dá)式
其中定義符內(nèi)X為字母B、W、D、Q、T之一。
DB偽指令:定義字節(jié)型存儲(chǔ)單元(Define Byte),字節(jié)的值域?qū)τ跓o(wú)符號(hào)整數(shù)為0~255,對(duì)帶符號(hào)的 整數(shù)為-128~+127。初值表中各項(xiàng)數(shù)據(jù)用逗號(hào)隔開(kāi),每項(xiàng)數(shù)據(jù)占一個(gè)字節(jié)單元。符號(hào)名為變量名,是初值表中第一項(xiàng)數(shù)據(jù)所在存儲(chǔ)單元的符號(hào)地址,初值表中第一項(xiàng)數(shù)據(jù)后面?zhèn)€項(xiàng)數(shù)據(jù)的單元地址依次在該符號(hào)地址上遞增1。如果初值表中的初始值為“?”。則對(duì)應(yīng)字節(jié)單元將不賦初值,其內(nèi)容為未定義的不確定值。
DW偽指令:定義字節(jié)存儲(chǔ)單元(Define Word),字的值域?qū)o(wú)符號(hào)整數(shù)為0~65535,對(duì)帶符號(hào)數(shù)為-32768~+32767,它與DB不同的是初值表中各項(xiàng)數(shù)據(jù)占一個(gè)字單元(兩個(gè)字節(jié)),并且字單元不僅可以存放整型數(shù),還可以存放變量的偏移地址。
DD偽指令:定義雙字型存儲(chǔ)單元(Define Double Word),每個(gè)數(shù)據(jù)項(xiàng)占4個(gè)字節(jié)單元。雙字單除了可存放雙字整數(shù)外,還可以存放實(shí)數(shù)或存放一個(gè)變量的段地址和偏移地址。
由匯編語(yǔ)言產(chǎn)生的目標(biāo)碼、指令和存放指令的地址,在目標(biāo)碼產(chǎn)生后,指令就已經(jīng)放在指令存儲(chǔ)器中,然后就可以執(zhí)行。在指令送至存儲(chǔ)器的時(shí)候,數(shù)據(jù)項(xiàng)的初值也可以送至存儲(chǔ)器中,這意味著目標(biāo)碼除了包含指令和它們的地址外,也可包含數(shù)據(jù)項(xiàng)的初值和地址,這些初值是由數(shù)據(jù)定義語(yǔ)句所規(guī)定的。例
在匯編時(shí)遇到問(wèn)號(hào)(?),則只為數(shù)據(jù)項(xiàng)分配響應(yīng)的存儲(chǔ)單元,但不產(chǎn)生目標(biāo)碼來(lái)初始化這些存儲(chǔ)單元,即不為數(shù)據(jù)項(xiàng)規(guī)定相應(yīng)初值,用來(lái)存放指令執(zhí)行時(shí)間的中間結(jié)果。
初值除直接表示數(shù)據(jù)定義語(yǔ)句中外,還可用一個(gè)表達(dá)式來(lái)表示。表達(dá)式的值可以由匯編時(shí)計(jì)算或由EQU語(yǔ)句給出。
同樣,在存儲(chǔ)單元中可以存放地址值,存放段內(nèi)偏移量需一個(gè)字,存放全地址則需要兩個(gè)字 ,一個(gè)字放段字址,另一個(gè)字放放段內(nèi)偏移量。
在實(shí)際應(yīng)用中,還經(jīng)常會(huì)用到由字節(jié)、字或雙字構(gòu)成的表。如8086中XLAT指令可以利用一個(gè)由字節(jié)組成的表,把一個(gè)編碼轉(zhuǎn)換為同一個(gè)值的另一個(gè)編碼;中斷服務(wù)程序的入口地址表,其中每一項(xiàng)是一個(gè)雙字指針,串操作指令對(duì)包含串元素的由字節(jié)或字組成的表進(jìn)行操作等。如何在內(nèi)存中建立這樣的表呢?只要在數(shù)據(jù)定義語(yǔ)句的參數(shù)部分,因如若干個(gè)用逗號(hào)分隔的參數(shù)就可以建立一個(gè)表。
可以用數(shù)據(jù)定義語(yǔ)句在內(nèi)存中定義一個(gè)字符串,字符串中的每一個(gè)字符用它的ASCII碼表示,為一個(gè)字節(jié),故字符串的定義必須用DB命令。有兩種定義字符串的方法,一種是字符串中的每一個(gè)字符分別定義,每個(gè)字符之間用逗號(hào)分隔;另一種方法在整個(gè)字符串的前后加單引號(hào)。
§4.3.3 存儲(chǔ)單元的類型
1、 變量的類型
變量在定義時(shí)被指定其類型,變量的類型可以是:字節(jié)(Byte,用DB定義)、字(Word,用DW定義)、雙字(DWORD,用DD定義)。
變量被指定類型后,匯編程序能生成正確的機(jī)器碼。
像[SI]這樣的存儲(chǔ)單元,匯編程序不知道其類型是字節(jié)、字、雙字。應(yīng)該在源程序中用偽指令明確指出。
2、調(diào)用和轉(zhuǎn)移的類型(SHORT、NEAR、FAR)
規(guī)定一個(gè)NEAR指令單元長(zhǎng)度為兩字節(jié),一個(gè)FAR指令單元長(zhǎng)度為四字節(jié)。指令位置能出現(xiàn)在跳轉(zhuǎn)或調(diào)用指令語(yǔ)句中,如果指令的位置類型為NEAR型,那么匯編程序就產(chǎn)生一條段內(nèi)跳轉(zhuǎn)或調(diào)用指令,若該單元類型為FAR型,匯編程序就產(chǎn)生一條段間跳轉(zhuǎn)或調(diào)用指令。一個(gè)存儲(chǔ)器地址加上或減去一個(gè)數(shù)字量,所得到的新存儲(chǔ)器地址與源存儲(chǔ)器地址具有相同的類型。
§4.3.4 分析運(yùn)算符和合成運(yùn)算符
分析運(yùn)算符用來(lái)將存儲(chǔ)器操作數(shù)分解為它的組成部分,這類運(yùn)算符有SEG,OFFSET,TYPE,SIZE,LENGHT。合成運(yùn)算符有PTR和THIS。
1、SEG、OFFSET(分析運(yùn)算符)
SEG運(yùn)算符返回的是存儲(chǔ)器地址操作數(shù)的段分量,即取得存儲(chǔ)器符號(hào)的段地址值;
OFFSET運(yùn)算符返回的是段內(nèi)偏移量,即取得存儲(chǔ)器符號(hào)的地址偏移量。 這兩種分量一般都是數(shù)值。
2、 TYPE、LENGTH、SIZE(分析運(yùn)算符)
TYPE取得存儲(chǔ)器操作數(shù)的類型(字節(jié)=1,字=2,雙字=4),返回一個(gè)數(shù)值,它表示存儲(chǔ)器操作數(shù)相關(guān)的類型部分。各種存儲(chǔ)器地址操作數(shù)類型部分的值分別為:數(shù)據(jù)字節(jié)為1;數(shù)據(jù)字為2;數(shù)據(jù)雙字為4;NEAR和FAR的值無(wú)實(shí)際的物理意義。
LENGTH取得存儲(chǔ)器操作數(shù)元素的個(gè)數(shù),即返回的數(shù)值是與存儲(chǔ)器地址操作數(shù)相關(guān)的單元(字節(jié)、字或雙字)數(shù)目。
SIZE取得存儲(chǔ)器操作數(shù)占用的存儲(chǔ)器字節(jié)數(shù),即返回的數(shù)值等于分配給指定的存儲(chǔ)器地址操作數(shù)的字節(jié)數(shù)。
注意:MASM 5.0驗(yàn)證(99.2.13)
X DW 5 DUP (0) ;LENGTH X=5
Y DW 0,0,0,0,0 ;LENGTH Y=1
3、 PTR、THIS(合成運(yùn)算符)
PTR用于指定存儲(chǔ)單元的類型,它能產(chǎn)生一個(gè)新的存儲(chǔ)器地址操作數(shù)(一個(gè)變量或標(biāo)號(hào))。新的操作數(shù)的段地址和段內(nèi)偏移量與源操作數(shù)相同,但類型不同。它與數(shù)據(jù)定義語(yǔ)句不同,PTR運(yùn)算符不分配任何存儲(chǔ)器,它只是給已分配了的存儲(chǔ)單元一個(gè)新的意義。
THIS產(chǎn)生一個(gè)新的變量或標(biāo)號(hào),其地址等于當(dāng)前地址,類型在THIS中指定。(THIS不分配存儲(chǔ)器)。
4、$
$符號(hào)表示當(dāng)前地址。
§4.3.5 段定義偽指令SEGMENT/ENDS
關(guān)心匯編語(yǔ)言源程序的段結(jié)構(gòu)的原因是:
(1) CPU是按分段方式尋址的,即CPU對(duì)存儲(chǔ)器的訪問(wèn)按分段進(jìn)行,把存儲(chǔ)器的地址分為段基地址和相對(duì)于段基地址的偏移量,用CS:IP尋址代碼段;用SS:SP尋址堆棧段;用DS或ES表示數(shù)據(jù)段的基地址,用尋址方式表示數(shù)據(jù)段的偏移量。
(2) 匯編程序(MASM)知道程序的段結(jié)構(gòu)后,才能產(chǎn)生正確的機(jī)器指令。
例如,產(chǎn)生正確的段內(nèi)調(diào)用、段間調(diào)用、段內(nèi)轉(zhuǎn)移、段間轉(zhuǎn)移指令機(jī)器碼。
(3) 當(dāng)指令對(duì)當(dāng)前數(shù)據(jù)段、堆棧段訪問(wèn)時(shí),產(chǎn)生最優(yōu)指令,而對(duì)其他段訪問(wèn)時(shí),在指令前要加段超越前綴或改變段寄存器的值。
在匯編語(yǔ)言源程序中,段按如下格式定義:
段名 SEGMENT 段屬性
語(yǔ)句行
┇
語(yǔ)句行
段名 ENDS
其中,"段屬性"包含"定位類型"、"組合類型"、"類別"。
1、 定位類型(Align)
定位類型選項(xiàng)表示該段的起始邊界要求,有PAGE(頁(yè)邊界)、PARA(節(jié)邊界)、WORD(字邊界)、BYTE(字節(jié)邊界)四種,缺省是PARA, 如表所示。見(jiàn)圖4-3。


2、 組合類型(Combine)
Combine 選項(xiàng)指示連接程序(LINK)如何處理同名段。
可有如下選擇:
(1) NONE,沒(méi)有指定Combine選項(xiàng),連接程序(LINK)不把同名段合并,在可執(zhí)行文件中,每個(gè)模塊的同名段均有自己的物理段基地址。
(2) PUBLIC,指示LINK將所有同名段合并成一個(gè)新的連續(xù)段,新段中的所有指令和數(shù)據(jù)的地址使用同一個(gè)段寄存器,所有偏移量調(diào)整為相對(duì)與新段的首地址。
(3) COMMON,指示LINK將所有同名段置為相同起始地址,段的最終長(zhǎng)度等于所有段中的最大長(zhǎng)度。
(4) AT address,指示LINK,段內(nèi)所有標(biāo)號(hào)和變量的地址,都根據(jù)地址address來(lái)確定。
(5) STACK,指示LINK將所有同名段合并成一個(gè)新的連續(xù)段,且把新段作為堆棧區(qū)域使用。堆棧指針SP被初始化為該新段的長(zhǎng)度。堆棧段基地址寄存器SS的值被初始化為新段的首地址。
(6) MEMORY,指示LINK把本段定位在其他段之上(地址較大),如果有多個(gè)MEMORY屬性段,LINK只把第一個(gè)作為MEMORY屬性處理,其他作為COMMON屬性處理。
3、 類別('Class')
類別可以是任何合法名稱,必須用單引號(hào)括起來(lái)。當(dāng)未指定類別時(shí),該段的類別名為空。 LINK把同類別名的段連續(xù)放在一起。(不合并)。
4、 ASSUME偽指令
ASSUME偽指令告訴匯編程序(MASM),存儲(chǔ)器尋址的缺省段名。
例:ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK 告訴匯編程序:
段名為CODE的段是代碼段,其基地址與CS相聯(lián)系。
段名為DATA的段是數(shù)據(jù)段,其基地址與DS相聯(lián)系。
段名為DATA的段同時(shí)也是附加段,其基地址與ES相聯(lián)系。
段名為STACK的段是堆棧段,其基地址與SS相聯(lián)系。
注意,ASSUME偽指令與程序運(yùn)行時(shí)段寄存器的值毫無(wú)關(guān)系。
(1) 程序運(yùn)行時(shí),DS、ES寄存器的值,用指令賦給。如,
MOV AX,DATA ;DATA是段名
MOV DS,AX MOV ES,AX
(2) 程序運(yùn)行時(shí),SS和SP的值 當(dāng)某一個(gè)段具有STACK組合屬性(Combine)時(shí),SS的初值被自動(dòng)初始化為該段的基地址,SP的初值被自動(dòng)初始化為該段的長(zhǎng)度。
SS、SP的值也可以用指令來(lái)設(shè)定,如,
MOV AX,STACK ;STACK是段名
MOV SS,AX
MOV SP,1000H
(3) CS和IP的值
CS的初值由END偽指令指定。例,
END START ;START是一個(gè)標(biāo)號(hào)
指定CS的初值等于標(biāo)號(hào)START的段地址。
IP的初值一般為0000H,也可以使用ORG偽指令改變。如,
代碼段中,
ORG 100H
指定IP的值等于0100H。
CS、IP的值在程序運(yùn)行過(guò)程中自動(dòng)變化。當(dāng)指令順序執(zhí)行時(shí),每執(zhí)行一條指令,IP的值增加該指令的機(jī)器碼長(zhǎng)度;調(diào)用/返回調(diào)用、中斷/返回中斷、轉(zhuǎn)移可以改變CS、IP的值。
5、 ORG偽指令
代碼段中的ORG偽指令,指定IP的值。
數(shù)據(jù)段中的ORG偽指令,指定下一個(gè)存儲(chǔ)單元的地址偏移量。如,
DATA SEGMENT
ORG 200H
X DW ?
DATA ENDS 指定變量X的地址偏移量為200H。
§4.3.6 子程序定義語(yǔ)句
子程序,又稱為過(guò)程。
定義:
子程序名 PROC 屬性
┇
RET
┇
RET
子程序名 ENDP
子程序用PROC/ENDP偽指令定義。定義時(shí),可以指定子程序的屬性(NEAR或FAR),若不指定,匯編程序認(rèn)為是NEAR屬性。
子程序用CALL指令調(diào)用,為了讓匯編程序產(chǎn)生正確的機(jī)器指令,調(diào)用時(shí)可以指定調(diào)用類型(FAR段間調(diào)用,NEAR段內(nèi)調(diào)用)。若未指定調(diào)用類型,而匯編程序又不能確認(rèn)時(shí),認(rèn)為是NEAR段內(nèi)調(diào)用。
CALL 子程序名
CALL NEAR PTR 子程序名
CALL FAR PTR 子程序名
子程序中,必須有一個(gè)RET指令被執(zhí)行,允許子程序中出現(xiàn)過(guò)個(gè)RET指令。RET指令也可以帶參數(shù)。
RET
RET n ;n為0~65535間的偶數(shù)。
§4.3.7 匯編結(jié)束偽指令END
這是一條源程序結(jié)束指令。它告訴匯編程序,對(duì)源程序進(jìn)行匯編時(shí),遇到該語(yǔ)句,說(shuō)明源程序到此結(jié)束,以后的內(nèi)容不屬于本程序了。終止語(yǔ)句格式為:
END [表達(dá)式]
這里的表達(dá)式通常就是程序的第一條指令前面的標(biāo)號(hào),這樣,程序在匯編、連接后,得到的目標(biāo)程序在執(zhí)行時(shí)會(huì)自動(dòng)從第一條指令開(kāi)始。當(dāng)然,這個(gè)表達(dá)式也可以省略。
源程序結(jié)束偽指令,匯編程序遇到該偽指令時(shí),結(jié)束翻譯源程序。如果END偽指令帶標(biāo)號(hào),指定程序運(yùn)行時(shí)CS的初值等于該標(biāo)號(hào)的段地址。
