4.1 匯編語(yǔ)言的格式
4.1.1 8086匯編語(yǔ)言程序的一個(gè)例子
- 8086匯編的一個(gè)語(yǔ)句行是由4個(gè)部分組成的,即:
標(biāo)號(hào) 操作碼 操作數(shù) ;注釋?zhuān)ɑ蛎郑?/li>
4.1.2 8086匯編語(yǔ)言源程序的格式
- 源程序的一般格式位:
NAME1 SEGMENT
語(yǔ)句
語(yǔ)句
NAME1 ENDS
NAME2 SEGMENT
語(yǔ)句
語(yǔ)句
NAME2 ENDS
END<標(biāo)號(hào)>
語(yǔ)句行的構(gòu)成
4.2.1 標(biāo)記(Token)
1.IBM宏匯編的字符集
(1)字母
- 包含大寫(xiě)的英文字母
- 小寫(xiě)的英文字母
(2)數(shù)字 - 阿拉伯?dāng)?shù)字
(3)特殊字符 -
IBM中宏匯編字符集中可打印字符
2.界符
-
IBM宏匯編字符集中可打印字符
3.常量
(1)數(shù)字(整數(shù))常量
①二進(jìn)制常量
- 字母B結(jié)尾
②十進(jìn)制常量 - 字母D結(jié)尾
③八進(jìn)制常量 - 以字母Q結(jié)尾
④十六進(jìn)制 - 以字母H結(jié)尾
(2)字符串常量
- 字符串常量是由包含在單引號(hào)內(nèi)的1或2個(gè)ASCII碼構(gòu)成的
4.標(biāo)識(shí)符
- 標(biāo)識(shí)符是由程序員自由建立起來(lái)的、有特定意義的字符序列,如例子中的SUM、CYCLE、PORT_VAL等
- 一個(gè)標(biāo)識(shí)符是由最多31個(gè)字母、數(shù)字及規(guī)定的特殊字符(?@_$)等組成的,且不能用數(shù)字打頭(以免與十六進(jìn)制數(shù)向混淆)
5.保留字
- 保留字看上去像標(biāo)識(shí)符,但是它們?cè)谡Z(yǔ)言中有特殊的意義,而且不能用它們作為標(biāo)識(shí)符
IBM宏匯編中的保留字



