8086汇编语言精华笔记总结~
目錄
- 第一章 匯編語言的基礎(chǔ)知識
- 1、計(jì)算機(jī)系統(tǒng)概述
- 硬件(Handware)
- 軟件(Software)
- 2、匯編語言介紹
- 3、數(shù)據(jù)表示
- 1. BCD碼
- 2. ASCII碼
- 3. 真值和機(jī)器數(shù)
- 4. 補(bǔ)碼
- 4、8086微處理器
- 1、通用寄存器
- 2、標(biāo)志寄存器FLAGS
- 3、指令指針I(yè)P
- 4、段寄存器
- 段超越前綴指令
- 計(jì)算機(jī)中信息的單位
- 數(shù)據(jù)的地址對齊
- 存儲器(men)的分段管理
- 5、8086尋址方式
- 1、指令的組成
- 2、8086的機(jī)器代碼格式
- 3、立即數(shù)尋址方式
- 4、存儲器尋址方式
- 1. 直接尋址方式
- 2. 寄存器間接尋址方式
- 3. 寄存器相對尋址方式
- 4. 基址變址尋址方式
- 5. 相對基址變址尋址方式
- 5、尋址方式的多種表示方式
- 6、各種操作數(shù)的表達(dá)
- 第二章 8086指令系統(tǒng)
- 1、數(shù)據(jù)傳送類指令
- 1. 傳送指令MOV
- 2. 交換指令XCHG
- 3. 換碼指令XLAT
- 4. 堆棧操作指令PUSH、POP
- 5. 標(biāo)志傳送指令
- 6. 標(biāo)志位操作指令
- 7、地址傳送指令
- 有效地址傳送指令 LEA
- 指針傳送指令 LDS 和 LES
- 2、算術(shù)運(yùn)算類指令
- 1、加法指令A(yù)DD、ADC、INC
- 2、減法指令SUB、SBB、DEC
- 3、求補(bǔ)指令 NEG
- 4、比較指令CMP
- 5、乘法指令MUL、IMUL
- 6、除法指令DIV、IDIV
- 7、符號擴(kuò)展指令CBW、CWD
- 8、十進(jìn)制調(diào)整指令
- 壓縮BCD碼調(diào)整
- 非壓縮BCD碼調(diào)整
- 3、位操作指令
- 1、邏輯或指令 AND
- 2、邏輯與指令 OR
- 3、邏輯異或指令XOR
- 4、邏輯非指令 NOT
- 5、測試指令 TEST
- 6、移位指令(shift)
- 7、循環(huán)移位指令(rotate)
- 4、控制轉(zhuǎn)移類指令
- 1、無條件轉(zhuǎn)移指令 JMP
- 2、條件轉(zhuǎn)移指令 JCC
- 3、循環(huán)指令(loop)
- 4、子程序指令
- 5、中斷指令
- 5、處理機(jī)控制類指令
- 1、空操作指令 NOP
- 2、段超越前綴指令
- 3、封鎖前綴指令 LOCK
- 4、暫停指令 HLT
- 5、交權(quán)指令 ESC
- 6、等待指令
- 第三章 匯編語言程序格式
- 1、匯編語言程序的開發(fā)
- 1、匯編語言程序設(shè)計(jì)的語句格式
- 2、匯編語言的程序格式
- 3、匯編語言的開發(fā)過程
- 4、DOS系統(tǒng)功能調(diào)用
- 功能調(diào)用的步驟
- 輸入輸出類調(diào)用
- 1、字符輸出:
- 2、字符串輸出:
- 3、字符輸入:
- 4、字符串輸入:
- 5、按鍵判斷:
- 2、參量、變量和符號
- 1、參數(shù)
- 1. 常數(shù)
- 2. 數(shù)值表達(dá)式
- 3. 地址型參數(shù)
- 2、變量定義偽指令
- 1. 變量名
- 2. 位指令助記符
- 3. 初值表
- 3、變量和標(biāo)號的屬性
- 3、程序段的定義和屬性
- exe程序
- com程序
- 1、簡化段定義偽指令合集
- .MODEL存儲模型位指令
- 簡化段定義偽指令
- .STARTUP 程序開始偽指令
- EXIT [返回參數(shù)] 程序終止偽指令
- END [標(biāo)號] 匯編結(jié)束偽指令
- 2、com程序的編寫
- 3、完整段定義偽指令
- 完整段定義位指令
- 指定段寄存器偽指令
- 段組偽指令
- 段順序偽指令
- 4、簡化段定義格式的段屬性
- 第四章 基本匯編語言程序設(shè)計(jì)
- 1、順序程序設(shè)計(jì)
- 2、分支程序設(shè)計(jì)
- 1、單分支程序設(shè)計(jì)
- 2、雙分支程序設(shè)計(jì)
- 3、多分支程序設(shè)計(jì)
- 3、循環(huán)程序設(shè)計(jì)
- 1、冒泡法
- 2、串操作類指令
- 4、 子程序設(shè)計(jì)
- 1、過程定義位指令
- 2、子程序的參數(shù)傳遞
- 3、子程序的嵌套
- 4、子程序的遞歸
- 5、子程序的重入
- 第五章 高級匯編語言程序設(shè)計(jì)
- 1、高級語言特性
- 1、條件控制偽指令
- 2、循環(huán)控制偽指令
- 3、過程聲明和過程調(diào)用偽指令
- 2、宏結(jié)構(gòu)程序設(shè)計(jì)
- 1、宏匯編
- a. 宏
- b. 宏指令
- c. 宏展開
- 宏的參數(shù)
- 宏操作符
- 與宏有關(guān)的偽指令
- 宏匯編與子程序的比較
- 2、重復(fù)匯編
- 1. 按參數(shù)值重復(fù)
- 2. 按參數(shù)個(gè)數(shù)重復(fù)
- 3. 按參數(shù)字符個(gè)數(shù)重復(fù)
- 3、條件匯編
- 宏結(jié)構(gòu)的作用
- 3、模塊化程序設(shè)計(jì)
- 1. 源程序文件的包含
- 2. 目標(biāo)代碼文件的連接
- 3. 子程序庫的調(diào)入
- 4、輸入輸出程序設(shè)計(jì)
- 1、 輸入輸出指令
- a. 輸入指令I(lǐng)N
- b. 輸出指令OUT
- 2、程序直接控制輸入輸出
- 3、程序查詢輸入輸出
- 4、中斷服務(wù)程序
- 內(nèi)部中斷服務(wù)程序
- 駐留中斷服務(wù)程序
- 外部可屏蔽中斷服務(wù)程序
第一章 匯編語言的基礎(chǔ)知識
1、計(jì)算機(jī)系統(tǒng)概述
硬件(Handware)
- 中央處理器CPU
- 運(yùn)算器,控制器,寄存器
- 存儲區(qū)
- 主存儲器:RAM、ROM
- 輔助存儲器:硬盤,光盤,U盤
- 外部設(shè)備
- 輸入設(shè)備和輸出設(shè)備
軟件(Software)
- 系統(tǒng)軟件(eg:操作系統(tǒng))
- 應(yīng)用軟件
其中我們程序員最關(guān)心的有三個(gè)
- 寄存器(Register)
- CPU內(nèi)部的高速存儲單元
- 為CPU提供
數(shù)據(jù)和地址信息
- 存儲器地址(Address)
- 由大量存儲單元組成,用
編號區(qū)分每個(gè)存儲單元 - 存儲器的
地址=存儲器中存儲單元的編號 - 每個(gè)存儲單元存放
一個(gè)字節(jié)的數(shù)據(jù)(1Byte=8bit) - 地址采用
十六進(jìn)制表達(dá)- Inter8086有1MB的存儲器容量(1MB=210KB=220B)
- 存儲器地址表示為:00000H~FFFFFH
- 由大量存儲單元組成,用
- 端口(Port)
- 是
I/O地址的別稱 - I/O接口電路由
接口寄存器組成,用編號區(qū)分各寄存器 - I/O
地址=接口電路中寄存器的編號 - 端口采用
十六進(jìn)制表達(dá)- Intel 8086支持64K個(gè)8位端口
- I/O地址可以表示為:0000H~FFFFH
- 是
2、匯編語言介紹
以
助記符形式表示計(jì)算機(jī)指令,匯編格式指令以及使用它們編寫程序的規(guī)則就形成匯編語言
- **匯編語言程序:**用匯編語言書寫的程序
- **匯編程序:**將匯編語言程序
匯編成機(jī)器代碼目標(biāo)模塊的程序 匯編語言程序和匯編程序是兩個(gè)不同的概念
3、數(shù)據(jù)表示
1. BCD碼
壓縮BCD碼:一個(gè)字節(jié)表達(dá)兩位BCD碼非壓縮BCD碼:一個(gè)字節(jié)表達(dá)一位BCD碼(低4位表達(dá)數(shù)值,高4位常設(shè)置為0)
2. ASCII碼
標(biāo)準(zhǔn)ASCII碼用7位二進(jìn)制編碼,有128個(gè)
不可顯示的控制字符:
- 前32個(gè)和最后一個(gè)編碼
回車CR:0DH換行LF:0AH響鈴BEL:07H
可顯示和打印的字符:20H開始的95個(gè)編碼
-
數(shù)碼
0~9:30H~39H -
大寫字母
A~Z:41H~5AH -
小寫字母
a~z:61H~7AH -
空格:20H -
擴(kuò)展ASCII碼:最高D7位為1,表達(dá)
制表符
3. 真值和機(jī)器數(shù)
**真值:**現(xiàn)實(shí)中真實(shí)的數(shù)值
**機(jī)器數(shù):**計(jì)算機(jī)中用0和1數(shù)碼組合表達(dá)的數(shù)
**定點(diǎn)數(shù):**固定小數(shù)點(diǎn)的位置表達(dá)數(shù)值的機(jī)器數(shù)
- 定點(diǎn)整數(shù):將小數(shù)點(diǎn)固定在機(jī)器數(shù)的最右側(cè)表達(dá)的整數(shù)
- 定點(diǎn)小數(shù):將小數(shù)點(diǎn)固定在機(jī)器數(shù)的最左側(cè)表達(dá)的小數(shù)
浮點(diǎn)數(shù):小數(shù)點(diǎn)浮動表達(dá)的實(shí)數(shù)
無符號數(shù):只表達(dá)0和正整數(shù)的定點(diǎn)整數(shù)
有符號數(shù):表達(dá)負(fù)整數(shù)、0和正整數(shù)的定點(diǎn)整數(shù)
- 符號位需要占用一個(gè)位
- 常用機(jī)器數(shù)的最高位,0表示正數(shù)、1表示負(fù)數(shù)
4. 補(bǔ)碼
有符號數(shù)在計(jì)算機(jī)中默認(rèn)采用了補(bǔ)碼- **最高位表示符號:**正數(shù)用0,負(fù)數(shù)用1
- **正數(shù)補(bǔ)碼:**直接表示數(shù)值大小(同無符號數(shù))
- **負(fù)數(shù)補(bǔ)碼:**將對應(yīng)正數(shù)補(bǔ)碼取反加1
4、8086微處理器
微處理器是微機(jī)的硬件核心,主要包含指令執(zhí)行的運(yùn)算和控制部件,還有多種寄存器
8086內(nèi)部結(jié)構(gòu)有兩個(gè)功能模塊,完成一條指令的取指和執(zhí)行功能
- 總線接口單元
BIU:負(fù)責(zé)讀取指令和操作數(shù) - 執(zhí)行單元
EU**:**負(fù)責(zé)指令譯碼和執(zhí)行
8086CPU所有寄存器都是16位的,都可以存放兩個(gè)字節(jié),可存儲的數(shù)據(jù)的最大值為2^16-1
1、通用寄存器
16位通用寄存器:AX BX CX DX SI DI BP SP8 位通用寄存器:AH BH CH DH AL BL CL DL
數(shù)據(jù)寄存器: 用來存放計(jì)算的結(jié)果和操作數(shù),也可存放地址
| AX | 累加器,使用頻度最高,用于算術(shù)、邏輯運(yùn)算以及與外設(shè)傳送信息等; |
|---|---|
| BX | 基址寄存器,常用做存放存儲器地址**;** |
| CX | 計(jì)數(shù)器,作為循環(huán)和串操作等指令中的隱含計(jì)數(shù)器; |
| DX | 數(shù)據(jù)寄存器,常用來存放雙字長數(shù)據(jù)的高16位,或存放外設(shè)端口地址。 |
**變址寄存器:**用于存儲器尋址時(shí)提供地址(在串操作指令中有特殊用法)
| SI | 是源變址寄存器 |
|---|---|
| DI | 是目的變址寄存器 |
**指針寄存器:**用于尋址內(nèi)存堆棧內(nèi)的數(shù)據(jù)(與SS堆棧段寄存器聯(lián)合確定堆棧段中存儲單元地址)
| SP | 為堆棧指針寄存器,指示棧頂?shù)钠频刂?#xff0c;不能再用于其他目的,具有專用目的 |
|---|---|
| BP | 為基址指針寄存器,表示數(shù)據(jù)在堆棧段中的基地址 |
2、標(biāo)志寄存器FLAGS
用于反映指令
執(zhí)行結(jié)果或者控制指令執(zhí)行形式
-
狀態(tài)標(biāo)志:記錄程序執(zhí)行結(jié)果的狀態(tài)信息CF(進(jìn)位標(biāo)志):運(yùn)算結(jié)果
最高位有進(jìn)位(加法)或借位(減法),CF=1,針對無符號數(shù)AF(輔助進(jìn)位標(biāo)志):運(yùn)算時(shí)
D3位(低半字節(jié))有進(jìn)位或者借位,AF=1ZF(零位標(biāo)志):運(yùn)算
結(jié)果為0,則ZF=1SF(符號標(biāo)志):運(yùn)算結(jié)果
最高位為1,SF=1PF(奇偶標(biāo)志):運(yùn)算結(jié)果中
低八位中1的個(gè)數(shù)為0/偶數(shù)時(shí),PF=1OF(溢出標(biāo)志):運(yùn)算結(jié)果
超出范圍(例如8位表達(dá)的范圍是+127~-128)則產(chǎn)生溢出,ZF=1,針對有符號數(shù) -
控制標(biāo)志:可根據(jù)需要設(shè)置,控制指令執(zhí)行方式DF:DF置0,則串操作控制處理方向,從帶有最低地址的第一個(gè)元素逐個(gè)處理,否則,從高向低
IF:IF=1,CPU允許中斷,IF=0,則CPU關(guān)閉中斷
TF:TF=1,機(jī)器進(jìn)入單步工作方式,每條機(jī)器指令執(zhí)行后,顯示結(jié)果及寄存器狀態(tài),若TF=0,則機(jī)器處在連續(xù)工作方式。此標(biāo)志為調(diào)試機(jī)器或調(diào)試程序發(fā)現(xiàn)故障而設(shè)置。
3、指令指針I(yè)P
- 指示代碼段中指令的
偏移地址,通過CS:IP指向下一條指令的物理地址 - 是一個(gè)
專用寄存器
4、段寄存器
8086有四個(gè)
段寄存器,每個(gè)段寄存器確定了一個(gè)邏輯段的起始地址
| CS(Code Segment) | 指明代碼段的起始地址(CS:IP指向下一條要執(zhí)行的指令) |
|---|---|
| SS(Stack Segment) | 指明堆棧段的b起始地址(SS:SP操作堆棧頂?shù)臄?shù)據(jù)) |
| DS(Data Segment**)** | 指明數(shù)據(jù)段的起始地址(DS:EA存取數(shù)據(jù)段中的數(shù)據(jù)) |
| ES(Extra Segment) | 指明附加段(附加數(shù)據(jù)段)的起始地址(ES:EA存取附加段中的數(shù)據(jù)) |
段超越前綴指令
- 默認(rèn)的數(shù)據(jù)訪問在
DS段 - 默認(rèn)的情況允許改變,需要使用
段超越前綴指令
| CS: | ;代碼段超越,使用代碼段的數(shù)據(jù) |
|---|---|
| SS: | ;堆棧段超越,使用堆棧段的數(shù)據(jù) |
| DS: | ;數(shù)據(jù)段超越**,**使用數(shù)據(jù)段的數(shù)據(jù) |
| ES: | ;附加段超越,使用附加段的數(shù)據(jù) |
計(jì)算機(jī)中信息的單位
| 二進(jìn)制位Bit | 存儲一位二進(jìn)制數(shù):0或1 |
|---|---|
| 字節(jié)Byte | 8個(gè)二進(jìn)制位,D7~D0 |
| 字Word | 16位,2個(gè)字節(jié),D15~D0 |
| 雙字Dword | 32位,4個(gè)字節(jié),D31~D0 |
- 最低有效位LSB:數(shù)據(jù)的最低位,D0位
- 最高有效位MSB**:**數(shù)據(jù)的最高位,對應(yīng)字節(jié)、字、雙字分別指D7、D15、D31位
數(shù)據(jù)的地址對齊
- 字單元在偶地址(xxx0B)、雙字單元在模4地址(xx00B)
存儲器(men)的分段管理
-
8086CPU有
20根地址線- 最大尋址空間為2^20=1MB
- 物理尋址范圍從00000H~FFFFFH
-
8086CPU將
1MB的空間分成許多邏輯段,各個(gè)段之間可以重疊- 每個(gè)段的最大限制為
2^16=64KB - 段地址低四位為0000B
- 每個(gè)段的最大限制為
-
這樣,每個(gè)存儲單元除了唯一的一個(gè)物理地址外,還有多個(gè)邏輯地址
-
邏輯地址= 段基地址:段內(nèi)偏移地址- 邏輯地址是16位的,因此范屬圍是2的16次方,即
64K
- 邏輯地址是16位的,因此范屬圍是2的16次方,即
-
物理地址= 段地址 * 16 (二進(jìn)制數(shù)據(jù)左移四位,十六進(jìn)制左移一位) + 偏移地址- 物理地址是20位的,因此范圍是2的20次方,即
1M
- 物理地址是20位的,因此范圍是2的20次方,即
5、8086尋址方式
1、指令的組成
指令由
操作碼和操作數(shù)兩部分組成;
指令的助記符格式:
操作碼 操作數(shù)1,操作數(shù)2 ;注釋
- 有些指令不需要操作數(shù),通常的指令都有一個(gè)或兩個(gè)操作數(shù),個(gè)別指令有3個(gè)甚至4個(gè)操作數(shù)
2、8086的機(jī)器代碼格式
示例一:
示例二:
示例三:
3、立即數(shù)尋址方式
-
直接存放在機(jī)器代碼中,緊跟在操作碼之后的操作數(shù)為立即數(shù)(imm)
- 8位數(shù)值
i8(00F~FFH) - 16位數(shù)值
i16(0000H~FFFFH)
- 8位數(shù)值
-
立即數(shù)常用來給寄存器賦值
MOV AL,05H ;AL←05H MOV AX,0102H ;AX←0102H
4、存儲器尋址方式
-
操作數(shù)存放在cpu的內(nèi)部寄存器reg中8位寄存器 r8AH、AL、BH、BL、CH、CL、DH、DL 16位寄存器 r16AX、BX、CX、DX、SI、DI、BP、SP 4個(gè)段寄存器 segCS、DS、SS、ES -
指令中給出操作數(shù)的
主存地址信息
多種存儲器尋址方式:
1. 直接尋址方式
有效地址直接在指令中給出- 默認(rèn)
段地址在DS寄存器,可用段超越前綴改變
MOV AX,[2000H] ;AX←DS:[2000H] 指令代碼:A1 00 20
MOV AX,ES:[2000H] ;AX←ES:[2000H] 指令代碼:26 A1 00 20
2. 寄存器間接尋址方式
有效地址放在BX(基址寄存器)或變址寄存器(SI,DI)中- 默認(rèn)
段地址在DS寄存器,可用段超越前綴改變
MOV AX,[SI] ;AX←DS:[SI]
3. 寄存器相對尋址方式
有效地址是寄存器內(nèi)容(BX/BP/SI/DI)和有符號8位或16位位移量之和
有效地址=BX/BP/SI/DI+8/16位位移量
段地址對應(yīng)BX/SI/DI寄存器默認(rèn)在DS,對應(yīng)BP寄存器默認(rèn)在SS;可用段超越前綴改變
MOV AX,[DI+06H] ;AX←DS:[DI+06H]
MOV AX,[BP+06H] ;AX←SS:[BP+06H]
4. 基址變址尋址方式
有效地址是基址寄存器(BX)/指針寄存器(BP)和變址寄存器(SI/DI)之和
有效地址=BX/BP+SI/DI
段地址對應(yīng)BX基址寄存器默認(rèn)是DS,對應(yīng)BP指針寄存器默認(rèn)是SS;可用段超越前綴改變
MOV AX,[BX+SI] ;AX←DS:[BX+SI]
MOV AX,[BP+DI] ;AX←SS:[BP+DI]
MOV AX,DS:[BP+DI] ;AX←DS:[BP+DI]
5. 相對基址變址尋址方式
有效地址是基址寄存器(BX)/指針寄存器(BP)和變址寄存器(SI/DI)和一個(gè)有符號8位或16位位移量之和
有效地址=BX/BP+SI/DI+8/16位位移量
段地址對應(yīng)BX基址寄存器默認(rèn)是DS,對應(yīng)BP指針寄存器默認(rèn)是SS;可用段超越前綴改變
MOV AX,[BX+SI+06H] ;AX←DS:[BX+SI+06H]
5、尋址方式的多種表示方式
-
位移量可用符號表示:
MOV AX,[SI+COUNT] ;COUNT是事先定義的變量或常量(就是數(shù)值) MOV AX,[BX+SI+WNUM] ;WNUM是變量或常量 -
同一尋址方式可以寫成不同的形式:
MOV AX,[BX][SI] ;MOV AX,[BX+SI] MOV AX,COUNT[SI] ;MOV AX,[SI+COUNT] MOV AX,WNUM[BX][SI] ;等同于 MOV AX,WNUM[BX+SI];等同于 MOV AX,[BX+SI+WNUM]
6、各種操作數(shù)的表達(dá)
-
寄存器操作數(shù)的表達(dá)
r8(任意一個(gè)8位通用寄存器) AH AL BH BL CH CL DH DL r16(任意一個(gè)16位通用寄存器) AX BX CX DX SI DI BP SP reg 代表r8或r16 seg 段寄存器CS DS ES SS -
存儲器操作數(shù)的表達(dá)
m8 一個(gè)8位存儲器操作數(shù)單元(所有主存尋址方式) m16 一個(gè)16位存儲器操作數(shù)單元(所有主存尋址方式) mem 代表m8或m16 -
立即數(shù)的表達(dá)
i8 一個(gè)8位立即數(shù) i16 一個(gè)16位立即數(shù) imm 代表i8或i16 dest 目的操作數(shù) src 源操作數(shù)
第二章 8086指令系統(tǒng)
1、數(shù)據(jù)傳送類指令
1. 傳送指令MOV
把一個(gè)字節(jié)或字的操作數(shù)從源地址傳送至目的地址
;reg:通用寄存器
;mem:存儲器
;imm:立即數(shù)
;seg:段寄存器
MOV reg/mem,imm
MOV reg/mem/seg,reg
MOV reg/seg,mem
MOV reg/mem,seg
注意:
-
兩個(gè)操作數(shù)類型一致(對于存儲器單元和立即數(shù)同時(shí)作為操作數(shù)的情況,需要顯示聲明;
byte ptr為字節(jié)類型,word ptr為字類型)mov byte ptr [si],0ah ;byte ptr 說明是字節(jié)操作 mov word ptr [si+2],0bh ;word ptr 說明是字操作 -
兩個(gè)操作數(shù)不能都是存儲器(要實(shí)現(xiàn)這種操作,通過寄存器實(shí)現(xiàn))
mov ax,buffer1 ;ax←buffer1(將buffer1內(nèi)容送ax) mov buffer2,ax ;buffer2←ax -
段寄存器的操作有一些限制
-
不允許立即數(shù)傳給段寄存器
MOV DS,100H ;非法指令:立即數(shù)不能傳送段寄存器 -
不允許改變CS(代碼段)的值
MOV CS,[SI] ;不允許使用的指令 -
不允許段寄存器之間的直接數(shù)據(jù)傳送
MOV DS,ES ;非法指令:不允許段寄存器間傳送
-
2. 交換指令XCHG
將兩個(gè)地方的數(shù)據(jù)進(jìn)行交換
- 寄存器與寄存器之間對換數(shù)據(jù)
- 寄存器與存儲器之間對換數(shù)據(jù)
- 不能在存儲器與存儲器之間對換數(shù)據(jù)
XCHG reg,reg/mem ;reg<->reg/mem
3. 換碼指令XLAT
將BX指定的緩沖區(qū)中、AL指定的位移處的一個(gè)字節(jié)數(shù)據(jù)取出賦給AL
XLAT ;al←ds:[bx+al]
示例:
mov bx,100h
mov al,03h
Xlat
;換碼指令沒有顯式的操作數(shù),但使用了BX和AL;
;因?yàn)閾Q碼指令使用了隱含尋址方式——采用默認(rèn)操作數(shù)
4. 堆棧操作指令PUSH、POP
PUSH:
PUSH r16/m16/seg ;SP<SP-2 SS:[SP]←r16/m16/seg
POP:
POP r16/m16/seg ;r16/m16/seg←SS:[SP] SP←SP+2
-
堆棧的操作單位是
字,2個(gè)字節(jié) -
進(jìn)展和出棧時(shí),都是低地址字節(jié)送低字節(jié),高地址字節(jié)送高字節(jié)(
小端對齊) -
堆棧操作遵循
先進(jìn)后出原則,但可用存儲器尋址方式隨機(jī)存取數(shù)據(jù) -
常見作用:
-
臨時(shí)存放數(shù)據(jù)
-
傳遞參數(shù)
-
保存和恢復(fù)寄存器
push ax ;進(jìn)入子程序后 push bx push ds ... pop ds ;返回主程序前 pop bx pop ax
-
5. 標(biāo)志傳送指令
用來傳送標(biāo)志寄存器FLAGS的內(nèi)容
低八位傳送:LAHF 和 SAHF16位傳送:PUSHF 和 POPF
LAHF
AH <- FLAGS的低字節(jié)
- SF/ZF/AF/PF/CF狀態(tài)標(biāo)志位分別進(jìn)入
AH的第7/6/4/2/0位,而AH的5/3/1位任意
SAHF
FLAGS的低字節(jié) <- AH
- 用
AH的第7/6/4/2/0位響應(yīng)設(shè)置SF/ZF/AF/PF/CF標(biāo)志位
PUSHF
- 保存所有標(biāo)志到堆棧
POPF
- 將堆棧內(nèi)容取出到標(biāo)志寄存器
6. 標(biāo)志位操作指令
-
標(biāo)志位操作指令直接對
CF、DF、IF標(biāo)志進(jìn)行復(fù) 位或置位,常用于特定的情況 -
用于任意設(shè)置進(jìn)位標(biāo)志
CLC ;復(fù)位進(jìn)位標(biāo)志:CF←0 STC ;置位進(jìn)位標(biāo)志:CF←1 CMC ;求反進(jìn)位標(biāo)志:CF←~CF -
串操作指令中,需要使用
CLD ;復(fù)位方向標(biāo)志:DF←0 STD ;置位方向標(biāo)志:DF←1 -
在編寫中斷服務(wù)程序時(shí),需要控制可屏蔽中斷的允許和禁止
CLI ;復(fù)位中斷標(biāo)志:IF←0 STI ;置位中斷標(biāo)志:IF←1
7、地址傳送指令
將存儲器單元的
邏輯地址送至指定的寄存器
有效地址傳送指令 LEA
- 將存儲器操作數(shù)的有效地址傳送到指定的16位寄存器中
LEA r16,mem ;r16←mem的有效地址EA
- 示例:
mov bx,0400h
mov si,3ch
lea bx,[bx+si+0f62h] ;BX=0400h+003ch+0f62h=139EH
- 獲得主存單元的
有效地址;不是物理地址,也不是該單元的內(nèi)容 - 可以實(shí)現(xiàn)計(jì)算功能
指針傳送指令 LDS 和 LES
- LDS指令將主存中mem指定的字送至
r16,并將mem的下一字送至DS寄存器
LDS r16,mem ;r16←mem DS←mem+2
- LES指令將主存中mem指定的字送至
r16,并將mem的下一字送至ES寄存器
LES r16,mem ;r16←mem ES←mem+2
- 示例:
mov word ptr [3060h],0100h
mov word ptr [3062h],1450h
les di,[3060h] ;es=1450h,di=0100h
lds si,[3060h] ;ds=1450h,si=0100h
mem指定主存的連續(xù)4個(gè)字節(jié)作為邏輯地址(32位的地址指針),送入DS:r16或ES:r16
2、算術(shù)運(yùn)算類指令
1、加法指令A(yù)DD、ADC、INC
- ADD:將源與目的操作數(shù)相加,結(jié)果送到目的操作數(shù)
ADD reg,imm/reg/mem ; reg ← reg+imm/reg/mem
ADD mem,imm/reg ; mem ← mem+imm/reg
- ADC:將源與目的操作數(shù)相加,再加上進(jìn)位
CF標(biāo)志,結(jié)果送到目的操作數(shù)
ADC reg,imm/reg/mem ; reg ← reg+imm/reg/mem+CF
ADC mem,imm/reg ; mem ← mem+imm/reg+CF
- INC:對操作數(shù)
加1(不影響CF,按定義設(shè)置其他狀態(tài)標(biāo)志)
INC reg/mem ; reg/mem ← reg/mem+1
2、減法指令SUB、SBB、DEC
- SUB:將目的操作數(shù)減去源操作數(shù),結(jié)果送到目的操作數(shù)(按照定義相應(yīng)設(shè)置狀態(tài)標(biāo)志)
SUB reg,imm/reg/mem ; reg ← reg-imm/reg/mem
SUB mem,imm/reg ; mem ← mem-imm/reg
- SBB:將目的操作數(shù)減去源操作數(shù),再減去
借位CF(進(jìn)位),結(jié)果送到目的操作數(shù)(按照定義相應(yīng)設(shè)置狀態(tài)標(biāo)志)
SBB reg,imm/reg/mem ; reg ← reg-imm/reg/mem-CF
SBB mem,imm/reg ; mem ← mem-imm/reg-CF
- DEC:對操作數(shù)
減1(不影響CF,按定義設(shè)置其他狀態(tài)標(biāo)志)
DEC reg/mem ; reg/mem ← reg/mem-1
3、求補(bǔ)指令 NEG
用零減去操作數(shù),然后結(jié)果返回操作數(shù)求補(bǔ)運(yùn)算也可以表達(dá)成:`將操作數(shù)按位取反后加1`
NEG reg/mem ; reg/mem ← 0-reg/mem
4、比較指令CMP
將目的操作數(shù)減去源操作數(shù),按照定義相應(yīng)設(shè)置狀態(tài)標(biāo)志
執(zhí)行的功能與SUB指令相同,但結(jié)果不回送目的操作數(shù)
CMP reg,imm/reg/mem ; reg-imm/reg/mem
CMP mem,imm/reg ; mem-imm/reg
5、乘法指令MUL、IMUL
- MUL:
無符號乘法
MUL r8/m8 ;AX ← AL*r8/m8
MUL r16/m16 ;DX.AX ← AX*r16/m16
- IMUL:
有符號乘法
IMUL r8/m8 ;AX ← AL*r8/m8
IMUL r16/m16 ;DX.AX ← AX*r16/m16
-
乘法指令對標(biāo)志的影響
MUL指令 若乘積的高一半(AH或DX)為0,則OF=CF=0;否則OF=CF=1 IMUL指令 若乘積的高一半是低一半的符號擴(kuò)展,則OF=CF=0;否則均為1 -
乘法指令對其他狀態(tài)標(biāo)志沒有定義
6、除法指令DIV、IDIV
- DIV:無符號除法
MUL r8/m8 ;AL←AX÷r8/m8的商 AH←AX÷r8/m8的余數(shù)
MUL r16/m16 ;AX←DX.AX÷r16/m16的商 DX←DX.AX÷r16/m16的余數(shù)
- IDIV:有符號除法
IMUL r8/m8 ;AL←AX÷r8/m8的商 AH←AX÷r8/m8的余數(shù)
IMUL r16/m16 ;AX←DX.AX÷r16/m16的商 DX←DX.AX÷r16/m16的余數(shù)
- 除法指令對標(biāo)志沒有定義
- 除法指令會產(chǎn)生結(jié)果溢出
- 除法錯(cuò)中斷: 當(dāng)被除數(shù)遠(yuǎn)大于除數(shù)時(shí),所得的商就有可能超出它所能表達(dá)的范圍。如果存放商的寄存器AL/AX不能表達(dá),便產(chǎn)生溢出,8086CPU中就產(chǎn)生編號為0的內(nèi)部中斷
- 對DIV指令,除數(shù)為0,或者在字節(jié)除時(shí)商超過8位,或者在字除時(shí)商超過16位
- 對IDIV指令,除數(shù)為0,或者在字節(jié)除時(shí)商不在-128~127范圍內(nèi),或者在字除時(shí)商不在-32768~32767范圍內(nèi)
7、符號擴(kuò)展指令CBW、CWD
- 用一個(gè)操作數(shù)的符號位(即最高位)形成另一個(gè)操作數(shù),后一個(gè)操作數(shù)的各位是全0(正數(shù))或全1(負(fù)數(shù))
- 符號擴(kuò)展不改變數(shù)據(jù)大小
- 對于數(shù)據(jù)64H(表示數(shù)據(jù)100),其最高位D7為0,符號擴(kuò)展后高8位都是0,成0064H(仍表示數(shù)據(jù)100)
- 對于數(shù)據(jù)FF00H(表示有符號數(shù)-256),其最高位D15為1,符號擴(kuò)展后高16位都是1,成為FFFFFF00H(仍表示有符號數(shù)-256)
8、十進(jìn)制調(diào)整指令
壓縮BCD碼調(diào)整
-
加減調(diào)整
- 使用DAA或DAS指令前,應(yīng)先執(zhí)行以AL為目的操作數(shù)的加法或減法指令
- DAA和DAS指令對OF標(biāo)志無定義,按結(jié)果影響其他標(biāo)志
- 例如CF反映壓縮BCD碼相加或減的進(jìn)位或借位狀態(tài)
mov al,68h ;al=68h,壓縮BCD碼表示真值68
mov bl,28h ;bl=28h,壓縮BCD碼表示真值28
add al,bl ;二進(jìn)制加法:al=68h+28h=90h
daa ;十進(jìn)制調(diào)整:al=96h 實(shí)現(xiàn)壓縮BCD碼加法:68+28=96
mov al,68h ;al=68h,壓縮BCD碼表示真值68
mov bl,28h ;bl=28h,壓縮BCD碼表示真值28
sub al,bl ;二進(jìn)制減法:al=68h-28h=40h
das ;十進(jìn)制調(diào)整:al=40h 實(shí)現(xiàn)壓縮BCD碼減法:68-28=40
非壓縮BCD碼調(diào)整
-
加減調(diào)整
- 使用AAA或AAS指令前,應(yīng)先執(zhí)行以AL為目的操作數(shù)的加法或減法指令
- AAA和AAS指令在調(diào)整中產(chǎn)生了進(jìn)位或借位,則AH要加上進(jìn)位或減去借位,同時(shí)CF=AF=1,否則CF=AF=0;
- 對其他標(biāo)志無定義
mov ax,0608h ;ax=0608h,非壓縮BCD碼表示真值68
mov bl,09h ;bl=09h,非壓縮BCD碼表示真值9
add al,bl ;二進(jìn)制加法:al=08h+09h=11h
Aaa ;十進(jìn)制調(diào)整:ax=0707h 實(shí)現(xiàn)非壓縮BCD碼加法:68+9=77
mov ax,0608h ;ax=0608h,非壓縮BCD碼表示真值68
mov bl,09h ;bl=09h,非壓縮BCD碼表示真值9
sub al,bl ;二進(jìn)制減法:al=08h-09h=ffh
aas ;十進(jìn)制調(diào)整:ax=0509h 實(shí)現(xiàn)非壓縮BCD碼減法:68-9=59
- 乘除調(diào)整
-
AAM指令跟在字節(jié)乘MUL之后,將乘積調(diào)整為非壓縮BCD碼
-
AAD指令跟在字節(jié)除DIV之前,先將非壓縮BCD碼的被除數(shù)調(diào)整為二進(jìn)制數(shù)
-
AAM和AAD指令根據(jù)結(jié)果設(shè)置SF、ZF和PF,但對OF、CF和AF無定義
mov ax,0608h ;ax=0608h,非壓縮BCD碼表示真值68 mov bl,09h ;bl=09h,非壓縮BCD碼表示真值9 mul bl ;二進(jìn)制乘法:al=08h×09h=0048h aam ;十進(jìn)制調(diào)整:ax=0702h 實(shí)現(xiàn)非壓縮BCD碼乘法:8×9=72mov ax,0608h ;ax=0608h,非壓縮BCD碼表示真值68 mov bl,09h ;bl=09h,非壓縮BCD碼表示真值9 aam ;二進(jìn)制擴(kuò)展:ax=68=0044h div bl ;除法運(yùn)算:商al=07h,余數(shù)ah=05h;實(shí)現(xiàn)非壓縮BCD碼除法:68÷9=7(余5)
3、位操作指令
以二進(jìn)制位為基本單位進(jìn)行數(shù)據(jù)操作
1、邏輯或指令 AND
| AND reg,imm/reg/mem | ;reg←reg∧imm/reg/mem |
|---|---|
| AND mem,imm/reg | ;mem←mem∧imm/reg |
- AND指令設(shè)置CF = OF = 0,根據(jù)結(jié)果設(shè)置SF、ZF和PF狀態(tài),而對AF未定義
2、邏輯與指令 OR
| OR reg,imm/reg/mem | ;reg←reg∨imm/reg/mem |
|---|---|
| OR mem,imm/reg | ;mem←mem∨imm/reg |
- OR指令設(shè)置CF = OF = 0,根據(jù)結(jié)果設(shè)置SF、ZF和PF狀態(tài),而對AF未定義
3、邏輯異或指令XOR
- 異或不同為1,相同為0
| XOR reg,imm/reg/mem | ;reg←reg⊕imm/reg/mem |
|---|---|
| XOR mem,imm/reg | ;mem←mem⊕imm/reg |
- XOR指令設(shè)置CF = OF = 0,根據(jù)結(jié)果設(shè)置SF、ZF和PF狀態(tài),而對AF未定義
4、邏輯非指令 NOT
| NOT reg/mem | ;reg/mem←~reg/mem |
|---|---|
- NOT指令是一個(gè)單操作數(shù)指令,不影響標(biāo)志位
5、測試指令 TEST
- 對兩個(gè)操作數(shù)執(zhí)行邏輯與運(yùn)算,結(jié)果不送到目的操作數(shù)
| TEST reg,imm/reg/mem | ;reg∧imm/reg/mem |
|---|---|
| TEST mem,imm/reg | ;mem∧imm/reg |
- XOR指令設(shè)置CF = OF = 0,根據(jù)結(jié)果設(shè)置SF、ZF和PF狀態(tài),而對AF未定義
6、移位指令(shift)
- 將操作數(shù)移動一位或多位,分成邏輯移位和算術(shù)移位,分別具有左移或右移操作
| SHL reg/mem,1/CL | ;邏輯左移,最高位進(jìn)入CF,最低位補(bǔ)0 |
|---|---|
| SHR reg/mem,1/CL | ;邏輯右移,最低位進(jìn)入CF,最高位補(bǔ)0 |
- 邏輯左移一位相當(dāng)于無符號數(shù)乘以2,邏輯右移一位相當(dāng)于無符號數(shù)除以2
| SAL reg/mem,1/CL | ;算術(shù)左移,最高位進(jìn)入CF,最低位補(bǔ)0 |
|---|---|
| SAR reg/mem,1/CL | ;算術(shù)右移,最低位進(jìn)入CF,最高位不變 |
- 移位指令的第一個(gè)操作數(shù)是指定的被移位的操作數(shù),可以是寄存器或存儲單元
- 后一個(gè)操作數(shù)表示移位位數(shù),該操作數(shù)為1,表示移動一位;當(dāng)移位位數(shù)大于1時(shí),則用CL寄存器值表示,該操作數(shù)表達(dá)為CL
- 按照移入的位設(shè)置進(jìn)位標(biāo)志CF,根據(jù)移位后的結(jié)果影響SF、ZF、PF,而對AF未定義
- 對于OF,如果進(jìn)行一位移動,則按照操作數(shù)的最高符號位是否改變,相應(yīng)設(shè)置溢出標(biāo)志OF:如果移位前的操作數(shù)最高位與移位后操作數(shù)的最高位不同(有變化),則OF = 1;否則OF = 0。當(dāng)移位次數(shù)大于1時(shí),OF不確定
7、循環(huán)移位指令(rotate)
- 將操作數(shù)從一端移出的位返回到另一端形成循環(huán),分成不帶進(jìn)位和帶進(jìn)位,分別具有左移或右移操作
| ROL reg/mem,1/CL | ;不帶進(jìn)位循環(huán)左移 |
|---|---|
| ROR reg/mem,1/CL | ;不帶進(jìn)位循環(huán)右移 |
| RCL reg/mem,1/CL | ;帶進(jìn)位循環(huán)左移 |
| RCR reg/mem,1/CL | ;帶進(jìn)b位循環(huán)右移 |
- 按照指令功能設(shè)置進(jìn)位標(biāo)志CF,不影響SF、ZF、PF、AF
- 對于OF,如果進(jìn)行一位移動,則按照操作數(shù)的最高符號位是否改變,相應(yīng)設(shè)置溢出標(biāo)志OF:如果移位前的操作數(shù)最高位與移位后操作數(shù)的最高位不同(有變化),則OF = 1;否則OF = 0。當(dāng)移位次數(shù)大于1時(shí),OF不確定
4、控制轉(zhuǎn)移類指令
- 用于實(shí)現(xiàn)分支、循環(huán)、過程等程序結(jié)構(gòu)
- 通過改變IP(和CS)值,實(shí)現(xiàn)程序執(zhí)行順序的改變
1、無條件轉(zhuǎn)移指令 JMP
JMP label ;程序轉(zhuǎn)向label標(biāo)號指定的地址
- 執(zhí)行JMP,使程序轉(zhuǎn)到指定的目標(biāo)地址處,從目標(biāo)地址處開始執(zhí)行指令
- 操作數(shù)label是要轉(zhuǎn)移到的目標(biāo)地址(目的地址、轉(zhuǎn)移地址)
- 目標(biāo)地址的尋址方式
- 相對尋址方式:以當(dāng)前IP為基地址,加上位移量構(gòu)成目標(biāo)地址
- 直接尋址方式:轉(zhuǎn)移地址像立即數(shù)一樣,直接在指令的機(jī)器代碼中
- 間接尋址方式:轉(zhuǎn)移地址在寄存器或主存單元中
- 轉(zhuǎn)移方式
- 段內(nèi)轉(zhuǎn)移——近轉(zhuǎn)移(near)
- 在當(dāng)前代碼段64KB范圍內(nèi)轉(zhuǎn)移
- 不需要更改CS地址,只要改變IP偏移地址
- 段內(nèi)轉(zhuǎn)移——短轉(zhuǎn)移(short)
- 轉(zhuǎn)移范圍可以用一個(gè)字節(jié)表達(dá),在段內(nèi)-128~+127的范圍轉(zhuǎn)移
- 段間轉(zhuǎn)移——遠(yuǎn)轉(zhuǎn)移(far)
- 從當(dāng)前代碼段跳轉(zhuǎn)到另一個(gè)代碼段,可在1MB之內(nèi)
- 更改CS和IIP
- 目標(biāo)地址必須用一個(gè)32位數(shù)表達(dá),叫做32位遠(yuǎn)指針(邏輯地址)
- 段內(nèi)轉(zhuǎn)移——近轉(zhuǎn)移(near)
JMP指令分為四種類型
-
段內(nèi)轉(zhuǎn)移,相對尋址
- 位移量是緊接著JMP指令后的那條指令的偏移地址,到目標(biāo)指令的偏移地址的地址位移
- 當(dāng)向地址增大方向轉(zhuǎn)移時(shí),位移量為正;向地址減小方向轉(zhuǎn)移時(shí),位移量為負(fù)
JMP label ;IP←IP+位移量 -
段內(nèi)轉(zhuǎn)移,間接尋址
- 將一個(gè)16位寄存器或主存字單元內(nèi)容送入IP寄存器,作為新的指令指針,但不修改CS寄存器的內(nèi)容
JMP r16/m16 ;IP←r16/m16 -
段間轉(zhuǎn)移,直接尋址
- 將標(biāo)號所在段的段地址作為新的CS值,標(biāo)號在該段內(nèi)的偏移地址作為新的IP值;這樣,程序跳轉(zhuǎn)到新的代碼段執(zhí)行
JMP far ptr label ;IP←label的偏移地址 CS←label的段地址 -
段間轉(zhuǎn)移,間接尋址
- 用一個(gè)雙字存儲單元表示要跳轉(zhuǎn)的目標(biāo)地址。這個(gè)目標(biāo)地址存放在主存中連續(xù)的兩個(gè)字單元中的,低位字送IP寄存器,高位字送CS寄存器
JMP far ptr mem ;IP←[mem],CS←[mem+2]
2、條件轉(zhuǎn)移指令 JCC
JCC label ;條件滿足,發(fā)生轉(zhuǎn)移:IP←IP+8位位移量 條件不滿足,順序執(zhí)行
操作數(shù)label采用 相對尋址、短轉(zhuǎn)移 方式
- 表示Jcc指令后的那條指令的偏移地址,到目標(biāo)指令的偏移地址的地址位移
- 距當(dāng)前IP地址-128~+127個(gè)單元的范圍之內(nèi)
JCC指令不影響標(biāo)志,但要利用標(biāo)志,分為3種情況:
- 判斷單個(gè)標(biāo)志位狀態(tài)
- 比較無符號數(shù)大小
- 比較有符號數(shù)大小
轉(zhuǎn)移條件cc:單個(gè)標(biāo)志狀態(tài)
| JZ/JE | ZF=1 | Jump if Zero/Equal |
|---|---|---|
| JNZ/JNE | ZF=0 | Jump if Not Zero/Not Equal |
| JS | SF=1 | Jump if Sign |
| JNS | SF=0 | Jump if Not Sign |
| JP/JPE | PF=1 | Jump if Parity/Parity Even |
| JNP/JPO | PF=0 | Jump if Not Parity/Parity Odd |
| JO | OF=1 | Jump if Overflow |
| JNO | OF=0 | Jump if Not Overflow |
| JC | CF=1 | Jump if Carry |
| JNC | CF=0 | Jump if Not Carry |
轉(zhuǎn)移條件cc:兩數(shù)大小關(guān)系
| 無符號數(shù): | ------------------------- | -------------------------------------------- |
|---|---|---|
| JB/JNAE | CF=1 | Jump if Below/Not Above or Equal |
| JNB/JAE | CF=0 | Jump if Not Below/Above or Equal |
| JBE/JNA | CF=1或ZF=1 | Jump if Below/Not Above |
| JNBE/JA | CF=0且ZF=0 | Jump if Not Below or Equal/Above |
| 有符號數(shù): | ------------------------- | -------------------------------------------- |
| JL/JNGE | SF≠OF | Jump if Less/Not Greater or Equal |
| JNL/JGE | SF=OF | Jump if Not Less/Greater or Equal |
| JLE/JNG | ZF≠OF或ZF=1 | Jump if Less or Equal/Not Greater |
| JNLE/JG | SF=OF且ZF=0 | Jump if Not Less or Equal/Greater |
3、循環(huán)指令(loop)
- 操作數(shù)label采用 相對尋址、短轉(zhuǎn)移 方式
- 默認(rèn)利用CX計(jì)數(shù)器
| JCXZ label | ;CX=0,轉(zhuǎn)移到標(biāo)號label |
|---|---|
| LOOP label | ;CX←CX-1,CX≠0,循環(huán)到標(biāo)號label |
| LOOPZ label | ;CX←CX-1,CX≠0且ZF=1,循環(huán)到標(biāo)號label |
| LOOPNZ label | ;CX←CX-1,CX≠0且ZF=0,循環(huán)到標(biāo)號label |
4、子程序指令
- 子程序是完成特定功能的一段程序
- CALL指令調(diào)用子程序,RET指令返回主程序
子程序調(diào)用指令:
-
CALL指令有四種類型:
CALL label ;段內(nèi)調(diào)用、相對尋址 CALL r16/m16 ;段內(nèi)調(diào)用、間接尋址 CALL far ptr label ;段間調(diào)用、直接尋址 CALL far ptr mem ;段間調(diào)用、間接尋址 -
CALL指令需要保存返回地址
-
段內(nèi)調(diào)用——入棧偏移地址IP
-
SP←SP-2,SS:[SP]←IP -
段間調(diào)用——入棧偏移地址IP和段地址CS
-
SP←SP-2,SS:[SP]←IP SP←SP-2,SS:[SP]←CS
子程序返回指令:
- 根據(jù)段內(nèi)和段間、有無參數(shù),分成4種類型
| RET | ;無參數(shù)段內(nèi)返回 |
|---|---|
| RET i16 | ;有參數(shù)段內(nèi)返回 |
| RET | ;無參數(shù)段間返回 |
| RET i16 | ;有參數(shù)段間返回 |
-
需要彈出CALL指令壓入堆棧的返回地址
-
段內(nèi)返回——出棧偏移地址IP
IP←SS:[SP], SP←SP+2
- 段間返回——出棧偏移地址IP和段地址CS
IP←SS:[SP],SP←SP+2CS←SS:[SP],SP←SP+2
- 返回指令RET的參數(shù)
RET i16 ;有參數(shù)返回
-
RET指令可以帶有一個(gè)立即數(shù)i16,
則堆棧指針SP將增加,即 SP←SP+i16
-
這個(gè)特點(diǎn)使得程序可以方便地廢除若干執(zhí)行CALL指令以前入棧的參數(shù)
5、中斷指令
中斷(Interrupt )是又一種改變程序執(zhí)行順序的方法,具有多種類型
8086外部中斷:來自CPU之外的原因引起的中斷,可分為:
- 可屏蔽中斷:可由CPU的中斷允許標(biāo)志IF控制
- 非屏蔽中斷:不受CPU的中斷允許標(biāo)志IF控制
8086內(nèi)部中斷:CPU內(nèi)部執(zhí)行程序引起的中斷,可分成:
- 除法錯(cuò)中斷:執(zhí)行除法指令,結(jié)果溢出產(chǎn)生的 0號 中斷
- 指令中斷:執(zhí)行中斷調(diào)試指令 INT i8 產(chǎn)生的 i8號 中斷
- 斷點(diǎn)中斷:用于斷點(diǎn)調(diào)試(INT 3)的 3號 中斷
- 溢出中斷:執(zhí)行溢出中斷指令,OF=1產(chǎn)生的 4號 中斷
- 單步中斷:TF=1在每條指令執(zhí)行后產(chǎn)生的 1號 中斷
中斷指令I(lǐng)NT
| INT i8 | ;中斷調(diào)用指令:產(chǎn)生i8號中斷 |
|---|---|
| IRET | ;中斷返回指令:實(shí)現(xiàn)中斷返回 |
| INTO | ;溢出中斷指令;若溢出標(biāo)志OF=1,產(chǎn)生4號中斷;否則順序執(zhí)行 |
5、處理機(jī)控制類指令
1、空操作指令 NOP
-
不執(zhí)行任何操作,但占用一個(gè)字節(jié)存儲單元,空耗一個(gè)指令執(zhí)行周期
-
NOP常用于程序調(diào)試
- 在需要預(yù)留指令空間時(shí)用NOP填充
- 代碼空間多余時(shí)也可以用NOP填充
- 還可以用NOP實(shí)現(xiàn)軟件延時(shí)
-
事實(shí)上,NOP和 XCHG AX,AX 的指令代碼一樣,都是 90H
2、段超越前綴指令
- 在允許段超越的存儲器操作數(shù)之前,使用段超越前綴指令,將采用指定的段寄存器尋址操作數(shù)
| CS: | ;使用代碼段的數(shù)據(jù) |
|---|---|
| SS: | ;使用堆棧段的數(shù)據(jù) |
| DS: | ;使用數(shù)據(jù)段的數(shù)據(jù) |
| ES: | ;使用附加段的數(shù)據(jù) |
3、封鎖前綴指令 LOCK
LOCK ;封鎖總線
- 這是一個(gè)指令前綴,可以放在任何指令前
- 這個(gè)前綴使得在這個(gè)指令執(zhí)行時(shí)間內(nèi),8086 處理器的封鎖輸出引腳有效,即把總線封鎖,使別的控制器不能控制總線;直到該指令執(zhí)行完后,總線封鎖解除
4、暫停指令 HLT
HLT ;進(jìn)入暫停狀態(tài)
- 暫停指令使CPU進(jìn)入暫停狀態(tài),這時(shí)CPU不進(jìn)行任何操作。當(dāng)CPU發(fā)生復(fù)位或來自外部的中斷時(shí),CPU脫離暫停狀態(tài)
- HLT指令可用于程序中等待中斷。當(dāng)程序中必須等待中斷時(shí),可用HLT,而不必用軟件死循環(huán)。然后,中斷使CPU脫離暫停狀態(tài),返回執(zhí)行HLT的下一條指令
5、交權(quán)指令 ESC
ESC 6位立即數(shù),reg/mem ;把浮點(diǎn)指令交給浮點(diǎn)處理器執(zhí)行
- 浮點(diǎn)協(xié)處理器8087指令是與8086的整數(shù)指令組合在一起的,當(dāng)8086發(fā)現(xiàn)是一條浮點(diǎn)指令時(shí),就利用ESC指令將浮點(diǎn)指令交給8087執(zhí)行
6、等待指令
WAIT ;進(jìn)入等待狀態(tài)
- 8086利用WAIT指令和測試引腳實(shí)現(xiàn)與8087同步運(yùn)行
- 浮點(diǎn)指令經(jīng)由8086處理發(fā)往8087,并與8086本身的整數(shù)指令在同一個(gè)指令序列;而8087執(zhí)行浮點(diǎn)指令較慢,所以8086必須與8087保持同步
第三章 匯編語言程序格式
1、匯編語言程序的開發(fā)
編輯—匯編–連接–調(diào)試
1、匯編語言程序設(shè)計(jì)的語句格式
- 執(zhí)行性語句:由
硬指令構(gòu)成的語句,通常對應(yīng)一條機(jī)器指令,出現(xiàn)在程序的代碼段中
標(biāo)號: 硬指令助記符 操作數(shù),操作數(shù) ; 注釋
- 說明性語句:由
偽指令構(gòu)成的語句它通常指示匯編程序如何匯編源程序
名字 偽指令助記符 參數(shù),參數(shù).. ;注釋
-
標(biāo)號、名字與標(biāo)識符:
-
標(biāo)號:反映硬指令(邏輯地址)的標(biāo)識符,后加冒號分隔 -
名字:反映位指令(邏輯地址)和屬性的標(biāo)識符,后跟空格或制表符分隔,沒有冒號 -
標(biāo)識符:一般最多由31個(gè)字母、數(shù)字及規(guī)定的特殊符號(如、$、?、@)組成,不能以數(shù)字開頭。默認(rèn)情況下,匯編程序不區(qū)別標(biāo)識符中的字母大小寫- 一個(gè)程序中,每個(gè)標(biāo)識符的定義是唯一的,還不能是匯編語言采用的保留字
-
-
保留字:匯編程序已經(jīng)利用的標(biāo)識符
硬指令助記符 例如:MOV、ADD 偽指令助記符 例如:DB、EQU 操作符 例如:OFFSET、PTR 寄存器名 例如:AX、CS 預(yù)定義符號 例如:@data -
助記符
-
操作數(shù)與參數(shù):
- 處理器指令的操作數(shù)可以是立即數(shù)、寄存器和存儲單元
- 偽指令的參數(shù)可以是常數(shù)、變量名、表達(dá)式等,可以有多個(gè),參數(shù)之間用逗號分隔
-
注釋
-
分隔符:
- 語句的4個(gè)組成部分要用分隔符分開
- 標(biāo)號后用冒號,注釋前用分號
- 操作數(shù)之間和參數(shù)之間使用逗號分隔
- 其他部分通常采用空格或制表符
- 多個(gè)空格和制表符的作用與一個(gè)相同
- MASM支持續(xù)行符"\"
2、匯編語言的程序格式
- 完整的匯編程序由段組成,可以包含若干個(gè)代碼段、數(shù)據(jù)段、附加段、堆棧段,段與段之間的順序可以隨意排列
- 獨(dú)立運(yùn)行的程序必須包含一個(gè)代碼段,并指示程序執(zhí)行的起始點(diǎn),一個(gè)程序只有一個(gè)起始點(diǎn)
- 可執(zhí)行語句必須在一個(gè)代碼段中,說明性語句可位于任何一個(gè)段中
匯編源程序有兩種格式:
-
簡化段定義格式(MASM5.0開始支持)
;MASM 6.X支持 ;example.asm ;文件名.model small ;程序存儲模型.stack ;定義堆棧段.data ;定義數(shù)據(jù)段... ;在數(shù)據(jù)段定義數(shù)據(jù).code ;定義代碼段.startup ;程序起始點(diǎn),建立DS、SS... ;在代碼段填入指令序列.exit 0 ;程序結(jié)束點(diǎn),返回DOS... ;子程序代碼end ;匯編結(jié)束;MASM 5.X支持 ;example.asm ;文件名.model samll ;程序存儲模型.stack ;定義堆棧段.data ;定義數(shù)據(jù)段... ;在數(shù)據(jù)段定義數(shù)據(jù).code ;定義代碼段 start: move ax,@data move ds,ax ;這兩句指令等價(jià)于.startup... ;代碼段,填入指令序列move ax,4c00h int 21h ;這兩句指令等價(jià)于.exit 0... ;子程序代碼end start ;匯編結(jié)束 -
完整段定義格式(MASM5.0以前就具有)
;MASM 5.X支持 ;example.asm ;文件名 stack segment stack ;定義堆棧段dw 512 dup(?) ;堆棧段有512字(1024字節(jié))空間 stack ends ;堆棧段結(jié)束 data segment ;定義數(shù)據(jù)段... ;在數(shù)據(jù)段定義數(shù)據(jù) data ends ;數(shù)據(jù)段結(jié)束 code segment 'code' ;定義代碼段assume cs:code,ds:data,ss:stack start: move ax,data ;建立DS段地址move ds,ax... ;在代碼段填入指令序列move ax,4c00hint 21h ;利用功能調(diào)用返回DOS... ;子程序代碼 code ends ;代碼段結(jié)束end start ;匯編結(jié)束,同時(shí)指明程序起始點(diǎn)
3、匯編語言的開發(fā)過程
-
準(zhǔn)備工作
- 安裝開發(fā)軟件包
- 進(jìn)入操作系統(tǒng)(模擬DOS環(huán)境)
- 進(jìn)入MSAM開發(fā)目錄
-
源程序的
編輯- 以ASM為擴(kuò)展名
-
源程序的
匯編-
匯編是將程序翻譯成由機(jī)器代碼組成的目標(biāo)模塊文件的過程
-
MASM 6.X提供的匯編程序是ML.EXE
-
如果源程序中沒有語法錯(cuò)誤,MASM將自動生成一個(gè)目標(biāo)模塊文件(.obj);否則MASM將給出相應(yīng)的錯(cuò)誤信息
ML /c lt301.asm -
-
目標(biāo)模塊的
鏈接- 鏈接程序能把一個(gè)或多個(gè)目標(biāo)文件和庫文件合成一個(gè)可執(zhí)行文件(.EXE、.COM文件)
- 如果沒有錯(cuò)誤,則會生成一個(gè)可執(zhí)行文件(.EXE),否則將提示相應(yīng)的錯(cuò)誤信息
LINK lt301.obj
ML匯編程序可以自動調(diào)用LINK連接程序,實(shí)現(xiàn)匯編和連接的依次進(jìn)行
- 該命令除了產(chǎn)生模塊化文件.obj和可執(zhí)行文件.exe之外,還會產(chǎn)生列表文件.lst
- 列表文件是一種文本文件,含有源程序和目標(biāo)代碼
-
可執(zhí)行程序的調(diào)試
- 經(jīng)過匯編,連接生成的可執(zhí)行程序在操作系統(tǒng)下只要輸入文件名就可以運(yùn)行
lt301.exe- 操作系統(tǒng)裝載該文件進(jìn)入主存,并開始運(yùn)行
4、DOS系統(tǒng)功能調(diào)用
21H中斷是DOS給用戶用于調(diào)用系統(tǒng)功能的中斷,它有近百個(gè)功能,只要包括設(shè)備管理,目錄管理和文件管理這三個(gè)方面的功能ROM-BIOS也以中斷服務(wù)程序的形式,向程序員提供系統(tǒng)的基本輸入輸出程序
功能調(diào)用的步驟
- 在
AH寄存器設(shè)置系統(tǒng)功能的調(diào)用號 - 在指定寄存器中設(shè)置入口參數(shù)
- 執(zhí)行
INT 21H(或ROM-BIOS的中斷向量號)實(shí)現(xiàn)中斷服務(wù)程序的功能調(diào)用 - 根據(jù)出口參數(shù)分析功能調(diào)用執(zhí)行情況
輸入輸出類調(diào)用
1、字符輸出:
-
功能號:
AH=02H -
入口參數(shù):
DL=字符的ASCII碼 -
功能:在顯示器當(dāng)前光標(biāo)位置顯示給定的字符,光標(biāo)右移一個(gè)字符位置。
按Ctrl-Berak或Ctrl-C退出
2、字符串輸出:
- 功能號:
AH=09H - 入口參數(shù):
DS:DX=欲顯示字符串在主存中的首地址,字符串應(yīng)以$(24H)結(jié)束 - 功能:在顯示器輸出指定的字符串【可以輸出回車(0DH)和換行(0AH)字符產(chǎn)生回車和換行的作用】
3、字符輸入:
-
功能號:
AH=01H -
入口參數(shù):
AL=字符的ASCII碼- 功能:獲得按鍵的ASCII代碼值
【調(diào)用此功能時(shí),若無鍵按下,則會一致等待,直到按鍵后才讀取該鍵值】
4、字符串輸入:
-
功能號:
AH=0AH -
入口參數(shù):
DS:DX=緩沖區(qū)首地址 -
執(zhí)行該功能調(diào)用時(shí),用戶按鍵,最后用回車確認(rèn)
【該調(diào)用可以執(zhí)行全部標(biāo)準(zhǔn)鍵盤編輯命令;用戶按回車鍵結(jié)束輸入,如按Ctrl+Break或Ctrl+c則終止】
緩沖區(qū)的定義
示例:
5、按鍵判斷:
- 功能號:
AH=0BH - 出口參數(shù):
AL=0,當(dāng)前沒有按鍵;AL=FFH,當(dāng)前已經(jīng)按鍵 - 功能:僅判斷當(dāng)前是否有按下的鍵,設(shè)置AL后退出
2、參量、變量和符號
1、參數(shù)
- 參數(shù)是指令的操作對象,參數(shù)之間用
逗號分隔 - 參數(shù)可以沒有,可以有1、2或多個(gè)
- 參數(shù)有數(shù)值型,主要形式是常數(shù)和數(shù)值表達(dá)式
1. 常數(shù)
表達(dá)一個(gè)固定的數(shù)值
-
十進(jìn)制常數(shù):由0 ~ 9數(shù)字組成,以字母D或d結(jié)尾,缺省情況下,后綴D或d可以省略100 255D -
十六進(jìn)制常數(shù):由0~9、A~F組成,以字母H或h結(jié)尾以字母A~F開頭的十六進(jìn)制數(shù),前面要用0表達(dá),以避免與其他符號混淆64H 0FFh 0B800H -
二進(jìn)制常數(shù): 由0或1兩個(gè)數(shù)字組成,以字母B或b結(jié)尾01101100B -
八進(jìn)制常數(shù):用單引號或雙引號括起來的單個(gè)字符或多個(gè)字符,其數(shù)值是每個(gè)字符對應(yīng)的ASCII碼的值'd' = 64H 'AB'= 4142H 'Hello, Everybody !' -
符號常數(shù):利用一個(gè)標(biāo)識符表達(dá)的一個(gè)數(shù)值
MASM提供等價(jià)機(jī)制,用于常量定義;等價(jià)EQU偽指令符號名 EQU 數(shù)值表達(dá)式符號名 EQU <字符串>;等號=偽指令符號名 = 數(shù)值表達(dá)式
示例:
DosWriteChar equ 2
CarriageReturn = 13
CallDOS equ <int 21h>mov ah,2 ;mov ah,DosWriteChar
mov dl,13 ;mov dl,CarriageReturn
int 21h ;CallDOS
2. 數(shù)值表達(dá)式
指由運(yùn)算符連接的各種常數(shù)所構(gòu)成的表達(dá)式
算數(shù)運(yùn)算符:+ - * / MOD
mov ax,3*4+5 ;等價(jià)于 mov ax,17
;除加、減外,其他運(yùn)算符的參數(shù)必須是整數(shù)
邏輯運(yùn)算符:AND OR XOR NOT
or al,03h AND 45h ;等價(jià)于 or al,01h
-
移位運(yùn)算符:SHL SHR實(shí)現(xiàn)
邏輯左移、右移;移入低位高位都是0
mov al,0101b SHL (2*2) ;等價(jià)于 mov al,01010000b
關(guān)系運(yùn)算符:- EQ(等于) NE(不等于) GT(大于) LT(小于) GE(大于等于) LE(小于等于)
- 用于比較和測試符號數(shù)值
- MASM用
0FFFFH(補(bǔ)碼-1)表示條件為真 - MASM用
0000H表示條件為假
mov bx,((PORT LT 5)AND 20)OR((PORT GE 5)AND 30)
;當(dāng)PORT<5時(shí),匯編結(jié)果為mov bx,20
;否則,匯編結(jié)果為mov bx,30
-
高低分離符:- HIGH LOW HIGHWORD LOWWORD
;HIGH、LOW從一個(gè)字?jǐn)?shù)值或符號常量中得到高、低字節(jié) mov ah,HIGH 8765h ;等價(jià)于mov ah,87h;HIGHWORD、LOWWORD取一個(gè)符號常量(不能是其他常數(shù))的高字或低字部分 dd_value equ 0ffff1234h ;定義一個(gè)符號常量 mov ax,LOWWORD dd_value ;等價(jià)于mov ax,1234h
3. 地址型參數(shù)
- 主要形式:標(biāo)號和名字(變量名、段名、過程名等)
- 硬指令的操作數(shù)有存儲單元;存儲單元就應(yīng)該用地址型參數(shù)(存儲器操作數(shù))表達(dá)
2、變量定義偽指令
作用:為變量申請固定長度的存儲空間,并可同時(shí)將相應(yīng)的存儲單元初始化
格式:變量名 位指令助記符 初值表
1. 變量名
- 變量名為用戶自定義標(biāo)識符,表示初值表首元素的邏輯地址;用這個(gè)符號表示地址,常稱為符號地址
- 可以沒有變量名。此時(shí)匯編程序會直接為初值表分配空間,無符號地址
- 設(shè)置變量名是為了方便存取它指示的存儲單元
2. 位指令助記符
-
DB——定義字節(jié)偽指令- 用于分配一個(gè)或多個(gè)字節(jié)單元,并可以將它們初始化為指定值
- 初值表中每個(gè)數(shù)據(jù)一定是字節(jié)量(Byte),存放一個(gè)8位數(shù)據(jù)
- 可以是0~255的無符號數(shù)
- 或是-128~+127帶符號數(shù)
- 也可以是字符串常數(shù)
.data ;數(shù)據(jù)段 X db 'a',-5 db 2 dup(100),? Y db 'ABC' mov al,X ;此處X表示它的第1個(gè)數(shù)據(jù),故AL←'a' dec X+1 ;對X為始的第2個(gè)數(shù)據(jù)減1,故成為-6 mov Y,al ;現(xiàn)在Y這個(gè)字符串成為 'aBC'
-
DW——定義字偽指令- 用于分配一個(gè)或多個(gè)字單元,并可以將它們初始化為指定值
- 初值表中每個(gè)數(shù)據(jù)一定是字量(Word),一個(gè)字單元可用于存放任何16位數(shù)據(jù)
- 一個(gè)段地址
- 一個(gè)偏移地址
- 兩個(gè)字符
- 0~65535之間的無符號數(shù)
- -32768~+32767之間的帶符號數(shù)
.data ;數(shù)據(jù)段 count dw 8000h,?,'AB' maxint equ 64h number dw maxint array dw maxint dup(0)
-
DD——定義雙字偽指令- 用于分配一個(gè)或多個(gè)雙字單元,并可以將它們初始化為指定值
- 初值表中每個(gè)數(shù)據(jù)是一個(gè)32位的雙字量
- 可以是有符號或無符號的32位整數(shù)
- 也可以用來表達(dá)16位段地址(高位字)和16位的偏移地址(低位字)的遠(yuǎn)指針
vardd DD 0,?,12345678h farpoint DD 00400078h
DF——定義3字偽指令- 用于為一個(gè)或多個(gè)6字節(jié)變量分配空間及初始化
- 6字節(jié)常用在32位CPU中表示一個(gè)48位遠(yuǎn)指針(16位段選擇器:32位偏移地址)
- 用于為一個(gè)或多個(gè)6字節(jié)變量分配空間及初始化
DQ——定義4字偽指令- 用于為一個(gè)或多個(gè)8字節(jié)變量分配空間及初始化
- 8字節(jié)變量可以表達(dá)一個(gè)64位整數(shù)
- 用于為一個(gè)或多個(gè)8字節(jié)變量分配空間及初始化
DT——定義10字節(jié)偽指令- 用于為一個(gè)或多個(gè)10字節(jié)變量分配空間及初始化
- 10字節(jié)變量可以表達(dá)擴(kuò)展精度浮點(diǎn)數(shù)
- 用于為一個(gè)或多個(gè)10字節(jié)變量分配空間及初始化
-
定位偽指令:控制數(shù)據(jù)的偏移地址、-
ORG參數(shù):ORG偽指令是將當(dāng)前偏移地址指針指向參數(shù)表達(dá)的偏移地址:ORG 100h ;從100h處安排數(shù)據(jù)或程序 ORG $+10 ;使偏移地址加10,即跳過10個(gè)字節(jié)空間MASM中,符號“$”表示當(dāng)前偏移地址值EVEN ;從偶地址開始 ALIGN n ;從n的整數(shù)倍地址開始
-
3. 初值表
-
初值表是用逗號分隔的參數(shù)
-
主要由數(shù)值常數(shù)、表達(dá)式或?、DUP組成
-
?——表示初值不確定,即未賦初值
-
DUP——表示重復(fù)初值
-
DUP的格式為:
重復(fù)次數(shù) DUP(重復(fù)參數(shù))
-
3、變量和標(biāo)號的屬性
-
地址屬性
- 標(biāo)號和名字對應(yīng)存儲單元的邏輯地址
- 邏輯地址包括:段地址和偏移地址
-
類型屬性
- 標(biāo)號、子程序名可以是NEAR、FAR,分別表示段內(nèi)和段間
- 變量名的類型可以是BYTE(字節(jié))、WORD(字)、DWROD(雙字)
-
地址操作符:取得名字或標(biāo)號的段地址和偏移地址兩個(gè)屬性
[ ] 將括起的表達(dá)式作為存儲器地址 $ 當(dāng)前偏移地址 : 采用指定的段地址寄存器 OFFSET 名字/標(biāo)號 返回名字或標(biāo)號的偏移地址 SEG 名字/標(biāo)號 返回名字或標(biāo)號的段地址 -
類型操作符:對名字或標(biāo)號的類型屬性進(jìn)行有關(guān)設(shè)置
-
類型名 PTR 名字/標(biāo)號
- PTR操作符使名字或標(biāo)號具有指定的類型
- 使用PTR操作符,可以臨時(shí)改變名字或標(biāo)號的類型
- 類型名可以是:BYTE/WORD/DWORD/FWORD/QWORD/TBYTE或者是NEAR/FAR,還可以是由STRUCT、RECORD、UNION以及TYPEDEF定義的類型
mov al,byte ptr w_var ;w_var是一個(gè)字節(jié)變量 jmp far ptr n_label ;n_label是一個(gè)標(biāo)號 -
THIS 類型名
- 利用THIS說明的操作數(shù)具有匯編時(shí)的當(dāng)前邏輯地址,但具有指定的類型
b_var equ THIS byte ;按字節(jié)訪問變量b_var,但與w_var的地址相同 w_var dw 10 dup(0) ;按字訪問變量w_var f_jump equ THIS far ;用f_jump為段間轉(zhuǎn)移(f_jump label far) n_jump: mov ax,w_var ;用n_jump為段內(nèi)近轉(zhuǎn)移,但兩者指向同一條指令- LABEL偽指令的功能等同于“EQU THIS”
-
SHORT 標(biāo)號
-
TYPE 名字/標(biāo)號
- 返回表明名字或標(biāo)號類型的一個(gè)字量數(shù)值
- 對字節(jié)、字和雙字變量依次返回1、2和4;
- 對短、近和遠(yuǎn)轉(zhuǎn)移依次返回ff01h、ff02h和ff05h
mov ax,TYPE w_var ;匯編結(jié)果為 mov ax,2 mov ax,TYPE n_jump ;匯編結(jié)果為 mov ax,0ff02h(near標(biāo)號)- 操作符SIZEOF返回整個(gè)變量占用的字節(jié)數(shù)
- LENGTHOF返回整個(gè)變量的數(shù)據(jù)項(xiàng)數(shù)(即元素?cái)?shù)) SIZEOF = LENGTHOF × TYPE
-
SIZEOF 變量名
-
LENGTHOF 變量名
-
3、程序段的定義和屬性
exe程序
- 可執(zhí)行程序
- 可以有獨(dú)立的代碼、數(shù)據(jù)和堆棧段,還可以有多個(gè)代碼段或多個(gè)數(shù)據(jù)段,程序長度可以超過64KB,執(zhí)行起始處可以任意指定
- 當(dāng)DOS裝入或執(zhí)行一個(gè)程序時(shí),DOS確定當(dāng)時(shí)主存最低的可用地址作為該程序的裝入起始點(diǎn)。此點(diǎn)以下的區(qū)域稱為程序段。在程序段內(nèi)偏移0處,DOS為該程序建立一個(gè)程序段前綴控制塊PSP(Program Segment Prefix),它占256(=100h)個(gè)字節(jié);而在偏移100h處才裝入程序本身
com程序
- COM程序是一種將代碼、數(shù)據(jù)和堆棧段合一的結(jié)構(gòu)緊湊的程序,所有代碼、數(shù)據(jù)都在一個(gè)邏輯段內(nèi),不超過64KB
- 程序開發(fā)中,需要滿足一定的要求并采用相應(yīng)參數(shù)才能夠生成COM結(jié)構(gòu)的程序
- COM文件存儲在磁盤上是主存的完全影象,不包含重新定位的加載信息,與EXE文件相比其加載速度更快,占用的磁盤空間也少
- 盡管DOS也為COM程序建立程序段前綴PSP,但由于兩種文件結(jié)構(gòu)不同,所以加載到主存后各段設(shè)置并不完全一樣
1、簡化段定義偽指令合集
.MODEL存儲模型位指令
-
使用簡化段定義,必須有存儲模型位指令
-
.model語句位于所有段定義語句之前
-
存儲模型決定一個(gè)程序的規(guī)模,確定進(jìn)行子程序調(diào)用、指令轉(zhuǎn)移和數(shù)據(jù)訪問的缺省屬性
-
MASM有7種不同的存儲模型:
① TINY ② SMALL
③ COMPACT ④ MEDIUM
⑤ LARGE ⑥ HUGE
⑦ FLAT
簡化段定義偽指令
-
.STACK [大小] ;堆棧段開始
.DATA ;數(shù)據(jù)段開始
.CODE [段名] ;代碼段開始
-
簡化段定義偽指令指明一個(gè)邏輯段的開始,同時(shí)自動結(jié)束前面的一個(gè)段,采用簡化段定義偽指令前,需有.model語句
-
使用簡化段定義,各段名稱和其他用戶所需的信息可以使用MASM預(yù)定義符號
例如:@data表示由.data等定義的數(shù)據(jù)段的段名
.STARTUP 程序開始偽指令
- 按照CPU類型、存儲模型、操作系統(tǒng)和堆棧類型,產(chǎn)生程序開始執(zhí)行的代碼;同時(shí)還指定程序開始執(zhí)行的起始點(diǎn)
- 在DOS下,還將設(shè)置DS值,調(diào)整SS和SP值
EXIT [返回參數(shù)] 程序終止偽指令
- 產(chǎn)生終止程序執(zhí)行返回操作系統(tǒng)的指令代碼
- 它的可選參數(shù)是一個(gè)返回的數(shù)碼,通常用0表示沒有錯(cuò)誤
- 例如.exit 0對應(yīng)的代碼是:
mov ax,4c00h
int 21h
- DOS功能調(diào)用的4ch子功能(返回DOS):
- 入口參數(shù):AH=4ch,AL=返回?cái)?shù)碼
END [標(biāo)號] 匯編結(jié)束偽指令
- 指示匯編程序MASM到此結(jié)束匯編過程
- 源程序的最后必須有一條END語句
- 可選的標(biāo)號用于指定程序開始執(zhí)行點(diǎn),連接程序?qū)?jù)此設(shè)置CS : IP值
- 采用了.startup偽指令就不需要再用“end 標(biāo)號”指明開始執(zhí)行點(diǎn),但還要有end偽指令
2、com程序的編寫
-
利用MASM 6.x的簡化段定義格式,可以非常容易地創(chuàng)建一個(gè)COM程序
-
遵循的規(guī)則:
-
- 采用TINY模型
- 源程序只設(shè)置代碼段,無數(shù)據(jù)、堆棧等段
- 程序必須從偏移地址100h處開始執(zhí)行
- 數(shù)據(jù)只能安排在代碼段中,注意不能與可執(zhí)行代碼相沖突,通常在程序最后
3、完整段定義偽指令
完整段定義位指令
段名 segment 定位 組合 段字 '類別'... ;語句序列
段名 ends
-
段定位(align)屬性:指定邏輯段在主存儲器中的邊界
BYTE 段開始為下一個(gè)可用的字節(jié)地址(xxxx xxxxb) WORD 段開始為下一個(gè)可用的偶數(shù)地址(xxxx xxx0b) DWORD 段開始為下一個(gè)可用的4倍數(shù)地址(xxxxxx00b) PARA 段開始為下一個(gè)可用的節(jié)地址(xxxx 0000b) PAGE 段開始為下一個(gè)可用的頁地址(0000 0000b) - 簡化段定義偽指令的代碼段和數(shù)據(jù)段默認(rèn)采用WORD定位,堆棧段默認(rèn)采用PARA定位
- 完整段定義偽指令的默認(rèn)定位屬性是PARA,其低4位已經(jīng)是0,所以默認(rèn)情況下數(shù)據(jù)段的偏移地址從0開始
-
段組合(combine)屬性:指定多個(gè)邏輯段之間的關(guān)系
PRIVATE 本段與其他段沒有邏輯關(guān)系,不與其他段合并,每段都有自己的段地址。這是完整段定義偽指令默認(rèn)的段組合方式 PUBLIC 連接程序把本段與所有同名同類型的其他段相鄰地連接在一起,然后為所有這些段指定一個(gè)共同的段地址,也就是合成一個(gè)物理段。這是簡化段定義偽指令默認(rèn)的段組合 STACK 本段是堆棧的一部分,連接程序?qū)⑺蠸TACK段按照與PUBLIC段的同樣方式進(jìn)行合并。這是堆棧段必須具有的段組合 -
段字(use)屬性
-
為支持32位段而設(shè)置的屬性
-
對于16位×86cpu來說,默認(rèn)是16位段,即USE16
而對于匯編32位x86 CPU指令時(shí),它默認(rèn)采用32位段,即USE32;但可以使用USE16指定標(biāo)準(zhǔn)的16位段
-
編寫運(yùn)行于實(shí)地址方式(8086工作方式)的匯編語言程序,必須采用16位段
-
-
段類別(class)屬性
- 當(dāng)連接程序組織段時(shí),將所有的同類別段相鄰分配
- 段類別可以是任意名稱,但必須位于單引號中
- 大多數(shù)MASbM程序使用 ‘code’、'data’和’stack’來分別指名代碼段、數(shù)據(jù)段和堆棧段,以保持所有代碼和數(shù)據(jù)的連續(xù)
指定段寄存器偽指令
- 通知MASM用指定的段寄存器來尋址對應(yīng)的邏輯段,即建立段寄存器與段的缺省關(guān)系
- 在明確了程序中各段與段寄存器之間的關(guān)系后,匯編程序會根據(jù)數(shù)據(jù)所在的邏輯段,在需要時(shí)自動插入段超越前綴。這是ASSUME偽指令的主要功能
- ASSUME偽指令并不為段寄存器設(shè)定初值,連接程序LINK將正確設(shè)置CS : IP和SS : SP,由于數(shù)據(jù)段通常都需要,所以在樣板源程序中,首先為DS賦值;如果使用附加段,還要賦值ES
段組偽指令
-
把多個(gè)同類段合并為一個(gè)64KB物理段,并用一個(gè)組名統(tǒng)一存取它
-
定義段組后,段組內(nèi)各段就統(tǒng)一為一個(gè)段地址,各段定義的變量和標(biāo)號的偏移地址就相對于段組基地址計(jì)算
-
offset操作符取變量和標(biāo)號相對于段組的偏移地址,如果沒有段組則取得相對于段的偏移地址
offset后可以跟段組中的某個(gè)段名,表示該段最后一個(gè)字節(jié)后面字節(jié)相對于段組的偏移地址
段順序偽指令
-
.SEG ;按照源程序的各段順序
.DOSSEG ;按照微軟使用的標(biāo)準(zhǔn)DOS規(guī)定
.ALPHA ;按照段名的字母順序
- 段順序偽指令確定各邏輯段在主存的前后位置
- 完整段定義格式中,默認(rèn)按照源程序各段的書寫順序安排(即.seg)
- 采用.model偽指令的簡化段定義格式,則是規(guī)定的標(biāo)準(zhǔn)DOS程序順序( 即.dosseg ):
代碼段 → 數(shù)據(jù)段 → 堆棧段
主存地址低端 ——> 高端
4、簡化段定義格式的段屬性
-
采用簡化段定義格式的源程序,同樣具有段定位、組合、類別以及段組等屬性(表3.4),具有默認(rèn)的屬性
-
.MODEL偽指令除了設(shè)置程序采用的存儲模型外,還具有如下語句的作用:
dgroup GROUP _data,_bss,stack
assume cs:_TEXT,ds:dgroup,ss:dgroup
第四章 基本匯編語言程序設(shè)計(jì)
1、順序程序設(shè)計(jì)
順序程序完全按指令書寫的前后順序執(zhí)行每一條指令,是最基本、最常見的程序結(jié)構(gòu)
2、分支程序設(shè)計(jì)
- 分支程序根據(jù)條件是真或假決定執(zhí)行與否
- 判斷的條件是各種指令,如CMP、TEST等執(zhí)行后形成的狀態(tài)標(biāo)志
- 轉(zhuǎn)移指令Jcc和JMP可以實(shí)現(xiàn)分支控制;還可以采用MASM 6.x提供的條件控制偽指令實(shí)現(xiàn)
1、單分支程序設(shè)計(jì)
- 條件成立跳轉(zhuǎn),否則順序執(zhí)行分支語句體;注意選擇正確的條件轉(zhuǎn)移指令和轉(zhuǎn)移目標(biāo)地址
2、雙分支程序設(shè)計(jì)
-
條件成立跳轉(zhuǎn)執(zhí)行第2個(gè)分支語句體,否則順序執(zhí)行第1個(gè)分支語句體。
注意第1個(gè)分支體后一定要有一個(gè)JMP指令跳到第2個(gè)分支體后
3、多分支程序設(shè)計(jì)
- 多個(gè)條件對應(yīng)各自的分支語句體,哪個(gè)條件成立就轉(zhuǎn)入相應(yīng)分支體執(zhí)行。多分支可以化解為雙分支或單分支結(jié)構(gòu)的組合
3、循環(huán)程序設(shè)計(jì)
- 循環(huán)結(jié)構(gòu)一般是根據(jù)某一條件判斷為真或假來確定是否重復(fù)執(zhí)行循環(huán)體
- 循環(huán)指令和轉(zhuǎn)移指令可以實(shí)現(xiàn)循環(huán)控制;還可以采用MASM 6.x提供的循環(huán)控制偽指令實(shí)現(xiàn)
1、冒泡法
- “冒泡法”是一種排序算法,不是最優(yōu)的算法,但它易于理解和實(shí)現(xiàn)
- 冒泡法從第一個(gè)元素開始,依次對相鄰的兩個(gè)元素進(jìn)行比較,使前一個(gè)元素不大于后一個(gè)元素;將所有元素比較完之后,最大的元素排到了最后;然后,除掉最后一個(gè)元素之外的元素依上述方法再進(jìn)行比較,得到次大的元素排在后面;如此重復(fù),直至完成就實(shí)現(xiàn)元素從小到大的排序
- 這需要一個(gè)雙重循環(huán)程序結(jié)構(gòu)
move cx,count ;cx數(shù)組元素個(gè)數(shù)dec cx ;外循環(huán)個(gè)數(shù),元素個(gè)數(shù)減1
outlp: move dx,cx ;dx為內(nèi)循環(huán)個(gè)數(shù)move bx,offset array
inlp: move al,[bx] ;取前一個(gè)元素cmp al,[bx+1] ;與后一個(gè)元素比較jna next ;前一個(gè)不大于后一個(gè)元素,則不進(jìn)行交換xchg al,[bx+1] ;否則,進(jìn)行交換move [bx],al
next: inc bx ;下一對元素dec dxjnz inlp ;內(nèi)循環(huán)尾loop outlp ;外循環(huán)尾
2、串操作類指令
-
串傳送 MOVES
- 把字節(jié)或字從主存的源地址傳送到目的地址
MOVSB ;字節(jié)串傳送:ES:[DI]←DS:[SI] ;SI←SI±1,DI←DI±1 MOVSW ;字串傳送:ES:[DI]←DS:[SI] ;SI←SI±2,DI←DI±2 -
串存儲 STOS
- 把AL或AX數(shù)據(jù)傳送到目的地址
STOSB ;字節(jié)串存儲:ES:[DI]←AL ;DI←DI±1 STOSW ;字串存儲:ES:[DI]←AX ;DI←DI±2 -
串讀取 LODS
- 把指定主存單元的數(shù)據(jù)傳送給AL或AX
LODSB ;字節(jié)串讀取:AL←DS:[SI] ;SI←SI±1 LODSW ;字串讀取:AX←DS:[SI] ;SI←SI±2 -
串比較 CMPS
- 將主存中的源操作數(shù)減去目的操作數(shù),以便設(shè)置標(biāo)志,進(jìn)而比較兩操作數(shù)之間的關(guān)系
CMPSB ;字節(jié)串比較:DS:[SI]-ES:[DI] ;SI←SI±1,DI←DI±1 CMPSW ;字串比較:DS:[SI]-ES:[DI] ;SI←SI±2,DI←DI±2 -
串掃描 SCAS
- 將AL/AX減去目的操作數(shù),以便設(shè)置標(biāo)志,進(jìn)而比較AL/AX與操作數(shù)之間的關(guān)系
SCASB ;字節(jié)串掃描:AL-ES:[DI] ;DI←DI±1 SCASW ;字串掃描:AX-ES:[DI] ;DI←DI±2 -
REP 重復(fù)前綴
- 每執(zhí)行一次串指令,CX減1,直到CX=0,重復(fù)執(zhí)行結(jié)束
- REP前綴可以理解為:當(dāng)數(shù)據(jù)串沒有結(jié)束(CX≠0),則繼續(xù)傳送
-
REPZ 重復(fù)前綴
- 每執(zhí)行一次串指令,CX減1,并判斷ZF是否為0,只要CX=0或ZF=0,重復(fù)執(zhí)行結(jié)束
- REPZ/REPE前綴可以理解為:當(dāng)數(shù)據(jù)串沒有結(jié)束(CX≠0),并且串相等(ZF=1),則繼續(xù)比較
-
REPNZ 重復(fù)前綴
- 每執(zhí)行一次串指令,CX減1,并判斷ZF是否為1,只要CX=0或ZF=1,重復(fù)執(zhí)行結(jié)束
- REPNZ/REPNE前綴可以理解為:當(dāng)數(shù)據(jù)串沒有結(jié)束(CX≠0),并且串不相等(ZF=0),則繼續(xù)比較
4、 子程序設(shè)計(jì)
- 把功能相對獨(dú)立的程序段單獨(dú)編寫和調(diào)試,作為一個(gè)相對獨(dú)立的模塊供程序使用,就形成子程序
- 子程序可以實(shí)現(xiàn)源程序的模塊化,可簡化源程序結(jié)構(gòu),可以提高編程效率
1、過程定義位指令
過程名 proc [near|far]...
過程名 endp
-
過程名(子程序名)為符合語法的標(biāo)識符
NEAR屬性(段內(nèi)近調(diào)用) 的過程只能被相同代碼段的其他程序調(diào)用 FAR屬性(段間遠(yuǎn)調(diào)用) 的過程可以被相同或不同代碼段的程序調(diào)用 -
對簡化段定義格式,在微型、小型和緊湊存儲模型下,過程的缺省屬性為near;
-
在中型、大型和巨型存儲模型下,過程的缺省屬性為far
-
對完整段定義格式,過程的缺省屬性為near
-
用戶可以在過程定義時(shí)用near或far改變?nèi)笔傩?/strong>
-
通用格式:
具有多個(gè)出口的子程序:
2、子程序的參數(shù)傳遞
入口參數(shù)(輸入?yún)?shù)):主程序提供給子程序
出口參數(shù)(輸出參數(shù)):子程序返回給主程序
參數(shù)的形式: ① 數(shù)據(jù)本身(傳值)
**② 數(shù)據(jù)的地址(傳址)**
傳遞的方法: ① 寄存器 ② 變量 ③ 堆棧
例題:
-
用寄存器傳遞參數(shù)
把參數(shù)存于約定的寄存器中,可以傳值,也可以傳址。
子程序?qū)в谐隹趨?shù)的寄存器不能保護(hù)和恢復(fù)(主程序視具體情況進(jìn)行保護(hù))
子程序?qū)в腥肟趨?shù)的寄存器可以保護(hù),也可以不保護(hù);但最好一致
-
入口參數(shù):CX=元素個(gè)數(shù),DS:BX=數(shù)組的段地址:偏移地址
出口參數(shù):AL=校驗(yàn)和
;例4.16主程序 .startup ;設(shè)置入口參數(shù)(含有DS<-數(shù)組的段地址) mov bx,offset array ;BX<-數(shù)組的偏移地址 mov CX,count ;cx<-數(shù)組的元素個(gè)數(shù) call checksuma ;調(diào)用求和過程mov result,al ;處理出口參數(shù).exit 0 ;例4.16子程序 checksuma procxor al,al ;累加器清0 suma: add al,[bx] ;求和inc bx ;指向下一字節(jié)loop sumaret checksuma endpend
-
2.用變量傳遞參數(shù)
主程序和子程序直接采用同一個(gè)變量名共享同一個(gè)變量,實(shí)現(xiàn)參數(shù)的傳遞
不通模塊間共享時(shí),需要聲明
-
入口參數(shù):count=元素個(gè)數(shù),array=數(shù)組名(段地址:偏移地址)
出口參數(shù):result=校驗(yàn)和
;例4.16;主程序call checksumb;子程序 checksumb proc push ax push bx push cx xor al,al ;累加器清0 mov bx offset array ;bx<-數(shù)組的偏移地址mov cx,count ;cx<-數(shù)組的元素個(gè)數(shù) sumb: add al,[bx] ;求和inc bxloop sumbmov result,al ;保存校驗(yàn)和pop cxpop bxpop axret checksumb endp
-
用堆棧傳遞參數(shù)
主程序?qū)⒆映绦虻娜肟趨?shù)壓入堆棧,子程序從堆棧中取出參數(shù)
子程序?qū)⒊隹趨?shù)壓入堆棧,主程序彈出堆棧取得它們
-
入口參數(shù):順序壓入偏移地址和元素個(gè)數(shù)
出口參數(shù):AL=校驗(yàn)和
;例4.16主程序.startup mov ax,offset array ;偏移地址push ax mov ax,count ;元素個(gè)數(shù)push ax call checksumc add sp,4 mov result,al .exit 0 ;例4.16子程序 checksumc proc push bp mov bp,sp ;利用BP間接尋址存取參數(shù)push bx push cx mov bx,[bp+6] ;SS:[BP+6]指向偏移地址mov cx,[bp+4] ;SS:[BP+4]指向元素個(gè)數(shù)xor al,al sumc: add al,[bx] inc bx loop sumc pop cx pop bx pop bp ret checksumc endp -
3、子程序的嵌套
子程序內(nèi)包含有子程序的b調(diào)用就是子程序嵌套,沒有什么特殊要求
4、子程序的遞歸
- 當(dāng)子程序直接或間接地嵌套調(diào)用自身時(shí)稱為遞歸調(diào)用,含有遞歸調(diào)用的子程序稱為遞歸子程序
- 遞歸子程序必須采用寄存器或堆棧傳遞參數(shù),遞歸深度受堆棧空間的限制
5、子程序的重入
- 子程序的重入是指子程序被中斷后又被中斷服務(wù)程序所調(diào)用,能夠重入的子程序稱為可重入子程序。在子程序中,注意利用寄存器和堆棧傳遞參數(shù)和存放臨時(shí)數(shù)據(jù),而不要使用固定的存儲單元(變量),就能夠?qū)崿F(xiàn)重入。
- 子程序的重入不同于子程序的遞歸。重入是被動地進(jìn)入,而遞歸是主動地進(jìn)入;重入的調(diào)用間往往沒有關(guān)系,而遞歸的調(diào)用間卻是密切相關(guān)的。遞歸子程序也是可重入子程序
第五章 高級匯編語言程序設(shè)計(jì)
1、高級語言特性
MASM 6.0 引入高級語言的程序設(shè)計(jì)特性
-
條件控制偽指令
.IF .ELSE .ENDIF
-
循環(huán)控制偽指令
.WHILE .ENDW .REPEAT .UNTIL
-
過程聲明和過程調(diào)用偽指令
.PROTO .INVOKE
1、條件控制偽指令
.IF .ELSE .ENDIF
類似高級語言中IF、THEN、ELSE、ENDIF的相應(yīng)功能
在匯編時(shí)要展開,自動生成相應(yīng)的比較和條件轉(zhuǎn)移指令序列,實(shí)現(xiàn)程序分支
常見的操作符
| 操作符 | 功能 | 操作符 | 功能 | 操作符 | 功能 |
|---|---|---|---|---|---|
| == | 等于 | && | 邏輯與 | CARRY? | CF=1? |
| != | 不等于 | || | 邏輯或 | OVERFLOW? | OF=1? |
| > | 大于 | ! | 邏輯非 | PARITY? | PF=1? |
| >= | 大于等于 | & | 位測試 | SIGN? | SF=1? |
| < | 小于 | () | 改變優(yōu)先級 | ZERO? | ZF=1? |
| <= | 小于等于 |
;單分支結(jié)構(gòu)
.IF AX < 0neg ax
.ENDIF
mov result,ax;雙分支結(jié)構(gòu)
.IF ax==5mov bx,axmov ax,0
.ELSEdec ax
.ENDIF
2、循環(huán)控制偽指令
;求1~100之和
xor ax, ax
mov cx,100
.while cx!=0add ax,cxdec cx
.endw
mov sum,ax
;求1~100之和
xor ax, ax
mov cx,100
.repeatadd ax,cxdec cx
.until cx==0
mov sum,ax
3、過程聲明和過程調(diào)用偽指令
過程定義位指令PROC
要調(diào)用帶參數(shù)過程定義的過程,不應(yīng)該用CALL指令,因?yàn)楸容^煩瑣
應(yīng)該采用過程調(diào)用
INVOKE指令使用
INVOKE偽指令的前提是需要用PROTO偽指令對過程進(jìn)行聲明
-
過程聲明偽指令:用于事先聲明過程的結(jié)構(gòu)
PROTO 調(diào)用距離 語言類型, 參數(shù):類型 -
過程調(diào)用偽指令:
INVOKE 過程名,參數(shù),...
示例:
2、宏結(jié)構(gòu)程序設(shè)計(jì)
宏(Macro)是匯編語言的一個(gè)特點(diǎn),它是與子程序類似又獨(dú)具特色的另一種簡化源程序的方法
宏匯編、重復(fù)匯編、條件匯編——統(tǒng)稱為
宏結(jié)構(gòu)
1、宏匯編
a. 宏
具有宏名的一段匯編語句序列(宏定義時(shí)書寫)
b. 宏指令
匯編語句的縮寫(宏調(diào)用時(shí)書寫)
c. 宏展開
宏指令用這段宏代替的過程(宏匯編時(shí)實(shí)現(xiàn))
宏的參數(shù)
宏的參數(shù)功能強(qiáng)大,頗具特色
配合宏,還有宏操作符和有關(guān)偽指令
宏操作符
與宏有關(guān)的偽指令
宏匯編與子程序的比較
**<img src="https://zsr204.oss-cn-beijing.aliyuncs.com/imgs/20200709170741.png" alt="image-20200709170741619" style="zoom:50%;" />**
2、重復(fù)匯編
-
重復(fù)匯編指在匯編過程中,重復(fù)展開一段(基本)相同的語句 -
重復(fù)匯編沒有名字,不能被調(diào)用
-
重復(fù)匯編常用在宏定義體中,也可以在一般匯編語句中使用
-
重復(fù)匯編偽指令有三個(gè):
REPEAT——按參數(shù)值重復(fù)FOR——按參數(shù)個(gè)數(shù)重復(fù)FORC——按參數(shù)的字符個(gè)數(shù)重復(fù) -
最后,用ENDM結(jié)束
1. 按參數(shù)值重復(fù)
REPEAT 重復(fù)次數(shù)重復(fù)體
ENDM
2. 按參數(shù)個(gè)數(shù)重復(fù)
FOR 形參,〈實(shí)參表〉重復(fù)體
ENDM
3. 按參數(shù)字符個(gè)數(shù)重復(fù)
FORC 形參, 字符串重復(fù)體
ENDM
3、條件匯編
條件匯編偽指令在匯編過程中,根據(jù)條件決定匯編的語句
pdata macro numIF num lt 100 ;;如果num < 100,則匯編如下語句db num dup (?)ELSE ;;否則,匯編如下語句db 100 dup (?)ENDIFendm
;-----------------------------------------------------------------------------------------------
pdata 12 ;宏調(diào)用①
db 12 dup(?) ;宏匯編結(jié)果①
pdata 102 ;宏調(diào)用②
db 100 dup(?) ;宏匯編結(jié)果②
宏結(jié)構(gòu)的作用
宏匯編、重復(fù)匯編和條件匯編為源程序的編寫提供了很多方便,靈活運(yùn)用它們可以編寫出非常良好的源程序來- 匯編系統(tǒng)中有些以圓點(diǎn)起始的偽指令(如.startup、.exit等)實(shí)際上是一種宏結(jié)構(gòu)
dstring MACRO string ;;定義字符串db '&string&',0dh,0ah,'$'ENDM
mainbegin MACRO dsseg ;;設(shè)置數(shù)據(jù)段地址mov ax,dssegmov ds,axENDM
dispmsg MACRO messagemov dx,offset messagemov ah,09hint 21hENDM
mainend MACRO retnum ;;返回DOS,可不帶參數(shù)ifb <retnum>mov ah,4ch ;;沒有參數(shù)elsemov ax,4c00h+(retnum AND 0ffh);; 有參數(shù)endifint 21hENDM;----------------------------------------------------------.model small.stack 256.datamsg1 equ this bytedstring <Hello,Everybody !!>msg2 equ this bytedstring <You see,I made it.>.codestart: mainbegin @data ;建立DS內(nèi)容dispmsg msg1 ;顯示msg1字符串dispmsg msg2 ;顯示msg2字符串mainend ;返回DOSend start
3、模塊化程序設(shè)計(jì)
將
程序分段、采用子程序或者宏結(jié)構(gòu)都是進(jìn)行模塊化程序設(shè)計(jì)
1. 源程序文件的包含
2. 目標(biāo)代碼文件的連接
-
把常用子程序?qū)懗瑟?dú)立的源程序文件,單獨(dú)匯編,形成子程序的
目標(biāo)文件.OBJ -
主程序也經(jīng)過獨(dú)立匯編之后形成
目標(biāo)文件 -
連接程序?qū)⑺?code>目標(biāo)文件連接起來,最終產(chǎn)生
可執(zhí)行文件
需要遵循的原則:
**① 聲明共用的變量、過程等**
**② 實(shí)現(xiàn)正確的段組合**
**③ 處理好參數(shù)傳遞問題**
3. 子程序庫的調(diào)入
把常用子程序?qū)懗瑟?dú)立的源文件,單獨(dú)匯編形成OBJ 文件后,存入
子程序庫主程序也單獨(dú)匯編形成OBJ文件
主程序連接時(shí),調(diào)入子程序庫中的
子程序模塊,產(chǎn)生最終的可執(zhí)行文件
例題:
;Lt512c.asm
... ;宏定義
.code
extern ALdisp:near,sorting:near,input:near ;聲明其他模塊中的子程序
.startup
...
.exit 0
end
;sub512c1.asm.model small.codepublic aldisp
Aldisp proc...
Aldisp endpend
;sub512c2.asm.model small.codepublic sorting
sorting proc...
sorting endpend
;sub512c3.asm.model small.codepublic input
input proc...
input endpend
例題:
4、輸入輸出程序設(shè)計(jì)
1、 輸入輸出指令
8086通過輸入輸出指令與外設(shè)進(jìn)行數(shù)據(jù)交換,呈現(xiàn)給我們的外設(shè)是端口(I/O地址)
8086用于尋址外設(shè)端口的地址線為16條,端口最多為216=65536(64K)個(gè),端口號為0000H~FFFFH
每個(gè)端口用于傳送一個(gè)字節(jié)的外設(shè)數(shù)據(jù)
輸入輸出的尋址方式有兩種:
1、直接尋址:只用于尋址00H~FFH前256個(gè)端口,操作數(shù)i8表示端口號
2、間接尋址:可用于尋址全部64K個(gè)端口,DX寄存器的值就是端口號
- 大于FFH的端口只能采用間接尋址方式
a. 輸入指令I(lǐng)N
將外設(shè)數(shù)據(jù)傳送給CPU內(nèi)的AL/AX
| IN AL,i8 | ;字節(jié)輸入:AL←I/O端口(i8直接尋址) |
|---|---|
| IN AL,DX | ;字節(jié)輸入:AL←I/O端口(DX間接尋址) |
| IN AX,i8 | ;字輸入:AX←I/O端口(i8直接尋址) |
| IN AX,DX | ;字輸入:AX←I/O端口(DX間接尋址) |
b. 輸出指令OUT
將CPU內(nèi)的AL/AX數(shù)據(jù)傳送給外設(shè)
| OUT i8,AL | ;字節(jié)輸出:I/O端口←AL(i8直接尋址) |
|---|---|
| OUT DX,AL | ;字節(jié)輸出:I/O端口←AL(DX間接尋址) |
| OUT i8,AX | ;字輸出:I/O端口←AX(i8直接尋址) |
| OUT DX,AX | ;字輸出:I/O端口←AX(DX間接尋址) |
2、程序直接控制輸入輸出
3、程序查詢輸入輸出
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-0sT9y2qx-1598619859404)(https://zsr204.oss-cn-beijing.aliyuncs.com/imgs/20200709194057.png)]
4、中斷服務(wù)程序
需要交換數(shù)據(jù)的外設(shè),采用中斷請求向處理器提出要求
處理器執(zhí)行事先設(shè)計(jì)好的中斷服務(wù)程序,在中斷服務(wù)程序當(dāng)中實(shí)現(xiàn)數(shù)據(jù)交換
8086可以處理256種中斷,分為內(nèi)部、外部兩種類型
外部可屏蔽中斷用于與外 設(shè)進(jìn)行數(shù)據(jù)交換
內(nèi)部中斷服務(wù)程序
駐留中斷服務(wù)程序
外部可屏蔽中斷服務(wù)程序
總結(jié)
以上是生活随笔為你收集整理的8086汇编语言精华笔记总结~的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你想了解的Cookie和Session就
- 下一篇: 2020了,还要学JSP嘛?入个门呗!毕