匯編語言程序設計_第1頁
匯編語言程序設計_第2頁
匯編語言程序設計_第3頁
匯編語言程序設計_第4頁
匯編語言程序設計_第5頁
已閱讀5頁,還剩127頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第4章匯編語言程序設計匯編語言的特點:利用匯編語言可以設計出效率較高的核心底層程序,如設備驅動程序;用匯編語言編寫的程序一般比用高級語言編寫的程序執行得快,且占內存較少;匯編語言程序能夠直接有效地利用機器硬件資源,在一些實時控制系統中更是不可缺少和代替的;學習匯編語言是進行計算機應用系統設計的先決條件。匯編語言的應用70%以上的系統軟件是用匯編語言編寫的某些快速處理、位處理、訪問硬件設備等高效程序是用匯編語言編寫的某些高級繪圖程序、視頻游戲程序是用匯編語言編寫的匯編語言是我們理解整個計算機系統的最佳起點和最有效途徑主要內容:匯編語言源程序的結構匯編語言的語句與格式偽指令功能調用匯編語言程序設計4.1匯編語言源程序了解:計算機的三種語言源程序的結構匯編語言語句格式計算機設計語言機器語言匯編語言高級語言面向機器的語言機器語言匯編語言高級語言面向算法、過程或對象的語言匯編程序匯編語言源程序用助記符編寫源程序的編譯程序匯編程序匯編語言源程序機器語言目標程序匯編語言程序設計與執行過程輸入匯編語言源程序源文件.ASM匯編(編譯)目標文件.OBJ鏈接可執行文件.EXE調試最終程序匯編語言上機過程YYYNNN有錯

?有錯?有錯

?結束匯編輸入(修改)源程序連接運行查錯開始用EDIT,NOTEPAD等任何文本編輯器。源程序存為.ASM文件用MASM宏匯編程序進行匯編。匯編后生成.OBJ目標文件。命令格式:MASM<源文件名.ASM>;用LINK連接程序進行連接。連接后生成.EXE可執行文件。命令格式:LINK<目標文件名.OBJ>;用TD、DEBUG等調試程序進行調試。命令格式:TD<可執行文件名.EXE>數據段名SEGMENT…數據段名ENDS附加段名SEGMENT…附加段名ENDS堆棧段名SEGMENT…堆棧段名ENDS代碼段名SEGMENT…代碼段名ENDSEND

4.1.1匯編語言源程序的結構

匯編語言的語句有兩種:指令性語句——由8086指令助記符構成的語句指示性語句——由偽指令構成的語句指令性語句的格式為:[標號:]

[前綴]

指令助記符

[目的操作數,源操作數][;注釋]指示性語句的格式為:[名字]

偽指令

[操作數1,操作數2,…,操作數n][;注釋]

4.1.2匯編語言的語句與格式各部分之間至少要用一個空格作為分隔符指令性語句由CPU執行,每一條指令性語句都有一條機器碼指令與其對應;

指示性語句由匯編程序執行。它指出匯編程序應如何對源程序進行匯編,如何定義變量、分配存儲單元以及指示程序開始和結束等。指示性語句無機器碼指令與其相對應。

指令性語句匯編時生成機器碼;指示性語句匯編時不生成機器碼。語句的構成元素:標號——指令的符號地址,用來代表指令在存儲器中的地址。只能出現在指令性語句中,標號后應加上冒號。名字——段、過程、變量的名字,用來代表它們在存儲器中的地址。只能出現在指示性語句中,名字后不加冒號。指令助記符——8086助記符、偽指令操作數——即指令的操作對象對指令性語句——0,1,2個對指示性語句——根據需要而定操作數之間以逗號分隔操作數可以是:寄存器、存儲單元、常數或表達式

例如:AX,[DI+BX+10],200,16*8+TABLE,等等注釋——以分號開頭,可放在指令后,也可單獨一行。

注意注解的寫法。要寫指令(段)在程序中的作用,而不要寫指令的操作。

例如:以下為同一條指令寫的注釋

1)MOVCX,100;傳送100到CX2)MOVCX,100;循環計數器置初值顯然,第二種寫法要比第一種寫法要好。匯編語言的一個實例:hello.asm

dataSEGMENTHelloDB‘Hello,world!’,0DH,0AH,’$’dataENDSprogSEGMENTASSUME

CS:prog,DS:datastart:MOVAX,dataMOVDS,AX

LEADX,hello

;取字符串首地址

MOVAH,9INT21H ;顯示字符串

MOVAH,4CHINT21H ;退回DOSprogENDSENDstart名字標號寄存器存儲器單元常量變量或標號表達式4.1.3數據項與表達式常量數字常量字符串常量:用引號引起的字符或字符串例:‘A’,’ABCD’匯編時被譯成對應的ASCII碼41H,42H,43H,44H標號的屬性:

段地址:即標號所在段的段地址;

偏移量:標號所代表存儲單元的段內偏移地址;

類型:NEAR或FAR:

NEAR—表示標號所在語句與轉移指令/

調用指令在同一碼段內,跳轉時只需改變IP即可。

FAR—標號所在語句與轉移指令/調用指令不在同一代碼段內。

若沒有對類型進行說明,默認為NEAR。標號通常作為轉移指令或CALL指令的轉移地址。標號變量代表內存中的數據區,程序中視為存儲器操作數變量的屬性:段值變量所在段的段地址偏移量變量所在段的起始地址到變量地址之間的字節數類型字節型、字型和雙字型變量在程序中作為存儲器操作數被引用標號和變量名的使用規則組成:A-Z(不分大小寫),0-9,?@._$不能以數字開頭,圓點(.)只能作為首字符長度小于31個字符不能與保留字(指令助記符、偽指令、預定義符號等)重名不能重復定義例如:

正確的:LP1,AGAIN,NEXT,_GO,OK_1

錯誤的:4M,LOOP,AAA,#HELP,+ONE表達式表達式是常數、寄存器、標號、變量與運算符的組合。有數字表達式和地址表達式兩種。匯編時按優先規則對表達式進行計算,計算出具體的數值或地址。運行時不能改變。表達式中的運算符有6類:算術、邏輯、關系、取地址、屬性、其它類。算術運算符邏輯運算符關系運算符取值運算和屬性運算符其它運算符用于數字表達式,例:

MOVAX,4*1024匯編后的形式為:MOVAX,4096用于地址表達式,例:LEASI,TAB+3若TAB的偏移地址為1000H,則匯編后的形式為:

LEASI,[1003H]算術運算符——+、-、*、/,MOD邏輯運算符只能用于數字表達式中。例:MOV CL,36HAND0FH

經匯編后:MOVCL,06H注意,不要把邏輯運算符與邏輯運算指令混淆:例:ANDAX,3FC0HAND0FF00H

匯編后源操作數被翻譯為:3F00H,所以上述指令與ANDAX,3F00H等價。邏輯運算符——AND、OR、XOR、NOT關系運算的結果是一個邏輯值:真或假關系為真,結果為全1

關系為假,結果為全0例:MOVBX,PORTGT300H

若PORT的值大于300H,則匯編后為:

MOVBX,0FFFFH

否則匯編后為:

MOVBX,0關系運算符——EQ、NE、LT、GT、LE、GE取值運算符OFFSET取得其后變量或標號的偏移地址SEG取得其后變量或標號的段地址TYPE取變量的類型LENGTH取所定義存儲區的長度SIZE取所定義存儲區的字節數取值運算符例MOVAX,SEGDATAMOVDS,AXMOVBX,OFFSETDATA

LEABX,DATA等價于取值運算符例若BUFFER存儲區是用如下偽指令定義:

BUFFERDW200DUP(0)

則:

TYPEBUFFER 等于2LENGTHBUFFER 等于200SIZEBUFFER 等于400屬性運算符——PTR用來指定地址操作數的類型格式:<類型>PTR<地址操作數>

類型∈{BYTE,WORD,DWORD,NEAR,FAR}BYTE、WORD、DWORD

用于描述數據存儲單元(變量)地址NEAR、FAR

用于描述轉移、調用的目的地址例:MOV BYTEPTR[DI],0;字節類型

MOV WORDPTR[DI],0;字類型

MOV [DI],0B5H;類型不定PTR也可用來進行強制類型轉換例:STR1DW? ;STR1定義為字類型

MOV AX,STR1;合法

MOV AL,STR1;非法

MOVAL,BYTEPTRSTR1;合法其它運算符方括號

[]方括號中內容為操作數的偏移地址段重設符:段寄存器名:[]用于修改默認的段基地址4.2偽指令由匯編程序執行的“指令系統”用于定義變量、分配存儲區、定義邏輯段、指示程序開始和結束等常用偽指令數據定義偽指令符號定義偽指令段定義偽指令結束偽指令過程定義偽指令宏定義偽指令4.2.1數據定義偽指令用于定義數據區中變量的類型格式:[變量名]偽操作操作數[,…];注釋某些情況下可省略可選偽指令助記符DB定義的變量為字節型DW定義的變量為字類型(雙字節)DD定義的變量為雙字型(4字節)DQ定義的變量為四字型(8字節)DT定義的變量為10字節型DATA1DB11H,22H,33H,44HDATA2DW11H,22H,3344HDATA3DD11H*2,22H,33445566H以上變量在內存中的存放形式偽指令的性質決定所定義變量的屬性定義字符串必須用DB偽指令例:

DATA1DB‘ABCD’,66H‘A’‘B’‘C’‘D’41H42H43H44H66H重復操作符DUP為一個數據區的各單元設置相同的初值格式:

[變量名]偽指令助記符nDUP(初值,…)例:

DW20DUP(0)

DB3DUP(22H,11H,?)隨機數用?預留存儲空間MEM1DB34H,’A’,?,?,?MEM2DW20DUP(?)預留40個字節單元例:DATA_BDB10,5,10HDATA_WDW100H,-4DATA_DDD0FFFBH匯編后的內存分配情況如右圖所示。05H10H00H01HFCHFFHFBHFFH00H00H0AHDATA_BDATA_WDATA_D10510H100H-40FFFBH例:操作數可以是字符串,例如

STRDB ‘HELLO’匯編后的情況如圖:STR‘H’‘E’‘L’‘L’‘O’注意下面兩個定義的不同之處:DB ‘AB’ ;41H在低字節,42H在高字節DW‘AB’;42H在低字節,41H在高字節48H45H4CH4CH4FH例:TABLEDB10DUP(?)BUFFERDWTABLE,$+3設TABLE的偏移地址為0080H,則匯編后如下圖所示:BUFFER0080H80HTABLE008AH008BH008CH008DH...8FH00H00H0089H10Bytes4.2.2符號定義偽指令把一個表達式用一個符號表示,以后凡出現該表達式的地方都可用這個符號表示。符號定義偽指令有兩種:EQU,=用EQU定義的符號未清除前,不能重新定義。清除EQU定義可用PURGE偽指令。用”=”定義的符號可在任何時候進行重定義。二者均不占用存儲空間,僅是給符號賦值

例:FIVEEQU5

COUNTEQUCX

TENEQU10

DIST=BYTEPTR[SI+BP]GOTO=JMP…MOVAX,TENMOVCX,COUNTADDDIST,FIVEDIST=WORDPTR[SI+BP+1]ADDDIST,AX

GOTOLABEL定義引用4.2.3段定義偽指令說明邏輯段的起始和結束說明不同程序模塊中同類邏輯段之間的聯系形態匯編語言程序是按段來組織程序和數據的。和存儲器的物理段相對應,匯編語言程序中的段稱為邏輯段。匯編連接后被映射到物理段中。三類段:代碼(程序)、數據、堆棧段定義偽指令:SEGMENT、ENDS、ASSUME、ORG定義一個段的基本格式:

段名

SEGMENT

[定位類型][組合方式][類別]<匯編語言語句>

段名

ENDS這兩個偽指令總是成對出現,二者前面的段名應一致。SEGMENT說明了一個段的開始,ENDS說明了一個段的結束。對數據段和堆棧段,段中的語句一般是變量定義。對代碼段則是指令語句。如:dataSEGMENT<指令語句>dataENDSSEGMENT和ENDS偽指令ASSUME偽指令在代碼段中,還必須明確段和段寄存器的關系,這由ASSUME語句來指定。如

ASSUMECS:code,DS:data,ES:data

語句中的code和data為段名。這個語句說明:

1.CS將指向名字為code的代碼段

2.DS和ES將指向名字為data的數據段但要注意,ASSUME偽指令只是告知匯編程序有關段寄存器與段的關系,并沒有給段寄存器賦予實際的初值。故下面的語句

MOV AX,DATAMOV DS,AXMOV ES,AX將段基址裝入段寄存器。如果程序中用到堆棧段,則SS也需裝入實際的初值。代碼段基地址不需要程序員裝入CS寄存器,而由OS負責裝入。SEGMENT語句后可以帶有可選參數,用以規定邏輯段的其他一些屬性。1)定位類型說明如何確定邏輯段的邊界。有四種:PARA(Paragraph):

邏輯段從一個節(16個字節)的邊界開始。即段的起始地址應能被16整除,或這說段起始物理地址應為××××0H。——默認類型BYTE:

邏輯段從字節邊界開始,即段可以從任何地址開始。WORD:

邏輯段從字邊界開始。即段的起始地址必須是偶數。PAGE:

邏輯段從頁邊界開始。256字節稱為一頁,故段的起始物理地址應為×××00H。

2)組合類型說明不同模塊中同名段的組合方式。PUBLIC :

所有此類型的同名段組合成一個邏輯段,公用一個段地址,運行時裝入同一個物理段中。COMMON:

所有此類型的同名段具有相同的起始地址(覆蓋),共享相同的存儲區域。AT<數值表達式>:按絕對地址定位,段地址就是表達式的值。STACK:專用于說明堆棧段,組合方式同PUBLIC3)類別用單引號括起來的字符串。所有同類別的段被安排在連續的存儲區域中。如:在模塊1中有段定義:

seg1SEGMENTPARASTACK‘stack’…seg1ENDS

在模塊2中有段定義:

seg2SEGMENTPARASTACK‘stack’…seg2ENDS則連接時這兩個段被安排在一起。位置計數器$表示當前位置的計數器匯編程序每掃描一個字節,位置計數器的值加1

如:TOPEQU$-STACKJMP$ORG規定了段內的指令或數據存放的開始地址(偏移地址的初值),其格式為:

ORG<表達式>表達式的值即為開始地址,從此地址起連續存放程序或數據。例:ABCSEGMENTORG100Hbegin:……ABCENDS定位偽指令ORG指令從100H開始存放4.2.4匯編結束偽指令END匯編語言源程序的最后,要加匯編結束偽指令END,以使匯編程序結束匯編。格式:END

[表達式]END后跟的表達式通常就是程序第一條指令的標號,指示程序的啟動地址(要執行的第一條指令的地址)。4.2.5過程定義偽指令用于定義一個過程體格式:過程名PROC[NEAR/FAR]

RET

過程名ENDP過程入口的符號地址過程的類型有兩種:

NEAR——(默認類型)表示段內調用

FAR——表示段間調用

調用一個過程的格式為:

CALL

<過程名>4.2.6宏定義偽指令如果需要多次使用同一個程序段,可以將這個程序段定義為一個”宏指令”,然后在需要時,可簡單地用宏指令名來代替這個程序段。指令的格式為:<宏指令名>MACRO

[形參表]<宏定義體>

ENDM例:兩個數之和的宏定義和宏調用。宏定義為:DADDMACROX,Y,ZMOVAX,XADDAX,YMOVZ,AXENDMX、Y、Z是形式參數。調用宏DADD時可寫為:

DADD

DATA1,DATA2,SUMDATA1,DATA2,SUM是實際參數,由它們替換定義中的X、Y、Z。宏調用與過程(子程序)調用都是一次定義,多次調用。它們之間的差別是:①執行形式:宏命令偽指令由宏匯編程序在匯編過理中進行處理,而CALL、RET則是由CPU執行的指令。②匯編結果:宏命令偽指令匯編后被展開。③執行速度:宏命令執行速度較快(因無調用轉移)④

占用內存:宏指令簡化了源程序,但不能簡化目標程序,并不節省內存單元。使用過程可以節省代碼占用的內存空間。宏展開:匯編程序會把宏調用按宏定義展開。例如:宏定義為:

DISPLAYMACROstringLEADX,stringMOVAH,9INT21H

ENDM

程序中宏調用:

……DISPLAYERROR_MESSAGEDISPLAYEXIT_MESSAGE……

匯編后的結果:(帶有+號的指令為宏展開后的結果)……+LEADX,ERROR_MESSAGE+MOVAH,9+INT21H+LEADX,EXIT_MESSAGE+MOV AH,9+INT21H……一個完整源程序結構例DSEGSEGMENTDATA1DB1,2DATA2DW1234HDSEGENDSESEGSEGMENT

DB20DUP(?)ESEGENDSSSEGSEGMENT

STACK

‘STACK’

DB200DUP(?)SSEGENDSCSEGSEGMENT

ASSUMECS:CSEG,DS:DSEG,ES:ESEG,SS:SSEGSTART:MOVAX,DSEGMOVDS,AXMOVAX,ESEGMOVES,AXMOVAX,SSEGMOVSS,AX┇CSEGENDSENDSTART源程序代碼段寄存器賦初值習題1.下列語句在存儲器中分別為變量分配多少字節空間?并畫出存儲空間的分配圖。VAR1 DB 10,2VAR2 DW 5DUP(?),0VAR3 DB ‘HOWAREYOU?’,‘$’VAR4 DD -1,1,02.假定VAR1和VAR2為字變量,LAB為標號,試指出下列指令的錯誤之處。(1)ADD VAR1,VAR2 (2)SUB AL,VAR1(3)JMP LAB[SI] (4)JNZ VAR13.對于下面的符號定義,指出下列指令的錯誤。

A1 DB ?

A2 DB 10 K1 EQU 1024

(1)MOV K1,AX

(2)MOV A1,AX

(3)CMP A1,A2

(4)K1 EQU 20484.3功能調用DOS功能調用高級調用,操作系統提供BIOS功能調用低級調用DOS功能調用包含多個子功能的功能包,用軟中斷指令調用,中斷類型碼固定為21H各子功能采用功能號來區分調用格式:

MOVAH,功能號