6.注釋
- 為了使匯編語(yǔ)言的源程序更便于閱讀和理解,常在源程序中加上注釋
- 注釋是在分號(hào)(;)后面的任意的字符序列,知道行的結(jié)尾
- 在匯編時(shí),匯編程序?qū)λ鼈儾⒉贿M(jìn)行處理
- 可打印的文件中,注釋和源程序一起打印
4.2.2 符號(hào)(Symbol)
1. 寄存器
2.變量
- 所有變量都有三種屬性:
(1)段值(SEGMENT),即變量單元所在段的段地址(段的起始地址)的高16位,低4位始終為0
(2)偏移量(OFFSET),即變量單元地址與段的起始地址之間的偏移量(16位)
(3)類(lèi)型(TYPE),變量有三種類(lèi)型:字節(jié)(Byte)、字(word)和雙字(Double Word)
3.標(biāo)號(hào)(Label)
- 標(biāo)號(hào)是某條指令所存放單元的符號(hào)地址,它是轉(zhuǎn)移(條件轉(zhuǎn)移或無(wú)條件轉(zhuǎn)移)指令或調(diào)用(CALL)指令的目標(biāo)操作數(shù)
- 標(biāo)號(hào)的類(lèi)型與變量不同,它的類(lèi)型是NEAR或是FAR
4.數(shù)
- 匯編源程序中的常數(shù)也常以符號(hào)的形式出現(xiàn)
5.其他符號(hào)
4.2.3 表達(dá)式(Expressions)
1.操作數(shù)(Operands)
- 一個(gè)操作數(shù)或者一個(gè)寄存器名,或是一個(gè)常量(數(shù)字常量或字符串常量),或是一個(gè)存儲(chǔ)器操作數(shù)
(1)常量操作數(shù)
- 具有數(shù)字值的操作數(shù)是常量或是表示常量的標(biāo)識(shí)符(符號(hào))
- 例中的常量操作數(shù)是100、PORT_VAL
- 常量操作數(shù)的值允許范圍是從-65535 ~ +65535
(2)存儲(chǔ)器操作數(shù)
- 存儲(chǔ)器操作數(shù),通常是標(biāo)識(shí)符
- 具體地說(shuō),可以分為標(biāo)號(hào)(Label)和變量(Variable)兩種
變量可以具有以下幾種尋址方式:
①直接尋址
②基址尋址
③變址(索引)尋址
④基址變址尋址
2.運(yùn)算符(Operators)
(1)算術(shù)運(yùn)算符(Arithmetic Operators)
- 一個(gè)是加(+)減、乘、除運(yùn)算發(fā)
- 另一個(gè)算術(shù)運(yùn)算符是MOD
因此對(duì)例子中地存儲(chǔ)其地址作如下運(yùn)算:
SUM+2
CYCLE-5
NOT_DONE-GO
是有效地表達(dá)式。而
SUM-CYCLE
(2)邏輯運(yùn)算符
- 邏輯運(yùn)算符是按位操作地AND、OR、XOR和NOT
(3)關(guān)系運(yùn)算符 - 在IBM宏匯編中有以下關(guān)系運(yùn)算符
①相等Equal(EQ)
②不等Not Equal(NE)
③小于Less Than(LT)
④大于Greater Than(GT)
⑤小于或等于Less Than or Equal(LE)
⑥大于或等于Greater Than or Equal(GE)
MOV BX ,PORT_VAL LT 5
若PORT_VAL地值小于5,關(guān)系為真,則會(huì)變程序在匯編后產(chǎn)生地語(yǔ)句為:
MOV BX ,OFFFFH
若PORT_VAL的值不小于5,則關(guān)系為假,匯編后產(chǎn)生的語(yǔ)句為:
MOV BX,0
(4)分析運(yùn)算符
- 把存儲(chǔ)器操作數(shù)分解為它的組成部分,如它的段值、段內(nèi)偏移量和類(lèi)型
(5)合成運(yùn)算符 - 由已存在的存儲(chǔ)器操作數(shù)生成一個(gè)段值和偏移量相同而類(lèi)型不同的新的存儲(chǔ)器操作數(shù)
4.2.4 語(yǔ)句(Statements)
一個(gè)匯編語(yǔ)言的源程序是由一條條語(yǔ)句組成的,語(yǔ)句就是對(duì)需要計(jì)算機(jī)完成的動(dòng)作的說(shuō)明
源程序中的語(yǔ)句可分為兩類(lèi):指令語(yǔ)句和指示性語(yǔ)句
指令語(yǔ)句,匯編程序把它們翻譯成機(jī)器代碼,這些代碼命令8086執(zhí)行某些操作。如MOV、ADD、JMP等
對(duì)于指示性語(yǔ)句(偽指令),匯編程序并不把它們翻譯成機(jī)器代碼,實(shí)際上也不可能翻譯成機(jī)器代碼,只是用來(lái)指示、引導(dǎo)匯編程序在匯編時(shí)做一些操作,如定義符號(hào)、分配存儲(chǔ)單元、初始化存儲(chǔ)器等,所以偽指令本身不占用存儲(chǔ)單元
例如:
MY_PLACE DB ?
指令語(yǔ)句的格式:
標(biāo)號(hào):助記符 參數(shù),...,參數(shù) ;注釋
指示性語(yǔ)句的格式為:
名字 命令 參數(shù),...,參數(shù) ;注釋
4.3 指示性語(yǔ)句
4.3.1 符號(hào)定義語(yǔ)句
1.等值語(yǔ)句EQU
NAME EQU EXPRESSION
- EQU語(yǔ)句給符號(hào)定義一個(gè)值,或定義為別的符號(hào)名,甚至可定義為一條可執(zhí)行的指令等
-
一些例子如下:
2.等號(hào)(Equal Sign) =語(yǔ)句
- 能對(duì)符號(hào)進(jìn)行再定義
EMP = 6
EMP = 7
EMP = EMP + 1
3.解除語(yǔ)句PURGE
PURGE 符號(hào)1,符號(hào)2,...,符號(hào)n
-
已經(jīng)用EQU命令定義的符號(hào),若以后不再用了,就可以用PURGE語(yǔ)句接觸
例如:
4.3.2 數(shù)據(jù)定義語(yǔ)句
數(shù)據(jù)定義語(yǔ)句,為一個(gè)數(shù)據(jù)項(xiàng)分配存儲(chǔ)單元,用一個(gè)符號(hào)名與這個(gè)存儲(chǔ)單元相聯(lián)系,且為這個(gè)數(shù)據(jù)提供一個(gè)人選的初始值
與該項(xiàng)相聯(lián)系的符號(hào)名稱(chēng)為變量
-
例子:
例如:THING DB 25
不僅使THING這個(gè)符號(hào)與一個(gè)字節(jié)的存儲(chǔ)單元相聯(lián)系,而且在匯編時(shí)會(huì)把25放入THING相聯(lián)系的存儲(chǔ)單元中
所以THING是一個(gè)字節(jié)變量,它的初始值為25BIGGER_THING DW 4142H
在匯編時(shí)就會(huì)把41H與42H分別放至與BIGGER_THING相聯(lián)系的兩個(gè)連續(xù)的字節(jié)單元中(一個(gè)字中),而且42H放在地址低的字節(jié),41H放在地址高的字節(jié)
所以,若BIGGER_THING是一個(gè)字變量,則它的初始值為4142H-
語(yǔ)句:BIGGEST_THING DD 12345678H
它定義了一個(gè)雙字變量,且給了初始值
一個(gè)存儲(chǔ)單元的類(lèi)型如下:
(1)數(shù)據(jù)字節(jié)
SUM DB ? ;定義一個(gè)字節(jié)
(2)數(shù)據(jù)字(兩個(gè)連續(xù)的字節(jié))
BIGGER DW ?; 定義一個(gè)字
(3)數(shù)據(jù)雙字(四個(gè)連續(xù)的字節(jié))
BIGGER DD ? ;定義一個(gè)雙字
(4)Near指令單元
CYCLE : CMP SUM,100
(5)Far指令單元
-
若在一個(gè)程序中,對(duì)它的數(shù)據(jù)段有如下定義:
其中的每一個(gè)存儲(chǔ)單元都有一些屬性(或組成成分)
分析運(yùn)算符SEG,返回的是一個(gè)存儲(chǔ)單元的段地址(即它所在段的起始地址)OFFSET運(yùn)算符返回的是每一個(gè)存儲(chǔ)單元地址的段內(nèi)偏移量,即它與段地址之間的偏差。故:
SEG BUFFER1
SEG BUFFER2
SEG BUFFER3
都是相同的,它們返回的地址都是DATA_TABLES的地址
所以,若要對(duì)數(shù)據(jù)段寄存器初始化,則可采用指令:
MOV AX,SEG BUFFER1
MOV DS,AX
而
OFFSET BUFFER1
OFFSET BUFFER2
OFFSET BUFFER3
是各不相同的,若要向這些緩沖區(qū)填入新的數(shù)據(jù),可以采用一些地址指針,則可以用以下指令來(lái)初始化地址指針:
MOV BX ,OFFSET BUFFER1
MOV SI,OFFSET BUFFER2
MOV DI,OFFSET BUFFER3
以后,就可以用這些指針來(lái)間接尋址這些緩沖區(qū)
存儲(chǔ)器地址操作數(shù)的類(lèi)型值

