《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 解決方案 > 匯編基礎(chǔ):子程序設(shè)計(jì)

匯編基礎(chǔ):子程序設(shè)計(jì)

2017-06-10
關(guān)鍵詞: 匯編

在一個(gè)程序中的不同地方,常常需要多次非循環(huán)的使用完成特定功能的程序段,,這些程序段除了某些變量的賦值不同外,,具有相同的指令序列,這時(shí),,我們?yōu)榱藴p少重復(fù)編寫程序,,縮短目標(biāo)代碼,節(jié)省內(nèi)存空間,,把視線這一功能的指令序列組成一個(gè)相對獨(dú)立的程序段,。這也就是我們這片文章中所要討論的子程序。

子程序相當(dāng)于高級語言(比如C語言)中的過程和函數(shù),,在匯編語言中子程序也稱為過程,。使用子程序的好處:

a、有利于程序模塊化,、結(jié)構(gòu)化和自頂向下的程序設(shè)計(jì)方法,,簡化了程序設(shè)計(jì)過程。

b,、增加了源程序的可讀性,,便于調(diào)試維護(hù)

c、減少了目標(biāo)代碼鎖占用的空間

d,、子程序一旦編制成功,,在開發(fā)研制各種軟件時(shí)都可使用,,縮短了軟件的開發(fā)周期。

一,、子程序的調(diào)用與返回

1,、子程序的定義

子程序必須定義在一個(gè)邏輯段內(nèi),子程序的定義由過程定義偽指令PROC/ENDP來實(shí)現(xiàn),,它們分別用在程序的子程序的前后,,一般格式如下:

PROC_NAME   PROC    [NEAR/FAR]    
......    
PROC_NAME   ENDP

其中PROC_NAME為子程序名,也極為CALL的操作數(shù),,自程序具有3個(gè)屬性:段屬性,、偏移量屬性和類型屬性,段屬性表示該子程序所在段的段基值,。偏移量屬性表示該子程序在段中的偏移量,。類型屬性也稱為距離屬性,可以是NEAR或FAR,,屬性為NEAR的子程序只能在本段內(nèi)調(diào)用,,屬性為FAR的子程序則可以在本段以內(nèi)以及其他段中調(diào)用。

2,、調(diào)用指令

當(dāng)主程序?qū)傩允荖EAR的子程序時(shí),,CPU把當(dāng)前指令指針I(yè)P的內(nèi)容壓入堆棧,作為返回地址保存起來,,然后將子程序的偏移量送入IP,,當(dāng)從子程序返回時(shí),將從堆棧彈出2個(gè)字節(jié)的返回地址送入IP,,當(dāng)調(diào)用屬性是FAR的過程時(shí),,CPU把當(dāng)前的段寄存器CS與指令指針I(yè)P的內(nèi)容都壓入堆棧,作為返回地址保存起來,,然后將子程序的段基值與偏移量送入CS與IP,,當(dāng)子程序返回時(shí),將從堆棧彈出4個(gè)字節(jié)的返回地址分別送入IP與CS,。

我們?nèi)菀字?,?dāng)主程序和子程序處于同一邏輯段時(shí),可以把類型屬性定義為NEAR,,也可以把類型屬性定義為FAR,,然后進(jìn)行調(diào)用。而當(dāng)主程序與子程序不在同一邏輯段是,,只可把過程的類型定義為FAR,,然后調(diào)用。

二,、返回指令

返回指令RET是子程序邏輯上的最后一條指令,,也就是最后一條被執(zhí)行的指令,,它使子程序在完成功能后返回到調(diào)用它的CALL指令的后續(xù)指令處,即返回地址處繼續(xù)執(zhí)行,。

三,、子程序設(shè)計(jì)的基本要求

1、子程序必須有一定的通用性

2,、注意寄存器的保存和恢復(fù)

3,、正確使用堆棧

4、選用適當(dāng)?shù)姆椒ㄔ谥鞒绦蚺c子程序間進(jìn)行參數(shù)傳遞

5,、編制子程序說明信息文件

四,、子程序與主程序間的參數(shù)傳遞

在匯編語言中最常用的參數(shù)傳遞方式有3種,分別是:用寄存器傳遞參數(shù),、用堆棧傳遞參數(shù)和用地址表達(dá)式傳遞參數(shù),。

1,、用寄存器傳遞參數(shù)

這種方式是通過通用寄存器來傳遞的參數(shù),,即在主程序調(diào)用子程序前,將入口參數(shù)送到約定的通用寄存器中,,子程序可以直接從這些寄存器中取出參數(shù)進(jìn)行加工處理,,并將結(jié)果放在約定的通用寄存器中,返回主程序,,主程序再從約定的寄存器中取出結(jié)果,,我們一例子來說明問題:

例:將兩個(gè)給定的二進(jìn)制數(shù)(8位和16位)轉(zhuǎn)換為ASCII碼字符串。

分析:主程序提供唄轉(zhuǎn)換的數(shù)據(jù)和轉(zhuǎn)化后的ASCII碼字符串的存儲(chǔ)區(qū)的首地址,。子程序完成二進(jìn)制的轉(zhuǎn)換,。為了提高子程序的代碼轉(zhuǎn)換通用性,它可以完成8位或16位數(shù)的轉(zhuǎn)換,。設(shè)調(diào)用子程序時(shí),,入口參數(shù)為:被轉(zhuǎn)換的數(shù)在DX中,若位數(shù)小于16,,則從高到低存放,,轉(zhuǎn)換后的ASCII碼的存放首地址在DI中。下面給出一種實(shí)現(xiàn)方法:

DATA    SEGMENT    
   BIN1    DB  35H    
   BIN2    DW  0AB48H    
   ASCBUF  DB  20H DUP  (?)    
DATA    ENDS    
STACK1  SEGMENT PARA    STACK    
   DW  20H DUP  (0)    
STACK1  ENDS    
CODE    SEGMENT    
ASSUME  CS:CODE, DS:DATA, SS:STACK1    
BEGIN:  MOV AX, DATA    
   MOV DS, AX    
   XOR DX, DX    
   LEA DI, ASCBUF      ;存放ASCII碼的單元首地址送DI    
   MOV DH, BIN1            ;待轉(zhuǎn)換的第一個(gè)數(shù)據(jù)送DH    
   MOV AX, 8           ;待轉(zhuǎn)換的二進(jìn)制數(shù)的位數(shù)送AX    
   CALL    BINASC      
   MOV DX, BIN2    
   MOV AX, 16    
   LEA DI, ASCBUF    
   ADD DI, 8           ;設(shè)置下一個(gè)數(shù)的存放首地址    
   CALL    BINASC    
   MOV AH, 4CH    
   INT     21H    
BINASC  PROC    
   MOV CX, AX    
LOP:    ROL DX, 1           ;最高位移入最低位    
   MOV AL, DL    
   AND AL, 1           ;保留最低位,,屏蔽其他位    
   ADD AL, 30H    
   MOV [DI], AL            ;存結(jié)果    
   INC DI          ;修改地址指針    
   LOOP    LOP    
   RET    
BINASC  ENDP    
CODE    ENDS    
   END BEGIN


2,、用堆棧傳遞參數(shù)

這種方法是主程序先將入口參數(shù)壓入堆棧,子程序從堆棧中把參數(shù)讀出,,進(jìn)行加工處理,。這里要注意從堆棧中讀取數(shù)據(jù)與從堆棧中彈出數(shù)據(jù)是有區(qū)別的,從堆棧中讀取數(shù)據(jù)并不改變堆棧的棧頂指針SP,,而從堆棧中彈出的數(shù)據(jù),,則需修改SP,,在使用堆棧傳遞參數(shù)時(shí),要保證堆棧狀態(tài)的正確,。

我們還以上面的例子來說明下問題,,這次采用堆棧傳遞參數(shù)

分析:如果使用堆棧,一般用包括:

a,、在主程序中,,將待轉(zhuǎn)換的數(shù)據(jù)、存放ASCII碼的首地址和轉(zhuǎn)換的位數(shù)壓入棧中

b,、在子程序中保存信息

下面我們依然用程序說明問題,,在程序的必要處我已經(jīng)做了注釋

DATA    SEGMENT    
   BIN1    DB  35H    
   BIN2    DW  0AB48H    
   ASCBUF  DB  20H DUP  (?)    
DATA    ENDS    
STACK1  SEGMENT PARA    STACK    
   DW  20H DUP  (0)    
STACK1  ENDS    
CODE    SEGMENT    
ASSUME  CS:CODE, DS:DATA, SS:STACK1    
BEGIN:  MOV AX, DATA    
   MOV DS, AX    
   MOV AH, BIN1    
   PUSH    AX              ;待轉(zhuǎn)換數(shù)據(jù)壓棧    
   MOV AX, 8    
   PUSH    AX              ;待轉(zhuǎn)換位數(shù)壓棧    
   LEA DI, ASCBUF    
   PUSH    DI          ;存放ASCII碼的首地址壓棧    
   CALL    BINASC              ;調(diào)用轉(zhuǎn)換子程序    
   MOV AX, BIN2    
   PUSH    AX    
   MOV AX, 10H    
   PUSH    AX    
   ADD DI, 8    
   PUSH    DI    
   CALL    BINASC    
   MOV AH, 4CH    
   INT     21H    
BINASC  PROC    
   PUSH    AX    
   PUSH    CX    
   PUSH    DX    
   PUSH    DI      
   MOV BP, SP    
   MOV DI, [BP+10]         ;從堆棧取出入口參數(shù)    
   MOV CX, [BP+12]    
   MOV DX, [BP+14]    
LOP:    ROL DX, 1    
   MOV AL, DL    
   AND AL, 1    
   ADD AL, 30H    
   MOV [DI], AL    
   INC DI    
   LOOP    LOP    
   POP DI    
   POP DX    
   POP CX      
   POP AX    
   RET 6           ;返回并從堆棧中彈出6個(gè)字節(jié)    
BINASC  ENDP    
CODE    ENDS    
   END BEGIN

3、用地址表傳遞參數(shù)

當(dāng)要傳送的參數(shù)較多時(shí),,可在主程序中建立一個(gè)地址表,,在調(diào)用子程序前,把所有參數(shù)的地址依次存放在該地址表中,,然后把地址表的首地址通過寄存器傳送到子程序中去,,而在子程序中,按照地址表中給出的地址逐個(gè)取出參數(shù),,用地址表傳遞參數(shù)的方法,,在入口參數(shù)比較多時(shí)很方便,當(dāng)返回參數(shù)較多時(shí),,可用同樣的方法傳遞參數(shù),,供主程序使用。


本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章,、圖片,、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容,、版權(quán)和其它問題,請及時(shí)通過電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118,;郵箱:[email protected],。