<置相應參數>INT21HDOS系統功能調用的使用方法如下:① AH←功能號;② 設置該功能所要求的其他入口參數;執行INT21H指令;分析出口參數。1.DOS鍵盤功能調用(1)從鍵盤輸入一個字符(功能號=1)

MOVAH,1INT21H輸入的字符在AL中功能:等待從鍵盤輸入一個字符并將輸入字符的ASCII碼送入AL中,同時在顯示器上顯示該字符入口參數:無出口參數:AL=鍵入的ASCII碼字符單字符輸入例GET_KEY:MOV AH,1

INT 21H

CMP AL,’Y’ JZ YES CMP AL,’N’ JZ NO JNZ GET_KEY

YES:┇ NO:┇交互式應答程序(2)輸入字符串(功能號=0AH)MOVAH,

0AH

LEADX,<字符串緩沖區首地址>INT21H功能:從鍵盤輸入一串字符并把它存入用戶指定的緩沖區中入口參數:DS:DX指向緩沖區首地址出口參數:輸入的字符串及字符個數

DS:DX字符串在內存中的存放地址定義字符緩沖區用戶自定義緩沖區格式:0DHN1N2整個緩沖區最大鍵入字符數實際鍵入字符數若用戶鍵入的字符數(包括回車)≥定義的N1,本功能調用將不再接收新的鍵入,且光標不再向右移動。例:設在數據段定義鍵盤緩沖區如下:

STR1DB10,?,10DUP(?)

調用DOS功能的0AH號功能的程序段為:

LEADX,STR1MOVAH,0AHINT21H

此程序段最多從鍵盤接收10個按鍵(包括回車)。2.DOS顯示功能調用(1)在顯示器上顯示一個字符(功能號=2)MOVAH,2MOVDL,<要顯示的字符>INT21H

例:在顯示器上顯示一個字符‘A’MOVAH,2MOVDL,’A’;或MOVDL,41HINT21H

DL=待顯示字符的ASCII碼

MOVAH,9LEADX,<字符串>INT21H功能:在顯示器上顯示以‘$’(24H)為結束符的字符串,若顯示的字符串要求回車換行,可在字符串中加入0DH,0AH控制碼入口參數:DS:DX指向字符串首地址出口參數:無(2)顯示字符串(功能號=9)被顯示的字符串必須以‘$’結束例:在屏幕上顯示:’HELLO,WORLD!’;在數據段定義字符串:

DATASEGMENTSTR1DB‘HELLO,WORLD!$’DATAENDS;在代碼段中進行顯示輸出

MOVAH,9LEADX,STR1INT21H完整的程序:HELLO.ASM附:BIOS功能調用BIOS:基本輸入輸出系統,是固化在EPROM中的一組實現基本輸入輸出功能的子程序。BIOS調用通過多個軟中斷提供,調用方法為:

MOVAH,<功能號> <設置入口參數,一般將參數放在寄存器中> INT <中斷類型>

BIOS中的幾個主要中斷類型如下:

INT10H——屏幕顯示

INT13H——磁盤操作

INT14H——串行口操作

INT16H——鍵盤操作

INT17H——打印機操作 每類中斷由包含許多子功能,調用時通過功能號指定。4.4匯編語言程序設計4.4.1概述1.程序質量(P170)2.匯編語言程序設計的步驟:

1-根據實際問題抽象出數學模型,確定算法

2-畫出程序框圖(流程圖)3-分配內存工作單元和寄存器

4-根據框圖編寫源程序,存成.ASM文件

5-對源程序匯編,生成.OBJ目標文件

6-把.OBJ文件連接成.EXE執行文件

7-運行、調試3.源程序的基本結構:順序、分支、循環、過程

(1)用方框表示工作框,框中用簡明語言標明要完成的功能(2)用菱形框表示判斷框

框中標明比較、判斷和條件如何繪制程序框圖(流程圖)?NY?(4)各框之間用直線連起來表示程序走向。框中標明子程序名字(入口參數等)(3)用

框表示調用子程序或過程。4.4.2順序程序設計順序結構是最常見、最基本的程序結構CPU按照指令的排列順序逐條執行。語句A語句B語句C程序的執行順序就是指令的編寫順序例實現C=A+B,設A,B,C均為字變量。DATASEGMENTADW5F73HBDW98CDHCDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVAX,AADDAX,BMOVC,AXMOVAH,4CHINT21HCODEENDSENDSTART標號:條件滿足?語句A4.4.3分支程序設計分支結構是指包含條件轉移或無條件跳轉指令的程序。分支結構具體分為單分支、雙分支、多分支結構NYIF…THEN結構程序結構:

測試/比較指令(TEST/CMP)

條件轉移指令(Jx

標號)

處理體

標號:其他指令

…單分支程序結構:

TEST/CMP指令