4.3.3 段定義語(yǔ)句
段定義的主要命令有①SEGMENT,②ENDS,③ASSUME,④ORG
SEGMENT和ENDS語(yǔ)句把匯編語(yǔ)言源程序分成段
這些段就相應(yīng)于存儲(chǔ)器段,在這些存儲(chǔ)器段中,存放相應(yīng)段的目標(biāo)碼
-
如何使用SEGMENT、ENDS和ASSUME命令,以定義代碼段、堆棧段、數(shù)據(jù)段和附加段
image.png
(1)不要搭接,段中的第一個(gè)可用字節(jié)是在16字節(jié)界限上
MY_SEG SEGMENT
.
.
.
MY_SEG ENDS
這是一種正常情況
(2)允許搭接,但第一個(gè)可用字節(jié)必須在字的界限上
MY_SEG SEGMENT WORD
.
.
.
MY_SEG ENDS
(3)段開(kāi)始在指定的16個(gè)字節(jié)界值上,但第一個(gè)可用字節(jié)在指定的偏移位置上
MY_SEG SEGMENT AT 1A2BH ; 段地址為1A2BH
ORG 0003H ;段內(nèi)從偏移量0003H開(kāi)始
MY_SEG ENDS
偽指令ORG的一般格式為:
ORG <表達(dá)式>
此語(yǔ)句指定了段內(nèi)在它以后的程序或數(shù)據(jù)塊存放的起始地址,也即以語(yǔ)句中的表達(dá)式的值作為起始地址,連續(xù)存放,除非遇到一個(gè)新的ORG語(yǔ)句
4.3.4 過(guò)程定義語(yǔ)句
過(guò)程定義語(yǔ)句的格式:
PROCEDURE_NAME PROC [NEAR]
或
PROCEDURE_NAME PROC FAR
RET
PROCEDURE _NAME ENDP
-
例子
4.3.5 結(jié)束語(yǔ)句
START:
END START
4.4 指令語(yǔ)句
4.4.1 指令助記符
1.NOP(No Operation)
- 使匯編產(chǎn)生一字節(jié)指令,使寄存器AX的內(nèi)容自行交換
2.保留空格(Place Holder)
- NIL是使匯編程序不產(chǎn)生任何指令的唯一的指令助記符
4.4.2 指令前綴
- IBM宏匯編中允許作為前綴的助記符:
LOCK
REP(Repeat)
REPE (當(dāng)相等時(shí)重復(fù))
REPNE (當(dāng)不相等時(shí)重復(fù))
REPZ (當(dāng)標(biāo)志ZF=1時(shí)重復(fù))
PEPNZ (當(dāng)標(biāo)志ZF=0時(shí)重復(fù))
具有前綴的指令語(yǔ)句例子
CYCLE: LOCK DEC COUNT
4.4.3 操作數(shù)尋址方式
1.立即
MOV AX,15 ;15是一個(gè)立即數(shù)
2.寄存器
MOV AX,15 ;15是一個(gè)寄存器操作數(shù)
3.直接
SUM DB ?
MOV SUM,15 ;SUM是一個(gè)直接存儲(chǔ)操作數(shù)
4.通過(guò)基址寄存器間接
MOV AX,[BX]
MOV AX,[BP]
5.通過(guò)變址寄存器間接
MOV AX,[SI]
MOV AX,[DI]
6.通過(guò)基址寄存器加變址寄存器間接
MOV AX,[BX][SI]
MOV AX,[BX][DI]
MOV AX,[BP][SI]
MOV AX,[BP][DI]
7.通過(guò)基址或變址寄存器加位移量間接
MANY_BYTES DB 100 DUP (?)
.
.
.
MOV AX,MANY_BYTES[BX]
MOV AX,MANY_BYTES[BP]
MOV AX,MANY_BYTES[SI]
MOV AX,MANY_BYTES[DI]
8.通過(guò)基址寄存器加變址寄存器加位移量間接存儲(chǔ)器
MANY_BYTES DB 100 DUP (?)
.
.
.
MOV AX,MANY_BYTES[BX][SI]
MOV AX,MANY_BYTES[BX][DI]
MOV AX,MANY_BYTES[BP][SI]
MOV AX,MANY_BYTES[BP][DI]
4.4.4 串操作指令
ALPHA DB ?
BETA DB ?
MOV SI,OFFSET ALPHA
MOV DI,OFFSET BETA
MOV BETA,ALPHA
- 一個(gè)完整的匯編語(yǔ)言源程序應(yīng)該由可執(zhí)行命令組成的指令性語(yǔ)句和由對(duì)符號(hào)定義、分配存儲(chǔ)單元、分段等組成的指示性語(yǔ)句構(gòu)成的。而且,一個(gè)完整的程序至少應(yīng)該包含三種段:由源程序組成的代碼段。堆棧操作所需要的堆棧段和存放數(shù)據(jù)的數(shù)據(jù)段
該例子是把兩個(gè)分別由未組合的BCD碼(一個(gè)字節(jié)為一位BCD數(shù))的串相加;由于8086中允許兩個(gè)未組合的十進(jìn)制數(shù)相加,只要經(jīng)過(guò)適當(dāng)?shù)恼{(diào)整就可以得到正確的結(jié)果。所以,在程序中把第一個(gè)串的一位BCD數(shù)取至AL中,與第二個(gè)串的相應(yīng)位相加,經(jīng)過(guò)AAA調(diào)整,再把結(jié)果存至存儲(chǔ)器中。程序中的前面部分是為了設(shè)置段,先設(shè)置數(shù)據(jù)段,用DB偽指令定義兩個(gè)數(shù)據(jù)串,用COUNT表示數(shù)據(jù)的長(zhǎng)度。接著是定義堆棧段,為堆棧留下了100個(gè)單元的空間(實(shí)際上當(dāng)然由需要來(lái)定),然后是當(dāng)以代碼段,從標(biāo)號(hào)GO開(kāi)始就是可執(zhí)行指令部分。






4.5 匯編語(yǔ)言程序設(shè)計(jì)及舉例
4.5.1 算術(shù)運(yùn)算程序設(shè)計(jì)(直線運(yùn)行程序)
- 例 兩個(gè)32位無(wú)符號(hào)數(shù)乘法程序
4.5.2 分支程序設(shè)計(jì)
4.5.3 循環(huán)程序設(shè)計(jì)
1.用計(jì)數(shù)器控制循環(huán)
例題:在一串給定個(gè)數(shù)的數(shù)中尋找最大值(或最小值),放至指定的存儲(chǔ)單元。每個(gè)數(shù)用16位表示
2.多重循環(huán)
4.5.4 字符串處理程序
1.確定字符串的長(zhǎng)度
例題:從頭搜索字符串的結(jié)束標(biāo)志,統(tǒng)計(jì)搜索的字符個(gè)數(shù)
2.加偶校驗(yàn)到ASCII字符
- 例題:若有一個(gè)ASCII字符串,它的起始地址放在單元STRING內(nèi),要求從串中取出每一個(gè)字符,檢查其中包含的“1”的個(gè)數(shù),若已為偶數(shù),則它的最高有效位置“0”;否則,最高有數(shù)位置“1”,然后送回
4.5.5 碼轉(zhuǎn)換程序設(shè)計(jì)
1.十六進(jìn)制到ASCII的轉(zhuǎn)換
例4-5 若有一個(gè)二進(jìn)制數(shù)碼串,要把每一個(gè)字節(jié)中的二進(jìn)制轉(zhuǎn)換位兩位十六進(jìn)制數(shù)的ASCII,高4位的ASCII放在第hi高的單元。串中的第一個(gè)字節(jié)為串的長(zhǎng)度(小于128)
2.從二進(jìn)制到ASCII串的轉(zhuǎn)換
- 例4-6 把在內(nèi)存變量NUMBER中的16位二進(jìn)制數(shù),每一位轉(zhuǎn)換為相應(yīng)的ASCII,存入串變量STRING中
4.5.6 有關(guān)I/O的DOS功能調(diào)用
1.在CRT上連續(xù)輸出0 ~ 9
4.5.7 宏匯編與條件匯編
1.宏命令的用途
(1)在匯編語(yǔ)言的源程序中,若有的程序段要多次使用,為了使在源程序中不重復(fù)書(shū)寫(xiě)這個(gè)程序段,可以一條宏指令來(lái)代替。由宏匯編程序在匯編時(shí)產(chǎn)生所需要的代碼
MOV CL,4
SAL AL,CL
若要多次使用,就可以用一條宏指令代替:
SHFT MACRO
MOV CL,4
SAL AL,CL
ENDM
(2)宏定義不但能使源程序書(shū)寫(xiě)簡(jiǎn)潔,而且由于宏指令具有接受參量的能力,所以功能就更靈活
SHFT MACRO X,Y
MOV CL,X
SAL Y,CL
ENDM
(3)形式參量不只可以出現(xiàn)在操作數(shù)部分,也可以出現(xiàn)在操作碼部分。如:
SHFT MACRO X,Y,Z
MOV CL,X
S&Z Y,CL
ENDM
若有以下調(diào)用:
SHFT 4,AL,AL
SHIFT 6,BX,AR
SHIFT 8,SI,HR
在匯編時(shí),分別產(chǎn)生以下指令的目標(biāo)代碼
MOV CL,4
SAL AL,CL
MOV CL,6
SAR CL,6
SAR BX,CL
MOV CL,8
SHR SI,CL
2.IBM宏匯編中主要宏操作偽指令
(1)MACRO
宏定義名 MRRCO <形式參量表>
(2)PURGE
PURGE 宏定義名 [,......]
(3)LOCAL
- 例題在AL中有一位十六進(jìn)制數(shù)碼要轉(zhuǎn)換為ASCII,則可以用以下宏定義:
CHANGE MACRO
CMP AL,10
JL ADD_0
ADD AL,'A'-'0'-10
ADD_0 ADD AL,'0'
ENDM
上面的CHANGE宏定義在下有多次調(diào)用的情況,應(yīng)定義為:
CHANGE MACRO
LOCAL ADD_0
CMP AL,10
JL ADD_0
ADD AL,'A'-'0'-10
ADD_0 ADD AL,'0'
ENDM
(4)REPT
REPT <表達(dá)式>
ENDM
- 這個(gè)偽指令可以重復(fù)執(zhí)行在它的指令體部分所包含的語(yǔ)句。重復(fù)執(zhí)行的次數(shù),由表達(dá)式的值所決定
例4-7 把數(shù)字0 ~ 9的ASCII填入表TABLE。CHAR = ‘0’

例題4-8 建立一個(gè)地址表,其中每個(gè)字的內(nèi)容是下一個(gè)字的地址(用作地址指針),而最后一個(gè)字的內(nèi)容是第一個(gè)字的地址

(5)IRP
IRP 形式參量(參數(shù)表)
ENDM

(6)IRPC
IRPC 形式參量,字符串(或<字符串>)
ENDM

3.宏定義嵌套
4.宏指令與子程序的區(qū)別
(1)宏指令是為了簡(jiǎn)化源程序的書(shū)寫(xiě),在匯編時(shí),匯編程序處理宏指令,還把宏定義體插入到宏調(diào)用處。所以,宏指令并沒(méi)有簡(jiǎn)化目標(biāo)程序。有多少次宏調(diào)用,在目標(biāo)程序中仍需要有同樣多次的目標(biāo)代碼插入。所以,宏指令不能節(jié)省目標(biāo)程序所占的內(nèi)存單元
(2)若一個(gè)源程序中多次調(diào)用一個(gè)程序段,則可用子程序,也可以用宏指令來(lái)簡(jiǎn)化源程序。用子程序的辦法,匯編后產(chǎn)生的目標(biāo)代碼少,也即目標(biāo)程序占用的內(nèi)存少,節(jié)約了內(nèi)存空間。但是,子程序在執(zhí)行時(shí),每調(diào)用一次都要先保護(hù)斷點(diǎn),通常在程序中還要保護(hù)現(xiàn)場(chǎng);在返回時(shí)先要恢復(fù)現(xiàn)場(chǎng),然后恢復(fù)斷點(diǎn)(返回)
這些操作都額外增加了時(shí)間,因而執(zhí)行時(shí)間長(zhǎng),速度慢指令恰好相反,它的目標(biāo)程序長(zhǎng),占用的內(nèi)存的那元多;但是執(zhí)行時(shí)不需要保護(hù)斷點(diǎn),也不需要保護(hù)現(xiàn)場(chǎng)以及恢復(fù)、返回等這些額外的操作,因而執(zhí)行時(shí)間短、速度快