Jx

標號1

處理體P1JMP標號2標號1:

處理體P2標號2:其他指令

…條件滿足?語句A語句B標號1:標號2:條件1條件2IF…THEN…ELSE結構雙分支若條件成立,則執行A,否則執行B標號1:條件1成立?P1NYCASE結構程序結構:

…TEST/CMP指令(測試條件1)

Jx

標號1;不滿足轉標號1

處理體P1…JMP標號n+1標號1:TEST/CMP指令(測試條件2)

Jx

標號2;不滿足轉標號2

處理體P2…JMP標號n+1標號2:TEST/CMP指令(測試條件3)

Jx

標號3;不滿足轉標號3

處理體P3…JMP標號n+1標號3:TEST/CMP指令(測試條件4)

……標號n+1:(公共出口)條件2成立?條件n成立?…Pn+1標號2:標號n:標號n+1:P2PnNNYY例:將1字節的二進制數以十六進制數顯示出來

DATASEGMENTADW5FHDATAENDSCODESEGMENT

ASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVDL,AMOVCL,4SHRDL,CLADDDL,30H;0~9加30H,A~F加37HCMPDL,’9’JBENEXT1ADDDL,7NEXT1:MOV

AH,2

INT21H

MOVDL,AANDDL,0FHADDDL,30HCMPDL,’9’JBENEXT2ADDDL,7NEXT2:INT21HMOVAH,4CHINT21HCODEENDS

ENDSTART單分支程序設計例:在某串中查找某個特定字符,找到顯示’Y’,未找到顯示’N’

REPNESCASBJZFOUND

MOVDL,’N’JMPDISPFOUND:MOV

DL,’Y’DISP:MOVAH,2INT21H

MOVAH,4CHINT21HCODEENDS

ENDSTARTDATASEGMENTSTRINGDB‘Howareyou!welcometochina!’NEQU$-STRINGDATAENDSCODESEGMENT

ASSUMECS:CODE,ES:DATASTART:MOVAX,DATAMOVES,AXLEADI,STRINGMOVCX,NCLDMOVAH,1INT21H雙分支程序設計4.4.4循環程序設計1.DO…UNTIL<條件>結構先執行,再判斷條件。工作部分至少執行一次。初始化循環體循環控制繼續循環?YN包含循環執行某一段指令序列的程序2.DOWHILE<條件>結構先判斷條件,再執行。工作部分有可能一次都不執行。初始化循環體循環控制繼續循環?YN循環結構的組成部分:循環初始化部分—初始化循環控制變量、循環體所用到變量;循環體部分—循環結構的主體,即要求重復執行得程序段部分,包括循環工作部分和循環控制部分;循環結束條件—在循環程序中必須給出循環結束條件,否則就會進入死循環。循環結束條件:用計數器控制循環按問題的條件控制循環用開關量控制循環有些情況下,在循環體內又嵌套了循環,這種結構成為多重循環。多重循環常用于軟件延時程序或二維數組處理例:統計字變量VAL中0和1的個數,并將統計結果分別送字單元X和Y中。

MOVCX,16MOVSI,0MOVDI,0MOVAX,VALAGAIN:SHLAX,1JCNOZEROINCSIJMPNEXTNOZERO:INCDINEXT:LOOPAGAINMOVX,SIMOVY,DI掌握以下幾點:調用子程序用CALL指令,返回調用程序用RET指令。子程序允許嵌套調用。進入子程序后首先要保護主程序的運行狀態(標志位)和使用的寄存器內容(稱為保護現場),退出子程序前要恢復現場。調用前要預先確定子程序中要使用哪些寄存器,并定義入口參數和出口參數。參數傳遞可利用寄存器、存儲單元或堆棧(要用BP尋址)。4.4.5子程序設計對于一個子程序,應該注意它的入口參數和出口參數。入口參數—由主程序傳給子程序的參數出口參數—子程序運算完傳給主程序的結果參數傳遞的方法:利用寄存器。把所需傳遞的參數直接放在主程序的寄存器中傳遞給子程序。利用存儲單元。主程序把參數放在公共存儲單元,子程序則從公共存儲單元取得參數。利用堆棧。主程序將參數壓入堆棧,子程序運行時則從堆棧中取參數。例:編寫一個將單字節的二進制數轉換成BCD碼數的程序,再將對應的十進制數轉換成ASCII碼字符串,在顯示器上顯示出來。分析:設單字節二進制數存放在NUMBIN單元。利用除法實現轉換:將該數除以100,商即為BCD碼數的百位,保留第一步所得余數。將①所得余數再除以10,商即為BCD碼數的十位,余數即為BCD碼數的個數將BCD碼數的百位、十位和個位分別加上30H,即為它們的ASCII碼將ASCII碼字符串存入一個緩沖區,然后調用DOS功能調用INT21H的09H號功能即可顯示該字符串。程序如下:DATASEGMENTNUMBINDB0E7H;待轉換的單字節二進制數STRINGDB10DUP(20H);定義顯示緩沖區,初值全為空格20HDB0DH,0AH;定義回車換行符

DB$;定義結束符DATAENDSSTACKSEGMENTPARASTACK‘STACK’DB100DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKSTARTPROCFARBEGIN:PUSHDS;DS中包含的是程序段前綴的起始地址

MOVAX,0PUSHAX;設置返回至DOS的段值和偏移量

MOVAX,DATAMOVDS,AX;置段寄存器初值

LEADI,STRINGXORAH,AH;AH清零

MOVAL,NUMBINMOVBL,100DDIVBL;AX除以BL,商在AL中,余數在AH中

CALLBCDTOASC;調用轉換程序,入口參數:AL=BCD數

MOVAL,AH;取余數送ALXORAH,AHMOVBL,10DDIVBL

CALLBCDTOASCMOVAL,AHCALLBCDTOASCCALLDISPASC;調用顯示程序

RETSTARTENDPBCDTOASCPROC;BCD碼到ASCII碼轉換程序

ADDAL,30HMOV[DI],AL;保存ASCII字符

INCDI;指向下一個單元

RETBCDTOASCENDPDISPASCPROC;顯示子程序

LEADX,STRING

MOVAH,09HINT21HRETDISPASCENDPCODEENDSENDBEGIN1.碼制轉換十、二進制數、ASCII碼之間的互相轉換。①BCD數→二進制數算法:Dn-1*10n-1+……+D0*100

=(…(Dn-1*10+Dn-2)*10+…)*10+D0=(…((0*10+Dn-1)*10+Dn-2)*10+…)*10+D0

即:新的中間結果=中間結果*10+本位數字

(中間結果初值為0)4.5常見程序設計舉例例:將≤65535的非壓縮BCD數轉換成二進制數。

;數據段定義

mydataSEGMENT

decnumDB5,3,0,1,9;BCD數53019

binnumDW?

mydataENDSprogSEGMENT

ASSUMECS:prog,DS:mydatabegin: MOVAX,mydata MOVDS,AX

MOVSI,OFFSETdecnum MOVCX,5;5位BCD數

MOVBX,10

XORAX,AX;中間結果初始值為0Next: MULBX;中間結果*10+本位數字

ADDAL,[SI]ADCAH,0

INCSI;指向下位BCD數

LOOPnextMOVbinnum,AX;保存結果

MOVAH,4CHINT21Hprog ENDS

ENDbegin例:把≤255的非壓縮BCD數轉換成2進制數

decnumDB1,5,9;BCD數159

binnumDB? ……MOVAX,decnumXCHGAH,AL;百位在AH,十位在ALAAD;百位數*10+十位數

MOVAH,AL;中間結果送AHMOVAL,decnum+2AAD;中間結果*10+個位數

MOVbinnum,AL……例:從鍵盤輸入兩個整數,并求其和。因鍵入為整數,故要進行如下轉換:

ASCII→BCD→二進制數

ASCII→BCD碼很簡單,高4位清零即可得到非壓縮的BCD碼。

BCD→二進制數在本例中采用用以下方法:

((((0+千位數)*10+百位數)*10)+十位數)*10+個位數②ASCII碼→二進制數(用于輸入)第一次中間結果第二次中間結果第三次中間結果最終結果開始兩個數分別轉換成二進制數鍵入兩個數相加結束返回DOS如有溢出則提示開始取第一個ASCII碼是負號嗎?數字符個數-1,指針+1指針定位字符個數-1=0?取數字,與中間結果相加,再乘以10指向下一個數字字符加個位數是負數則求補存結果結束NYYN轉換子程序程序如下:DATA SEGMENTSTR1 DB10,?,10DUP(?);第1個數的輸入緩沖區

STR2 DB10,?,10DUP(?);第2個數的輸入緩沖區

NUM DW?,? ;存轉換后的二進制數SUM DW0 ;存和OVER DB‘Overflow!’,13,10,’$’DATA ENDS;CODE SEGMENT ASSUMECS:CODE,DS:DATAMAIN PROC FARSTART:MOV AX,DATA MOV DS,AX MOV AH,0AH LEA DX,STR1 INT 21H ;輸入第一個數字串(設為26) MOV AH,0AH LEA DX,STR2 INT 21H ;輸入第二個數字串(設為33) LEA BX,STR1;串1的首地址送BX LEA DI,NUM;存二進制首地址送DI CALL CHANGE;將串1ASCII碼→二進制

LEA BX,STR2;串2的首地址送BX

LEA DI,NUM+2 ;指向

CALL CHANGE ;將串2ASCII碼→二進制

MOV AX,NUM;(AX)=[NUM]=001AH ADD AX,NUM+2 ;兩數相加,(AX)=003BH MOV SUM,AX ;存和

JNO NEXT ;無溢出,轉NEXT LEA DX,OVER MOV AH,9 INT 21H ;顯示’Overflow!’NEXT: MOV AH,4CH INT 21H ;返回DOS MAIN ENDPCHANGE PROC MOV CL,[BX+1] ;實際字符數送CL MOV AL,[BX+2] ;第一個字符送AL MOV CH,AL ;暫存在CH CMP AL,’-’ ;第一個字符是負號嗎? JNZ NEXT1 ;不是,轉NEXT1 DEC CL ;字符數減1 INC BXNEXT1:ADD BX,2 ;指向第一個數字字符

MOV AX,0 ;清零AX,存二進制數LP1:DEC CL JZ NEXT2 ;若(CL)=0,轉NEXT2 MOV DL,[BX];取字符

AND DL,0FH ;轉換成BCD碼

ADDAL,DL;加到中間結果上

ADCAH,0

MOVDX,10MULDX;*10INCBX;指向下一個字符

JMPSHORTLP1NEXT2:MOVDL,[BX];取個位數

ANDDL,0FH;個位ASCII→未組合BCDADDAX,DX;加個位數,(AX)=001AHCMPCH,’-’;是’-’?JNZNEXT3;該數非負,轉NEXT3NEGAX;若為負,求補NEXT3:MOV[DI],AX;存二進制結果

RETCHANGEENDP;CODEENDSENDSTART020A32360D…020A33330D…001A21003B00STR1STR2NUMSUM10個10個‘O’……OVER??040A313234…STR1若鍵入‘1234’330D‘1’‘2’‘3’‘4’…設鍵入第1個數為26,第2個數為33,則在內存各變量分配如下:重點掌握:

如何從鍵盤輸入一個字符串

ASCII→未組合BCD→二進制有符號數的運算,對負數和溢出如何處理方法1

計算二進制數中所包含的1000的個數、100的個數、10的個數和1的個數。方法2

除10取余。下面舉例介紹第一種方法。流程圖如下:③二進制數→BCDYN二進制數

AX令(DL)=0(AX)-1000<0?(DL)+1(AX)+1000(AX)DL存至緩沖區令(DL)=0YN(AX)-10<0?(DL)+1(AX)+10(AX)存DL存AL返回DOS求100的個數,結構同上A匯編程序如下:DATA SEGMENTBNUM DB 270FHDNUM DB 4DUP(?);存放BCD碼的緩沖區DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATABINBCD PROC FARBEGIN:MOV AX,DATA MOV DS,AX MOV AX,BNUM;取二進制數

LEA BX,DNUM;BCD碼緩沖區首地址送BX

;計算百位的個數

MOVDL,0;千位的個數計數器AGAIN1:SUBAX,1000;(AX)-1000JCNEXT1;若≤0,則退出循環

INCDL;(DL)+1JMPAGAIN1NEXT1:ADDAX,1000;(AX)←(AX)+1000 MOV[BX],DL;存千位的個數

;計算百位的個數

MOVDL,0;百位的個數計數器AGAIN2:SUBAX,100;(AX)-100JCNEXT2INCDLJMPAGAIN2NEXT2:ADDAX,100MOV[BX+1],DL;存百位的個數

MOVDL,0;十位的個數計數器AGAIN3:SUBAX,10;(AX)-10JCNEXT3INCDL JMPAGAIN3NEXT3:ADDAX,10MOV[BX+2],DL;存十位的個數

MOV[BX+3],AL;存個位的個數

MOVAH,4CHINT21HBINBCDENDP;CODEENDS ENDBEGIN④BCD→ASCII

⑤二進制串轉換為ASCII碼一個二進制位串若要送顯示或打印,需把串中每一位(0或1)化為ASCII碼。思路:先將目標串全部預置為30H,再把每個二進制位逐位左移至CF,然后判CF=0?若是,取下一位;若不是,將31H送此單元。

流程圖如下:初始化用’0’填滿串取要轉換的數左移1位存入‘1’結束CF=1?轉換完?調整指針NN匯編程序如下:DATA SEGMENTNUM DW 6F78HSTRING DB 16DUP(?)DATA ENDS;CODE SEGMENT ASSUMECS:CODE,DS:DATABINCA PROC FARBEGIN: MOV AX,DATA MOV DS,AX MOV ES,AX CLD LEA DI,STRING MOV CX,16;串的長度

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論