




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第4章
匯編語言程序設(shè)計(jì)4.1分支程序結(jié)構(gòu)4.2循環(huán)程序結(jié)構(gòu) 4.3子程序結(jié)構(gòu)4.4Windows應(yīng)用程序編程4.5與C++語言的混合編程2教學(xué)重點(diǎn)三種結(jié)構(gòu)程序設(shè)計(jì)①順序結(jié)構(gòu)②分支結(jié)構(gòu)③循環(huán)結(jié)構(gòu)
知識(shí)點(diǎn)4.1匯編語言的格式4.2語句行的構(gòu)成4.3指示性語句4.4指令語句4.5匯編語言程序設(shè)計(jì)及舉例匯編是把匯編語言程序翻譯成機(jī)器語言描述的目標(biāo)程序的過程。匯編程序是完成匯編任務(wù)的程序。用匯編語言編寫的程序。2.匯編程序連接程序的主要功能是把多個(gè)目標(biāo)文件及庫文件連接在一起形成可執(zhí)行文件。3.連接程序
1.匯編語言源程序匯編語言源程序匯編目標(biāo)程序連接可執(zhí)行程序從匯編語言源程序到可執(zhí)行程序的生成過程如圖所示。4.1匯編語言源程序格式下面是一個(gè)示范性的完整的匯編語言源程序。;lt301b.asm(文件名)stack segmentstack ;定義堆棧段
dw512dup(?) ;堆棧段有512字(1024字節(jié))空間stack ends ;堆棧段結(jié)束data segment ;定義數(shù)據(jù)段string db’Hello,Everybody!’,0dh,0ah,’$’data endscode segment’code’ ;定義代碼段
assumecs:code,ds:data,ss:stackstart: movax,data ;建立DS段地址
movds,ax movdx,offsetstring movah,9 int21h movax,4c00h int21h ;利用功能調(diào)用返回DOScode ends ;代碼段結(jié)束
endstart;匯編結(jié)束匯編語言源程序格式完整的匯編語言源程序由若干個(gè)段組成源程序中段的數(shù)目可以根據(jù)實(shí)際需要而定,但其中必不可少的是代碼段每個(gè)段由若干個(gè)語句行構(gòu)成匯編語言源程序格式NAME1SEGMENT
語句語句NAME1ENDSNAME2SEGMENT
語句
語句NAME2ENDSEND<標(biāo)號(hào)>.........匯編語言源程序語句行的格式匯編語言源程序中的每個(gè)語句行可以由四項(xiàng)組成,格式如下:若操作數(shù)項(xiàng)有多個(gè)操作數(shù),則操作數(shù)之間使用逗號(hào)分隔各部分之間至少用一個(gè)空格作為間隔[名字]操作碼[操作數(shù)][;注釋]帶方括號(hào)的項(xiàng)是可選項(xiàng)名字項(xiàng)名字項(xiàng)是指一個(gè)標(biāo)號(hào)、變量、段名或過程名等。操作碼項(xiàng)操作碼項(xiàng)是一個(gè)操作碼的助記符,它可以是指令、偽指令或宏指令名。操作數(shù)項(xiàng)操作數(shù)項(xiàng)提供為執(zhí)行所要求的操作而需要的信息。操作數(shù)項(xiàng)可以是常數(shù)、寄存器、標(biāo)號(hào)、變量或由表達(dá)式組成。注釋項(xiàng)注釋項(xiàng)用來說明程序或語句的功能。";"為識(shí)別注釋項(xiàng)的開始。";"也可以從一行的第一個(gè)字符開始,此時(shí)整行都是注釋,常用來說明下面一段程序的功能。
在調(diào)試程序過程中可適當(dāng)使用“;”4.2語句行的構(gòu)成4.2.1標(biāo)記1、IBM宏匯編的字符集(1)字母大寫字母小寫字母(2)數(shù)字0、1……9(3)特殊字符圖4-12、界符圖4-2語句中有了界符,可以不用分隔符。3、常量常量是指匯編時(shí)已經(jīng)有確定數(shù)值的量它又分成多種形式:(1)十進(jìn)制常量(2)十六進(jìn)制常量(3)二進(jìn)制常量(4)八進(jìn)制常量(5)字符串常量用單引號(hào)或雙引號(hào)括起來的單個(gè)字符或多個(gè)字符,其數(shù)值是每個(gè)字符對(duì)應(yīng)的ASCII碼的值例如:'d''AB''Hello,Everybody!'字符串常量標(biāo)識(shí)符(Identifier)一般最多由31個(gè)字母、數(shù)字及規(guī)定的特殊符號(hào)(如_、$、?、@)組成,不能以數(shù)字開頭。一個(gè)程序中,每個(gè)標(biāo)識(shí)符的定義是唯一的,還不能是匯編語言采用的保留字4、標(biāo)識(shí)符由程序員自由建立的、有特定意義的字符序列。5、保留字保留字(ReservedWord)是匯編程序已經(jīng)利用的標(biāo)識(shí)符,主要有:指令語句助記符——例如:MOV、ADD偽指令語句助記符——例如:DB、EQU操作符——例如:OFFSET、PTR寄存器名——例如:AX、CS第3章IBM宏匯編中的保留字見P86表4-16、注釋以“;”打頭。4.2.2符號(hào)1、寄存器一種標(biāo)識(shí)符,要符合標(biāo)識(shí)符的組成規(guī)則。2、變量存放在存儲(chǔ)單元中的操作數(shù)是變量。在程序中出現(xiàn)的是存儲(chǔ)單元地址的符號(hào)。變量名變量名是數(shù)據(jù)存儲(chǔ)單元偏移地址的符號(hào)表示命名規(guī)則:
遵守標(biāo)識(shí)符的命名規(guī)則變量的屬性變量具有以下三種屬性:①段值名字對(duì)應(yīng)存儲(chǔ)單元的段地址②偏移值名字對(duì)應(yīng)存儲(chǔ)單元的偏移地址③類型變量名的類型可以是BYTE(字節(jié))、WORD(字)和DWORD(雙字)等變量的定義變量一般在除代碼段以外的其他段定義。變量需定義才能被引用變量用數(shù)據(jù)定義語句DB、DD等定義3、標(biāo)號(hào)標(biāo)號(hào)是指令存儲(chǔ)單元偏移地址的符號(hào)表示命名規(guī)則:
遵守標(biāo)識(shí)符的命名規(guī)則標(biāo)號(hào)的屬性標(biāo)號(hào)具有以下三種屬性:①段值標(biāo)號(hào)對(duì)應(yīng)存儲(chǔ)單元的段地址②偏移值標(biāo)號(hào)對(duì)應(yīng)存儲(chǔ)單元的偏移地址③類型標(biāo)號(hào)類型可以是NEAR(近)和FAR(遠(yuǎn)),分別表示段內(nèi)或段間標(biāo)號(hào)的定義和引用標(biāo)號(hào)在代碼段定義和引用LOOP1:MOVAL,[SI]...JMPLOOP1標(biāo)號(hào)定義標(biāo)號(hào)引用變量和標(biāo)號(hào)的區(qū)別不同:標(biāo)號(hào)對(duì)應(yīng)的存儲(chǔ)單元中存放的是指令,后面跟冒號(hào);變量對(duì)應(yīng)的存儲(chǔ)單元中存放的是數(shù)據(jù),后面不跟冒號(hào)。相同:都是存儲(chǔ)單元的符號(hào)地址。4、數(shù)利用一個(gè)標(biāo)識(shí)符表達(dá)的一個(gè)數(shù)值常數(shù)若使用有意義的符號(hào)名來表示,可以提高程序的可讀性,同時(shí)更具有通用性符號(hào)常量實(shí)例符號(hào)定義
DosWriteChar=2 CarriageReturn=13符號(hào)應(yīng)用(右邊程序段等價(jià)左側(cè)的符號(hào)形式)
movah,DosWriteChar;movah,2 movdl,CarriageReturn;movdl,135、其他符號(hào)指示性語句(偽指令)的操作碼、宏指令等
匯編語言大小寫不敏感4.2.3表達(dá)式后面介紹4.2.4語句匯編語言源程序中的語句有兩種:指令語句和指示性語句(偽指令)。指令語句——使CPU產(chǎn)生動(dòng)作、并在程序執(zhí)行時(shí)才處理的語句,就是第3章學(xué)習(xí)的指令偽指令(Directive)——不產(chǎn)生CPU動(dòng)作、在程序執(zhí)行前由匯編程序處理的說明性語句,例如,數(shù)據(jù)說明、變量定義等等兩種語句的格式標(biāo)號(hào):
指令語句助記符操作數(shù),操作數(shù);注釋名字偽指令助記符參數(shù),參數(shù),…
;注釋指令語句格式:偽指令格式:兩種語句在格式上的主要區(qū)別4.3指示性語句(偽指令語句)符號(hào)定義語句數(shù)據(jù)定義語句段定義語句過程定義語句結(jié)束語句4.3.1符號(hào)定義語句EQU=PURGE1、等值語句EQU語句格式:符號(hào)名EQU表達(dá)式功能:給符號(hào)名定義一個(gè)值,或定義為別的符號(hào)名,甚至可以定義為一條可執(zhí)行的指令。如:ABCEQU220XYZEQUABCCOUNTEQUCXCBDEQUADDEQU語句在未解除之前,不能重新定義。如:ABCEQU220ABCEQU330錯(cuò)誤!2、解除語句PURGE功能:用來解除已用EQU語句定義的符號(hào),解除后的符號(hào)可以重新定義。如:PURGEABCABCEQU330PURGE的格式為:PURGE符號(hào)1,符號(hào)2,...,符號(hào)n3、等號(hào)語句=語句格式:符號(hào)名=表達(dá)式功能:與EQU語句類似,但是能對(duì)符號(hào)進(jìn)行重新定義。如:EMP=6EMP=7EMP=EMP+14.3.2數(shù)據(jù)定義語句格式:[變量名]偽操作符操作數(shù)1,操作數(shù)2,...[;注釋]功能:定義一個(gè)變量的類型,給存儲(chǔ)器賦初值,或者僅僅給變量分配存儲(chǔ)單元,而不賦予特定的值。變量名可以沒有。這種情況,匯編程序?qū)⒅苯訛椴僮鲾?shù)分配空間,無符號(hào)地址。設(shè)置變量名是為了方便存取它指示的存儲(chǔ)單元匯編程序?qū)阉x的數(shù)據(jù)按先后次序連續(xù)分配存儲(chǔ)空間,所起的名字也只代表第一個(gè)字節(jié)單元的偏移地址。常用偽操作符DB(DefineByte)定義字節(jié)DW(DefineWord)定義字DD(DefineDoubleWord)定義雙字DQ(DefineQuadword)定義四個(gè)字DT(DefineTenbyte)定義十個(gè)字節(jié)操作數(shù)可以是常數(shù)、表達(dá)式、字符串或重復(fù)操作符DUP,不能是寄存器名.例1DATASEGMENTDATA_BYTEDB10,4,10H,?DATA_WORDDW100,100H,-5DATA_DWDD3*20,0FFFDHDATA_ASCDB‘AB’DATA_WORD1DW‘AB’DATAENDS說明:(1)操作數(shù)?,不放入任何數(shù),僅保留存儲(chǔ)空間.(2)操作數(shù)在內(nèi)存中所占的字節(jié)數(shù)與偽操作符所定義的字節(jié)數(shù)一致.(3)操作數(shù)在匯編后以補(bǔ)碼形式存放.(4)只有用DB定義時(shí),才允許字符串的長(zhǎng)度超過2個(gè)字節(jié)。DATA_BYTE0AH04H10H---64HDATA_WORD00H00H01HFBHFFHDATA_DW3CH00H00H00HFDH00HFFH00HDATA_ASC41H42H42H0000H0001H0002H0013H000AH0003H0004H0005H0006H0007H0008H0009H000BH000CH000DH000EH000FH0010H0011H0012H0014H41H0015HDATA_WORD1例2DATASEGMENTADWMBUFDWBUF-A
EMPEQU220
MDB2DUP(1),2DUP(2,2DUP(1,2))DDDBUFDATAENDS說明:(1)操作數(shù)為變量時(shí),則存放其地址。若用DW定義,則存放其偏移地址;若用DD定義,則存放其偏移地址和段地址,第一個(gè)字為偏移地址,第二個(gè)字為段地址.(2)重復(fù)操作符DUP可以嵌套.重復(fù)操作符DUP的格式:nDUP(初值[,初值…])括號(hào)中為重復(fù)的內(nèi)容,n為重復(fù)的次數(shù)。A04H00H02H00H01HBUF01H02H01H02H01HM02H02H00HDATA低8位0000H0001H0002H0013H000AH0003H0004H0005HDDATA高8位0006H0007H0008H0009H000BH000CH000DH000EH000FH0010H0011H0012H01H02H01H02H02H用DW或DD偽操作可以把變量或標(biāo)號(hào)的偏移地址(DW)或偏移地址和段地址(DD)存入存儲(chǔ)器。用DD偽操作存入地址時(shí),第一個(gè)字為偏移地址,第二個(gè)字為段地址。定位偽指令ORG語句格式:ORG常數(shù)表達(dá)式功能:使下一個(gè)字節(jié)地址為成為常數(shù)表達(dá)式的值。如:DSEGSEGMENTORG10VECT1DW47A5HORG20VECT2DW0C596HDSEGENDS說明:變量VECT1的偏移地址為10,即0AH,VECT2的偏移地址為20,即14H.4.3.3段定義語句語句格式:
段名SEGMENT...段名ENDS功能:定義了一個(gè)以SEGMENT偽指令開始,以ENDS偽指令結(jié)束,以段名命名的存儲(chǔ)段。假定偽指令語句格式:
ASSUME段寄存器名:段名,段寄存器名:段名,...其中,段寄存器名必須是CS,DS,ES,SS中的一個(gè),而段名必須是由SEGMENT定義的段中的段名。功能:設(shè)定段寄存器與段之間的關(guān)系。ASSUME語句寫在代碼段的一開始ASSUME語句只是指定某個(gè)段由哪一個(gè)段寄存器尋址,它并不能把段地址裝入段寄存器中,所以在代碼段的開始,還必須把段地址裝入相應(yīng)的段寄存器中??梢杂肕OV指令實(shí)現(xiàn)。但是代碼段不須這樣做。DATASEGMENTDATAENDSEXTRASEGMENTEXTRAENDSSTACKSEGMETSTACKENDS
............CODESEGMENTASSUMECS:CODE,DS:DATA,ES:EXTRA,SS:STACK...START:MOVAX,DATAMOVDS,AXMOVAX,EXTRAMOVES,AXMOVAX,STACK
MOVSS,AXCODEENDSENDSTART......段名也就是段地址4.3.4過程定義語句過程又稱為子程序,是完成特定功能的一段程序(1)過程定義偽操作功能:定義了一個(gè)以PROC偽指令開始,以ENDP偽指令結(jié)束,以過程名命名的過程。格式:過程名procfar/near...過程名endp過程名過程名是子程序入口的符號(hào)地址(規(guī)定與標(biāo)號(hào)相同,但后面不跟冒號(hào))。(2)調(diào)用程序與子程序不在同一個(gè)代碼段中,用far屬性-----NEAR,F(xiàn)AR(1)若調(diào)用程序與子程序在同一個(gè)代碼段中,用near注意:過程中若不沒有注明屬性,則匯編程序?qū)⑺J(rèn)為NEAR。(2)過程的調(diào)用與返回以后介紹。4.3.5結(jié)束語句功能:標(biāo)志著整個(gè)源程序的結(jié)束,它告訴匯編程序,沒有更多的指令要匯編了。語句格式:END<程序第一條指令的標(biāo)號(hào)>結(jié)束程序,返回DOS的方法一分為三個(gè)步驟(1)將程序開始啟動(dòng)運(yùn)行的過程定義為一個(gè)FAR過程.(2)在代碼段的開始處安放以下三條指令,為程序結(jié)束運(yùn)行,正確返回DOS做好準(zhǔn)備:
PUSHDSMOVAX,0PUSHAX(3)在程序結(jié)束返回DOS處安放一條RET指令結(jié)束程序,返回DOS的方法二調(diào)用DOS的4CH系統(tǒng)功能返回的方法在程序結(jié)束后插入以下語句:MOVAH,4CHINT21H4.4指令語句留給大家自己看。4.5匯編語言程序設(shè)計(jì)及舉例4.5.1直線程序設(shè)計(jì)例1計(jì)算(V-(X*Y+Z-540))/X其中X、Y、Z、V均為16位帶符號(hào)數(shù),已分別裝入X、Y、Z、V單元中,要求計(jì)算結(jié)果的商存入R單元,余數(shù)存入W單元。59DATASEGMENXDW1234HRDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATABEGIN:MOVAX,DATAMOVDS,AxYDW3456HZDW5678HVDW7834HWDW?60MOVAX,X;被乘數(shù)存入AXIMULY;X*YMOVCX,AX;乘積的低位字存入CXMOVBX,DX;乘積的高位字存入BXMOVAX,Z;加數(shù)Z存入AXCWD;把Z擴(kuò)展成雙字ADDCX,AX;乘積的低位字與Z的低位字相加ADCBX,DX;乘積與Z的高位字和低位的進(jìn)位相加SUBCX,540;(X*Y+Z)的低位字減去540SBBBX,0;(X*Y+Z)的高位字減去低位的借位61MOVAX,V;被減數(shù)V存入AXCWD;把V擴(kuò)展成雙字SUBAX,CX;V的低位字與(X*Y+Z-540)的低位字相減SBBDX,BX;V的高位字與(X*Y+Z-540)的高位字相減IDIVX;(V-(X*Y+Z-540))/XMOVR,AXMOVW,DXMOVAH,4CHINT21HCODEENDSENDBEGIN4.1分支程序結(jié)構(gòu)改變程序執(zhí)行順序、形成分支、循環(huán)、調(diào)用等程序結(jié)構(gòu)是很常見的程序設(shè)計(jì)問題高級(jí)語言采用IF等語句表達(dá)條件,并根據(jù)條件是否成立轉(zhuǎn)向不同的程序分支匯編語言需要首先利用比較CMP、測(cè)試TEST、加減運(yùn)算、邏輯運(yùn)算等影響狀態(tài)標(biāo)志的指令形成條件然后利用條件轉(zhuǎn)移指令判斷由標(biāo)志表達(dá)的條件,并根據(jù)標(biāo)志狀態(tài)控制程序轉(zhuǎn)移到不同的程序段4.1.1無條件轉(zhuǎn)移指令程序代碼在代碼段CS:指明代碼段在主存中的段基地址EIP:給出將要執(zhí)行指令的偏移地址程序順序執(zhí)行,處理器自動(dòng)增量EIP程序控制轉(zhuǎn)移,EIP隨之改變程序轉(zhuǎn)移到另外的代碼段,EIP和CS都改變控制轉(zhuǎn)移類指令:改變EIP(有些也改變CS),即改變程序執(zhí)行順序(實(shí)現(xiàn)程序控制轉(zhuǎn)移)的指令本章學(xué)習(xí)控制轉(zhuǎn)移類指令1.轉(zhuǎn)移范圍段內(nèi)轉(zhuǎn)移在當(dāng)前代碼段范圍內(nèi)的程序轉(zhuǎn)移不需更改CS,只要改變EIP(偏移地址)近轉(zhuǎn)移(Near):32位近轉(zhuǎn)移NEAR32,16位近轉(zhuǎn)移NEAR16短轉(zhuǎn)移(Short):轉(zhuǎn)移范圍在127~-128字節(jié)段間轉(zhuǎn)移從當(dāng)前代碼段跳轉(zhuǎn)到另一個(gè)代碼段需要更改CS(段地址)和EIP(偏移地址)遠(yuǎn)轉(zhuǎn)移(Far):48位遠(yuǎn)轉(zhuǎn)移FAR32,32位遠(yuǎn)轉(zhuǎn)移FAR162.指令尋址方式相對(duì)尋址方式提供目標(biāo)地址相對(duì)于當(dāng)前指令指針EIP的位移量目標(biāo)地址(轉(zhuǎn)移后的EIP)=當(dāng)前EIP+位移量相對(duì)尋址都是段內(nèi)轉(zhuǎn)移,最常用、最靈活直接尋址方式直接提供目標(biāo)地址目標(biāo)地址(轉(zhuǎn)移后的CS和EIP)=指令操作數(shù)間接尋址方式指示寄存器或存儲(chǔ)單元目標(biāo)地址來自寄存器或存儲(chǔ)單元、間接獲得寄存器間接尋址:用寄存器保存目標(biāo)地址存儲(chǔ)器間接尋址:用存儲(chǔ)單元保存目標(biāo)地址目標(biāo)地址=目的地址=轉(zhuǎn)移地址3.JMP指令無條件轉(zhuǎn)移:程序無條件改變執(zhí)行順序JMP指令相當(dāng)于高級(jí)語言的goto語句
JMPlabel ;程序轉(zhuǎn)向label標(biāo)號(hào)指定的地址
;段內(nèi)相對(duì)尋址,段間直接尋址
JMPreg32/reg16 ;程序轉(zhuǎn)向寄存器指定的地址
;寄存器間接尋址
JMPmem32/mem16 ;程序轉(zhuǎn)向存儲(chǔ)單元指定的地址
;存儲(chǔ)器間接尋址JMP指令的4種類型1.段內(nèi)轉(zhuǎn)移、相對(duì)尋址標(biāo)號(hào)指明目標(biāo)地址,指令代碼包含位移量2.段內(nèi)轉(zhuǎn)移、間接尋址通用寄存器或主存單元包含目標(biāo)指令偏移地址3.段間轉(zhuǎn)移、直接尋址標(biāo)號(hào)包含目標(biāo)指令的段地址和偏移地址4.段間轉(zhuǎn)移、間接尋址32位段用3字存儲(chǔ)單元包含目標(biāo)地址16位段用雙字存儲(chǔ)單元包含目標(biāo)地址MASM會(huì)根據(jù)存儲(chǔ)模式等信息自動(dòng)識(shí)別〔例4-1〕無條件轉(zhuǎn)移程序-1
;數(shù)據(jù)段00000000 00000000nvar dword?
;代碼段00000000 EB01 jmplabl1 ;相對(duì)尋址00000002 90
nop00000003 E900000001labl1: jmpnearptrlabl2 ;相對(duì)近轉(zhuǎn)移00000008 90
nop00000009 B800000011Rlabl2: moveax,offsetlabl3
〔例4-1〕無條件轉(zhuǎn)移程序-20000000E FFE0
jmpeax ;寄存器間接尋址00000010 90
nop00000011 B800000022Rlabl3: moveax,offsetlabl400000016 A300000000R
movnvar,eax0000001B FF2500000000R
jmpnvar ;存儲(chǔ)器間接尋址00000021 90
noplabl4:
movebx,offsetnvarjmpnearptr[ebx];數(shù)據(jù)的寄存器間接尋址數(shù)據(jù)的存儲(chǔ)器直接尋址4.1.2條件轉(zhuǎn)移指令根據(jù)指定的條件確定程序是否發(fā)生轉(zhuǎn)移
Jcclabel ;條件滿足,發(fā)生轉(zhuǎn)移;否則,順序執(zhí)行下條指令LABEL表示目標(biāo)地址,采用段內(nèi)相對(duì)尋址32位IA-32處理器:達(dá)到32位的全偏移量16位80x86處理器:-128~+127間的短轉(zhuǎn)移條件轉(zhuǎn)移指令不影響標(biāo)志,但要利用標(biāo)志cc表示利用標(biāo)志判斷的條件,16種、兩類單個(gè)標(biāo)志狀態(tài)作為條件兩數(shù)大小關(guān)系作為條件轉(zhuǎn)移條件cc:?jiǎn)蝹€(gè)標(biāo)志狀態(tài)JZ/JE
ZF=1 JumpifZero/EqualJNZ/JNE
ZF=0 JumpifNotZero/NotEqualJS
SF=1 JumpifSignJNS
SF=0 JumpifNotSignJP/JPE
PF=1 JumpifParity/ParityEvenJNP/JPO
PF=0 JumpifNotParity/ParityOddJO
OF=1 JumpifOverflowJNO
OF=0 JumpifNotOverflowJC
CF=1 JumpifCarryJNC
CF=0 JumpifNotCarry多個(gè)助記符方便記憶轉(zhuǎn)移條件cc:兩數(shù)大小關(guān)系JB/JNAE
CF=1 JumpifBelow/NotAboveorEqualJNB/JAE
CF=0 JumpifNotBelow/AboveorEqualJBE/JNA
CF=1或ZF=1 JumpifBelow/NotAboveJNBE/JA
CF=0且ZF=0 JumpifNotBeloworEqual/AboveJL/JNGE
SF≠OF JumpifLess/NotGreaterorEqualJNL/JGE
SF=OF JumpifNotLess/GreaterorEqualJLE/JNG
ZF≠OF或ZF=1 JumpifLessorEqual/NotGreaterJNLE/JG
SF=OF且ZF=0 JumpifNotLessorEqual/Greater1.單個(gè)標(biāo)志狀態(tài)作為條件的條件轉(zhuǎn)移指令JZ(JE)和JNZ(JNE):利用零位標(biāo)志ZF判斷結(jié)果是零(相等)還是非零(不等)JS和JNS:利用符號(hào)標(biāo)志SF判斷結(jié)果是負(fù)還是正JO和JNO:利用溢出標(biāo)志OF判斷結(jié)果是溢出還是沒有溢出JP(JPE)和JNP(JPO):利用奇偶標(biāo)志PF判斷結(jié)果低字節(jié)“1”的個(gè)數(shù)是偶數(shù)還是奇數(shù)JC和JNC:利用進(jìn)位標(biāo)志CF判斷結(jié)果是有進(jìn)位(為1)還是無進(jìn)位(為0)〔例4-2〕個(gè)數(shù)折半程序-1
moveax,885 ;假設(shè)一個(gè)數(shù)據(jù)
shreax,1 ;數(shù)據(jù)右移進(jìn)行折半
jncgoeven ;余數(shù)為0,即CF=0條件成立,轉(zhuǎn)移
addeax,1 ;否則余數(shù)為1,即CF=1,進(jìn)行加1操作goeven: calldispuid ;顯示結(jié)果
443運(yùn)行結(jié)果〔例4-2〕個(gè)數(shù)折半程序-2
moveax,886 ;假設(shè)一個(gè)數(shù)據(jù)
shreax,1 ;數(shù)據(jù)右移進(jìn)行折半
jcgoodd ;余數(shù)為1,即CF=1條件成立,轉(zhuǎn)移到分支體,進(jìn)行加1操作
jmpgoeven ;余數(shù)為0,即CF=0,不需要處理,轉(zhuǎn)移到顯示!goodd: addeax,1 ;進(jìn)行加1操作goeven: calldispuid ;顯示結(jié)果jncgoeven何不合二為一?〔例4-2〕個(gè)數(shù)折半程序-3
moveax,887 ;假設(shè)一個(gè)數(shù)據(jù)
shreax,1 ;數(shù)據(jù)右移進(jìn)行折半
adceax,0 ;余數(shù)=CF=1,進(jìn)行加1操作 ;余數(shù)=CF=0,沒有加1
calldispuid ;顯示結(jié)果
moveax,888 ;假設(shè)一個(gè)數(shù)據(jù)
addeax,1 ;個(gè)數(shù)加1
rcreax,1 ;數(shù)據(jù)右移進(jìn)行折半
calldispuid ;顯示結(jié)果改進(jìn)算法消除分支〔例4-3〕位測(cè)試程序—說明例如:進(jìn)行打印前,要測(cè)試打印機(jī)狀態(tài)。假設(shè)測(cè)試數(shù)據(jù)已經(jīng)進(jìn)入了EAX,其中D1位為0表示打印機(jī)沒有處于聯(lián)機(jī)打印的正常狀態(tài),D1 位為1表示可以進(jìn)行打印。編程測(cè)試EAX,若D1=0,顯示“NoReady!”,若D1=1,顯示“ReadytoGo!”〔例4-3〕位測(cè)試程序-1
;數(shù)據(jù)段no_msg byte'NotReady!',0yes_msg byte'ReadytoGo!',0 ;代碼段
moveax,56h ;假設(shè)一個(gè)數(shù)據(jù)
testeax,02h ;測(cè)試D1位(D1=1,其他位為0)
jznom ;D1=0條件成立,轉(zhuǎn)移
moveax,offsetyes_msg ;D1=1,顯示準(zhǔn)備好
jmpdone ;跳轉(zhuǎn)過另一個(gè)分支體!nom: moveax,offsetno_msg ;顯示沒有準(zhǔn)備好done: calldispmsg〔例4-3〕位測(cè)試程序-2
;數(shù)據(jù)段no_msg byte'NotReady!',0yes_msg byte'ReadytoGo!',0 ;代碼段
moveax,56h ;假設(shè)一個(gè)數(shù)據(jù)
testeax,02h ;測(cè)試D1位(D1=1,其他位為0)
jnzyesm ;D1=1條件成立,轉(zhuǎn)移
moveax,offsetno_msg ;D1=0,顯示沒有準(zhǔn)備好
jmpdone ;跳轉(zhuǎn)過另一個(gè)分支體!yesm: moveax,offsetyes_msg ;顯示準(zhǔn)備好done: calldispmsg〔例4-4〕奇校驗(yàn)程序---說明數(shù)據(jù)通信時(shí),為了可靠常要進(jìn)行校驗(yàn)。最常用的方法就是奇偶校驗(yàn)。如果使包含校驗(yàn)位在內(nèi)的數(shù)據(jù)中“1”的個(gè)數(shù)恒為奇數(shù),就是奇校驗(yàn);恒為偶數(shù),就為偶校驗(yàn)。題目要求:編程從鍵盤輸入一個(gè)字符,編程為其最高位加上奇校驗(yàn)?!怖?-4〕奇校驗(yàn)程序
callreadc ;鍵盤輸入,AL=返回值
calldispcrlf ;回車換行(用于分隔)
calldispbb ;以二進(jìn)制形式顯示數(shù)據(jù)
calldispcrlf ;回車換行(用于分隔)
andal,7fh ;最高位置“0”、其他位不變
;同時(shí)標(biāo)志PF反映“1”的個(gè)數(shù)
jnpnext ;個(gè)數(shù)為奇數(shù),不需處理,轉(zhuǎn)移
oral,80h ;個(gè)數(shù)為偶數(shù),最高位置“1”、其他位不變next: calldispbb ;顯示含校驗(yàn)位的數(shù)據(jù)2.兩數(shù)大小關(guān)系作為條件的條件轉(zhuǎn)移指令無符號(hào)數(shù)用高(Above)、低(Below)低于(不高于等于):JB(JNAE)不低于(高于等于):JNB(JAE)低于等于(不高于):JBE(JNA)不低于等于(高于):JNBE(JA)有符號(hào)數(shù)用大(Greater)、?。↙ess)小于(不大于等于):JL(JNGE)不小于(大于等于):JNL(JGE)小于等于(不大于):JLE(JNG)不小于等于(大于):JNLE(JG)〔例4-5〕數(shù)據(jù)比較程序-1
;數(shù)據(jù)段in_msg1 byte'Enteranumber:',0in_msg2 byte'Enteranothernumber:',0out_msg1 byte'Twonumbersareequal:',0out_msg2 byte'Thelessnumberis:',0out_msg3 byte13,10,'Thegreaternumberis:',0
;代碼段
moveax,offsetin_msg1 ;提示輸入
calldispmsg callreadsid ;輸入第一個(gè)數(shù)據(jù)
movebx,eax ;保存到EBX
moveax,offsetin_msg2 ;提示輸入
calldispmsg callreadsid ;輸入第二個(gè)數(shù)據(jù)
movecx,eax ;保存到ECX〔例4-5〕數(shù)據(jù)比較程序-2
cmpebx,ecx ;二個(gè)數(shù)據(jù)進(jìn)行比較
jnenequal ;兩數(shù)不相等,轉(zhuǎn)移
moveax,offsetout_msg1
calldispmsg ;顯示兩數(shù)相等
moveax,ebx calldispsid ;顯示相等的數(shù)據(jù)
jmpdone ;轉(zhuǎn)移到結(jié)束nequal: jlfirst ;EBX較小,不需要交換,轉(zhuǎn)移
xchgebx,ecx ;EBX保存較小數(shù),ECX保存較大數(shù)〔例4-5〕數(shù)據(jù)比較程序-3first: moveax,offsetout_msg2 ;顯示較小數(shù)
calldispmsg moveax,ebx ;較小數(shù)在EBX中
calldispsid moveax,offsetout_msg3 ;顯示較大數(shù)
calldispmsg
moveax,ecx ;較大數(shù)在ECX中
calldispsiddone:4.1.3單分支結(jié)構(gòu)只有一個(gè)分支的程序類似高級(jí)語言的IF-THEN語句結(jié)構(gòu)注意采用正確的條件轉(zhuǎn)移指令當(dāng)條件滿足(成立),發(fā)生轉(zhuǎn)移,跳過分支體條件不滿足,順序向下執(zhí)行分支體條件轉(zhuǎn)移指令與高級(jí)語言的IF語句正好相反IF語句是條件成立,執(zhí)行分支體〔例4-6〕求絕對(duì)值程序
;代碼段
callreadsid ;輸入一個(gè)有符號(hào)數(shù),從EAX返回值
cmpeax,0 ;比較EAX與0
jgenonneg ;條件滿足:AX≥0,轉(zhuǎn)移
negeax ;條件不滿足:AX<0,為負(fù)數(shù)
;需求補(bǔ)得正值nonneg: calldispuid ;分支結(jié)束,顯示結(jié)果示意圖單分支結(jié)構(gòu)的流程圖返回〔例4-7〕字母判斷程序
callreadc ;輸入一個(gè)字符,從AL返回值
cmpal,'A’ ;與大寫字母A比較
jbdone ;比大寫字母A小,不是大寫字母,轉(zhuǎn)移
cmpal,'Z’ ;與大寫字母Z比較
jadone ;比大寫字母Z大,不是大寫字母,轉(zhuǎn)移
oral,20h ;轉(zhuǎn)換為小寫
calldispcrlf ;回車換行
calldispc ;顯示小寫字母done:
4.1.4雙分支結(jié)構(gòu)雙分支程序結(jié)構(gòu)有兩個(gè)分支,條件為真執(zhí)行一個(gè)分支;條件為假,執(zhí)行另一個(gè)分支相當(dāng)于高級(jí)語言的IF-THEN-ELSE語句順序執(zhí)行的分支體1最后一定要有一條JMP指令跳過分支體2JMP指令必不可少,實(shí)現(xiàn)結(jié)束前一個(gè)分支回到共同的出口作用雙分支結(jié)構(gòu)有時(shí)可以改變?yōu)閱畏种ЫY(jié)構(gòu)事先執(zhí)行其中一個(gè)分支(選擇出現(xiàn)概率較高的分支)〔例4-8〕顯示數(shù)據(jù)最高位程序-1
;數(shù)據(jù)段dvar dword0bd630422h ;假設(shè)一個(gè)數(shù)據(jù)
;代碼段
movebx,dvar shlebx,1 ;EBX最高位移入CF標(biāo)志
jcone ;CF=1,即最高位為1,轉(zhuǎn)移
moval,'0' ;CF=0,即最高位為0:AL←'0'
jmptwo ;一定要跳過另一個(gè)分支one: moval,'1' ;AL←'1'two: calldispc ;顯示
示意圖雙分支結(jié)構(gòu)雙分支結(jié)構(gòu)的流程圖返回〔例4-8〕顯示數(shù)據(jù)最高位程序-2
movebx,dvar moval,'0' ;假設(shè)最高位為0:AL←'0'
shlebx,1 ;EBX最高位移入CF標(biāo)志
jnctwo ;CF=0,即最高位為0,轉(zhuǎn)移
moval,'1' ;CF=1,即最高位為1,AL←'1'two: calldispc ;顯示單分支結(jié)構(gòu)〔例4-9〕有符號(hào)數(shù)運(yùn)算溢出程序
;數(shù)據(jù)段dvar1 dword1234567890 ;假設(shè)兩個(gè)數(shù)據(jù)dvar2 dword-999999999dvar3 dword?okmsg byte'Correct!',0 ;正確信息errmsg byte'ERROR!Overflow!',0 ;錯(cuò)誤信息
;代碼段
moveax,dvar1 subeax,dvar2 ;求差
joerror ;有溢出,轉(zhuǎn)移
movdvar3,eax ;無溢出,保存差值
moveax,offsetokmsg ;顯示正確
jmpdisperror: moveax,offseterrmsg ;顯示錯(cuò)誤disp: calldispmsg
4.2循環(huán)程序結(jié)構(gòu)三個(gè)部分組成:循環(huán)初始——為開始循環(huán)準(zhǔn)備必要的條件,如循環(huán)次數(shù)、循環(huán)體需要的初始值等;循環(huán)體——重復(fù)執(zhí)行的程序代碼,其中包括對(duì)循環(huán)條件的修改等;循環(huán)控制——判斷循環(huán)條件是否成立,決定是否繼續(xù)循環(huán)“先判斷、后循環(huán)”的循環(huán)程序結(jié)構(gòu)對(duì)應(yīng)高級(jí)語言的WHILE語句“先循環(huán)、后判斷”的循環(huán)程序結(jié)構(gòu)對(duì)應(yīng)高級(jí)語言的DO語句示意圖循環(huán)程序結(jié)構(gòu)的流程圖返回4.2.1循環(huán)指令
LOOPlabel;ECX←ECX-1;若ECX≠0,循環(huán)到LABEL;否則,順序執(zhí)行
JECXZlabel;ECX=0,轉(zhuǎn)移;否則順序執(zhí)行目標(biāo)地址采用相對(duì)短轉(zhuǎn)移實(shí)地址存儲(chǔ)模型使用CX作為計(jì)數(shù)器DECECXJNZlabelCMPECX,0JZlabel〔例4-10〕數(shù)組求和程序;數(shù)據(jù)段Arraydword136,-138,133,130,-161Sumdword?〔例4-10〕數(shù)組求和程序
movecx,lengthofarray ;ECX=數(shù)組元素個(gè)數(shù)
xoreax,eax ;求和初值為0
movebx,eax ;數(shù)組指針為0again: addeax,array[ebx*(typearray)] ;求和
incebx ;指向下一個(gè)數(shù)組元素
loopagain movsum,eax ;保存結(jié)果
calldispsid ;顯示結(jié)果循環(huán)體循環(huán)控制循環(huán)初始4.2.2計(jì)數(shù)控制循環(huán)通過次數(shù)控制循環(huán)利用LOOP指令屬于計(jì)數(shù)控制常見是“先循環(huán)、后判斷”循環(huán)結(jié)構(gòu)計(jì)數(shù)可以減量進(jìn)行,即減到0結(jié)束計(jì)數(shù)可以增量進(jìn)行,即達(dá)到規(guī)定值結(jié)束循環(huán)程序結(jié)構(gòu)的關(guān)鍵是如何控制循環(huán)〔例4-11〕簡(jiǎn)單加密解密程序-1
;數(shù)據(jù)段key byte234bufnum =255buffer bytebufnum+1dup(0) ;定義鍵盤輸入需要的緩沖區(qū)msg1 byte'Entermessage:',0msg2 byte'Encryptedmessage:',0msg3 byte13,10,'Originalmessage:',0 ;代碼段
moveax,offsetmsg1 ;提示輸入字符串
calldispmsg moveax,offsetbuffer ;設(shè)置入口參數(shù)EAX
callreadmsg ;調(diào)用輸入字符串子程序
pusheax ;字符個(gè)數(shù)保存進(jìn)入堆?!怖?-11〕簡(jiǎn)單加密解密程序-2
movecx,eax ;ECX=實(shí)際輸入的字符個(gè)數(shù),作為循環(huán)的次數(shù)
xorebx,ebx ;EBX指向輸入字符
moval,key ;AL=加密關(guān)鍵字encrypt: xorbuffer[ebx],al ;異或加密
incebx dececx ;等同于指令:loopencrypt
jnzencrypt ;處理下一個(gè)字符
moveax,offsetmsg2 calldispmsg moveax,offsetbuffer ;顯示密文
calldispmsg〔例4-11〕簡(jiǎn)單加密解密程序-3
popecx ;從堆棧彈出字符個(gè)數(shù),作為循環(huán)的次數(shù)
xorebx,ebx ;EBX指向輸入字符
moval,key ;AL=解密關(guān)鍵字decrypt: xorbuffer[ebx],al ;異或解密
incebx dececx jnzdecrypt ;處理下一個(gè)字符
moveax,offsetmsg3 calldispmsg moveax,offsetbuffer ;顯示明文
calldispmsg示意圖簡(jiǎn)單加密解密程序運(yùn)行實(shí)例返回4.2.3條件控制循環(huán)根據(jù)條件決定是否進(jìn)行循環(huán)需要使用有條件轉(zhuǎn)移指令實(shí)現(xiàn)多見“先判斷、后循環(huán)”結(jié)構(gòu)先行判斷的條件控制循環(huán)程序很像雙分支結(jié)構(gòu)主要分支需要重復(fù)執(zhí)行多次(JMP的目標(biāo)位置是循環(huán)開始)另一個(gè)分支用于跳出這個(gè)循環(huán)先行循環(huán)的條件控制循環(huán)程序類似單分支結(jié)構(gòu),循環(huán)體就是分支體順序執(zhí)行就跳出循環(huán)〔例4-12〕字符個(gè)數(shù)統(tǒng)計(jì)程序題目說明:已知某個(gè)字符串以0結(jié)尾,統(tǒng)計(jì)其包含的字符個(gè)數(shù),即計(jì)算字符串的長(zhǎng)度?!怖?-12〕字符個(gè)數(shù)統(tǒng)計(jì)程序 ;數(shù)據(jù)段string byte‘DoyouhavefunwithAssembly?’,0 ;以0結(jié)尾的字符串 ;代碼段
xorebx,ebx ;EBX用于記錄字符個(gè)數(shù),也用于指向字符的指針again: moval,string[ebx] cmpal,0 ;用指令“testal,al”也可
jzdone incebx ;個(gè)數(shù)加1
jmpagain ;繼續(xù)循環(huán)done: moveax,ebx ;顯示個(gè)數(shù)
calldispuid〔例4-13〕字符剔除程序題目說明現(xiàn)有一個(gè)以0結(jié)尾的字符串,要求剔除其中的空格字符。處理方法:
1、用結(jié)尾標(biāo)志0作為循環(huán)控制條件
2、循環(huán)體判斷每個(gè)字符,如果不是空格,不予處理繼續(xù)循環(huán);如果是空格,則進(jìn)行剔除,也就是將后續(xù)所有字符逐個(gè)前移一個(gè)字符位置,將空格覆蓋。這是一個(gè)雙重循環(huán)的程序結(jié)構(gòu)?!怖?-13〕字符剔除程序-1Stringbyte‘Letushaveatry!’0dh,0ah,0’moveax,offsetstring ;顯示處理前字符串
calldispmsg movesi,offsetstringoutlp: cmpbyteptr[esi],0 ;外循環(huán),先判斷后循環(huán)
jzdone ;為0結(jié)束again: cmpbyteptr[esi],'';是否是空格
jnznext ;不是空格繼續(xù)循環(huán)
movedi,esi ;是空格,剔除空格分支inlp: incedi ;該分支是循環(huán)程序
moval,[edi] ;前移一個(gè)位置
mov[edi-1],al〔例4-13〕字符剔除程序-2
cmpbyteptr[edi],0
;內(nèi)循環(huán),先循環(huán)后判斷
jnzinlp ;內(nèi)循環(huán)結(jié)束處
jmpagain ;再次判斷是否為空格(處理連續(xù)空格)next: incesi ;繼續(xù)對(duì)后續(xù)字符進(jìn)行判斷處理
jmpoutlp ;外循環(huán)結(jié)束處done: moveax,offsetstring ;顯示處理后字符串
calldispmsg4.3子程序結(jié)構(gòu)經(jīng)常用到的應(yīng)用問題編寫成一個(gè)通用子程序大型處理過程分解成能夠解決的模塊使用子程序可以使程序的結(jié)構(gòu)更為清楚程序的維護(hù)更為方便有利于大程序開發(fā)時(shí)的多個(gè)程序員分工合作子程序(Subroutine)=函數(shù)(Function)=過程(Procedure)4.3.1子程序指令子程序:與主程序分開的、完成特定功能的一段程序當(dāng)主程序(調(diào)用程序)執(zhí)行調(diào)用指令CALL調(diào)用子程序子程序(被調(diào)用程序)執(zhí)行返回指令RET返回主程序CALLlabel主程序RET子程序回到CALL指令后的指令處1.子程序調(diào)用指令CALLCALL指令用在主程序中,實(shí)現(xiàn)子程序的調(diào)用分成段內(nèi)調(diào)用(近調(diào)用)和段間調(diào)用(遠(yuǎn)調(diào)用)目標(biāo)地址采用相對(duì)尋址、直接尋址或間接尋址入棧返回地址:將CALL下條指令的地址壓入堆棧
CALLlabel ;調(diào)用標(biāo)號(hào)指定的子程序
CALLreg16/reg32
;調(diào)用寄存器指定地址的子程序
CALLmem16/mem32 ;調(diào)用存儲(chǔ)單元指定地址的子程序2.子程序返回指令RETRET指令用在子程序結(jié)束,實(shí)現(xiàn)返回主程序
RET
;無參數(shù)返回:出棧返回地址
RETi16 ;有參數(shù)返回:出棧返回地址
;ESP←ESP+i16MASM會(huì)根據(jù)存儲(chǔ)模型等信息確定子程序的遠(yuǎn)近調(diào)用,并相應(yīng)產(chǎn)生返回指令3.過程定義偽指令MASM利用過程定義偽指令獲得子程序信息
過程名 PROC
…… ;過程體
過程名 ENDP
;過程名為符合語法的標(biāo)識(shí)符PROC后面可加參數(shù):NEAR或FAR簡(jiǎn)化段定義源程序格式中,通常不需指定〔例4-14〕子程序調(diào)用程序-1
;代碼段,主程序00000000 B800000001 moveax,100000005 BD00000005 movebp,50000000A E800000016
callsubp ;子程序調(diào)用0000000F B900000003
retp1: movecx,300000014 BA00000004retp2: movedx,400000019 E800000000E
calldisprd〔例4-14〕子程序調(diào)用程序-2 ;子程序subp proc ;過程定義,過程名為subp
pushebp movebp,esp movesi,[ebp+4] ;ESI=CALL下條指令(標(biāo)號(hào)RETP1)偏移地址
movedi,offsetretp2 ;EDI=標(biāo)號(hào)RETP2的偏移地址
movebx,2 popebp ;彈出堆棧,保持堆棧平衡
ret ;子程序返回subp endp ;過程結(jié)束MOV[EBP+4],EDI?示意圖子程序調(diào)用的堆棧返回4.3.2子程序設(shè)計(jì)子程序的編寫方法與主程序一樣但需要留意幾個(gè)問題:利用過程定義,獲得子程序名和調(diào)用屬性RET指令返回主程序,CALL指令調(diào)用子程序壓入和彈出操作要成對(duì)使用,保持堆棧平衡開始保護(hù)寄存器,返回前相應(yīng)恢復(fù)安排在代碼段的主程序之外子程序允許嵌套和遞歸最好有完整的注釋難點(diǎn)是參數(shù)傳遞〔例4-15〕十六進(jìn)制顯示程序題目說明將每個(gè)16進(jìn)制數(shù)位轉(zhuǎn)換為ASCII碼。4位2進(jìn)制數(shù)對(duì)應(yīng)一位16進(jìn)制數(shù),具有16個(gè)數(shù)碼:0-9,A-F。依次對(duì)應(yīng)的ASCII碼是30H-39H,41H-46H。所以,16進(jìn)制數(shù)0-9只要加30H就可以轉(zhuǎn)換成ASCII碼,而對(duì)A-F需要再加7。HTOASC:主程序通過AL的低4位將要轉(zhuǎn)換的16進(jìn)制數(shù)位傳遞給子程序,子程序轉(zhuǎn)換后的ASCII碼通過AL反饋給主程序?!怖?-15〕十六進(jìn)制顯示程序-1.dataregd byte'EAX=',8dup(0),'H',0.code
moveax,1234abcdh ;假設(shè)一個(gè)數(shù)據(jù)
xorebx,ebx movecx,8 ;8位十六進(jìn)制數(shù)again: roleax,4 ;高4位循環(huán)移位進(jìn)入低4位
pusheax callhtoasc ;調(diào)用子程序
movregd+4[ebx],al ;保存轉(zhuǎn)換后的ASCII碼
popeax incebx dececx jnzagain moveax,offsetregd calldispmsg ;顯示regdbyte'EAX=',8dup(0),'H',0〔例4-15〕十六進(jìn)制顯示程序-2
;子程序htoasc proc;將AL低4位表達(dá)的一位十六進(jìn)制數(shù)轉(zhuǎn)換為ASCII碼
andal,0fh ;只取AL的低4位
oral,30h ;AL高4位變成3
cmpal,39h ;是0~9,還是A~F
jbehtoend addal,7 ;是A~F,ASCII碼再加上7htoend: ret ;子程序返回htoasc endp〔例4-15〕十六進(jìn)制顯示程序-3
;子程序htoasc proc andeax,0fh ;取AL低4位
moval,ASCII[eax];換碼
ret ;子程序的局部數(shù)據(jù)(只讀)ASCII byte'0123456789ABCDEF'htoasc endpEAX=1234ABCDH運(yùn)行結(jié)果4.3.3參數(shù)傳遞主程序與子程序間通過參數(shù)傳遞建立聯(lián)系入口參數(shù)(輸入?yún)?shù)):主程序→子程序出口參數(shù)(輸出參數(shù)):子程序→主程序傳遞參數(shù)的多少反映程序模塊間的耦合程度參數(shù)的具體內(nèi)容數(shù)據(jù)本身(傳遞數(shù)值)數(shù)據(jù)的存儲(chǔ)地址(傳遞地址,傳遞引用)參數(shù)傳遞方法寄存器變量堆棧1.寄存器傳遞參數(shù)最簡(jiǎn)單和常用的參數(shù)傳遞方法把參數(shù)存于約定的寄存器少量數(shù)據(jù)直接傳遞數(shù)值大量數(shù)據(jù)只能傳遞地址帶有出口參數(shù)的寄存器不能保護(hù)和恢復(fù)帶有入口參數(shù)的寄存器可以保護(hù)、也可以不保護(hù),但最好能夠保持一致〔例4-16〕有符號(hào)十進(jìn)制數(shù)顯示程序-1轉(zhuǎn)換的算法如下:(1)首先判斷數(shù)據(jù)是零、正數(shù)或負(fù)數(shù),是零顯示“0”退出(2)是負(fù)數(shù),顯示負(fù)號(hào)“-”,求數(shù)據(jù)的絕對(duì)值(3)接著數(shù)據(jù)除以10,余數(shù)為十進(jìn)制數(shù)碼,加30H轉(zhuǎn)換為ASCII碼保存(4)重復(fù)(3)步,直到商為0結(jié)束(5)依次從高位開始顯示各位數(shù)字〔例4-16〕有符號(hào)十進(jìn)制數(shù)顯示程序-2
;數(shù)據(jù)段array dword1234567890,-1234,0,1,...writebuf byte12dup(0) ;顯示緩沖區(qū)
;代碼段
movecx,lengthofarray movebx,0again: moveax,array[ebx*4] ;EAX=入口參數(shù)
callwrite ;調(diào)用子程序,顯示一個(gè)數(shù)據(jù)
calldispcrlf ;換行以便顯示下一個(gè)數(shù)據(jù)
incebx dececx jnzagain寄存器傳遞參數(shù)〔例4-16〕有符號(hào)十進(jìn)制數(shù)顯示程序-3 ;顯示有符號(hào)十進(jìn)制數(shù)的子程序write proc ;EAX=入口參數(shù)
pushebx ;保護(hù)寄存器
pushecx pushedx movebx,offsetwritebuf;EBX指向顯示緩沖區(qū)
testeax,eax ;判斷數(shù)據(jù)是零、正數(shù)或負(fù)數(shù)
jnzwrite1 ;不是零,跳轉(zhuǎn)
movbyteptr[ebx],'0' ;是零,設(shè)置“0”
incebx jmpwrite5 ;轉(zhuǎn)向顯示write1: jnswrite2 ;是正數(shù),跳轉(zhuǎn)
movbyteptr[ebx],'-';是負(fù)數(shù),設(shè)置負(fù)號(hào)
incebx negeax ;數(shù)據(jù)求補(bǔ)(絕對(duì)值)寄存器傳遞參數(shù)〔例4-16〕有符號(hào)十進(jìn)制數(shù)顯示程序-4write2: movecx,10 pushecx ;10壓入堆棧,作為退出標(biāo)志write3: cmpeax,0 ;數(shù)據(jù)(商)為零,轉(zhuǎn)向保存
jzwrite4 xoredx,edx ;零位擴(kuò)展被除數(shù)為EDX.EAX
divecx ;數(shù)據(jù)除以10:EDX.EAX÷10
addedx,30h ;余數(shù)(0~9)轉(zhuǎn)換為ASCII碼
pushedx ;數(shù)據(jù)先低位后高位壓入堆棧
jmpwrite3〔例4-16〕有符號(hào)十進(jìn)制數(shù)顯示程序-5write4: popedx ;數(shù)據(jù)先高位后低位彈出堆棧
cmpedx,ecx ;是結(jié)束標(biāo)志10,轉(zhuǎn)向顯示
jewrite5 mov[ebx],dl ;數(shù)據(jù)保存到緩沖區(qū)
incebx jmpwrite4write5: movbyteptr[ebx],0 ;顯示內(nèi)容加上結(jié)尾標(biāo)志
moveax,offsetwritebuf calldispmsg
popedx ;恢復(fù)寄存器
popecx popebx ret ;子程序返回write endp2.共享變量傳遞參數(shù)子程序和主程序使用同一個(gè)變量名存取數(shù)據(jù)如果變量定義和使用不在同一個(gè)程序模塊中,需要利用PUBLIC、EXTREN聲明共享變量傳遞參數(shù),子程序的通用性較差特別適合在多個(gè)程序段間、尤其在不同的程序模塊間傳遞數(shù)據(jù)〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-1十進(jìn)制有符號(hào)整數(shù)轉(zhuǎn)換為補(bǔ)碼的算法如下:(1)判斷輸入了正數(shù)、還是負(fù)數(shù),用一個(gè)寄存器記錄(2)判斷下一個(gè)字符是否為有效數(shù)碼 字符無效,提示錯(cuò)誤重新輸入,并轉(zhuǎn)向(1) 字符有效,繼續(xù)(3)字符有效,減30H轉(zhuǎn)換為二進(jìn)制數(shù);然后將前面輸入的數(shù)值乘10,并與剛輸入的數(shù)字相加得到新的數(shù)值(4)判斷輸入的數(shù)據(jù)是否超出有效范圍超出范圍,提示錯(cuò)誤重新輸入,并轉(zhuǎn)向(1)沒有超出范圍,則繼續(xù)(5)重復(fù)(2)~(4)步,輸入字符都有效,一直處理完(6)是負(fù)數(shù)進(jìn)行求補(bǔ),轉(zhuǎn)換成補(bǔ)碼;否則直接將數(shù)值保存〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-2
;數(shù)據(jù)段count =10array dwordcountdup(0)temp dword?readbuf byte30dup(0) ;代碼段
movecx,count movebx,offsetarrayagain: callread ;調(diào)用子程序,輸入一個(gè)數(shù)據(jù)
moveax,temp ;獲得出口參數(shù)
mov[ebx],eax ;存放到數(shù)據(jù)緩沖區(qū)
addebx,4 dececx jnzagain共享變量傳遞參數(shù)〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-3 ;輸入有符號(hào)十進(jìn)制數(shù)的子程序read proc ;出口參數(shù):變量TEMP=補(bǔ)碼表示的二進(jìn)制數(shù)值
pusheax ;說明:負(fù)數(shù)用“-”引導(dǎo)
pushebx
pushecx pushedxread0: moveax,offsetreadbuf
callreadmsg ;輸入一個(gè)字符串
testeax,eax jzreaderr ;沒有輸入數(shù)據(jù),錯(cuò)誤
cmpeax,12 jareaderr ;輸入超過12個(gè)字符,錯(cuò)誤〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-4
movedx,offsetreadbuf;EDX指向輸入緩沖區(qū)
xorebx,ebx ;EBX保存結(jié)果
xorecx,ecx ;ECX為正負(fù)標(biāo)志,0為正,-1為負(fù)
moval,[edx] ;取一個(gè)字符
cmpal,'+' ;是“+”,繼續(xù)
jzread1 cmpal,'-' ;是“-”,設(shè)置-1標(biāo)志
jnzread2 movecx,-1read1: incedx ;取下一個(gè)字符
moval,[edx] testal,al ;是結(jié)尾0,轉(zhuǎn)向求補(bǔ)碼
jzread3〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-5read2: cmpal,'0' ;不是0~9之間的數(shù)碼,錯(cuò)誤
jbreaderr cmpal,'9' jareaderr subal,30h ;是0~9之間的數(shù)碼,轉(zhuǎn)換
imulebx,10 ;原數(shù)值乘10:EBX=EBX×10
jcreaderr ;CF=1,乘積溢出,出錯(cuò)
movzxeax,al ;零位擴(kuò)展,便于相加
addebx,eax ;原數(shù)乘10后,與新數(shù)碼相加
cmpebx,80000000h ;數(shù)據(jù)超過231,出錯(cuò)
jberead1 ;繼續(xù)轉(zhuǎn)換下一個(gè)數(shù)位〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-6readerr: moveax,offseterrmsg ;顯示出錯(cuò)信息
calldispmsg jmpread0 ;read3: testecx,ecx ;判斷是正數(shù)還是負(fù)數(shù)
jzread4
negebx ;是負(fù)數(shù),進(jìn)行求補(bǔ)
jmpread5read4: cmpebx,7fffffffh ;正數(shù)超過231-1,出錯(cuò)
jareaderr〔例4-17〕有符號(hào)十進(jìn)制數(shù)輸入程序-7read5: movtemp,ebx ;設(shè)置出口參數(shù)
popedx popecx popebx popeax ret ;子程序返回errmsg byte'Inputerror,enteragain:',0read endp共享變量傳遞參數(shù)3.堆棧傳遞參數(shù)主程序?qū)⑷肟趨?shù)壓入堆棧,子程序從堆棧中取出參數(shù)出口參數(shù)通常不使用堆棧傳遞高級(jí)語言進(jìn)行函數(shù)調(diào)用時(shí)提供的參數(shù),實(shí)質(zhì)也利用堆棧傳遞采用堆棧傳遞參數(shù)是程式化的,它是編譯程序處理參數(shù)傳遞、以及匯編語言與高級(jí)語言混合編程時(shí)的常規(guī)方法〔例4-18〕計(jì)算有符號(hào)數(shù)平均值程序-1
;數(shù)據(jù)段array dword675,354,-34,... ;代碼段
pushlengthofarray ;壓入數(shù)據(jù)個(gè)數(shù)
pushoffsetarray ;壓數(shù)組的偏移地址
callmean ;調(diào)用求平均值子程序
;出口參數(shù):EAX=平均值(整數(shù)部分)
addesp,8 ;平衡堆棧(壓入了8個(gè)字節(jié)數(shù)據(jù))
calldispsid ;顯示堆棧傳遞參數(shù)〔例4-18〕計(jì)算有符號(hào)數(shù)平均值程序-2
;計(jì)算32位有符號(hào)數(shù)平均值子程序mean proc ;入口參數(shù):順序壓入數(shù)據(jù)個(gè)數(shù)和數(shù)組偏移地址
pushebp ;出口參數(shù):EAX=平均值
movebp,esp
pushebx ;保護(hù)寄存器
pushecx pushedx movebx,[ebp+8] ;EBX=取出的偏移地址
movecx,[ebp+12] ;ECX=取出的數(shù)據(jù)個(gè)數(shù)
xoreax,eax ;EAX保存和值
xoredx,edx ;EDX=指向數(shù)組元素堆棧傳遞參數(shù)〔例4-18〕計(jì)算有符號(hào)數(shù)平均值程序-3mean1: addeax,[ebx+edx*4] ;求和
addedx,1 ;指向下一個(gè)數(shù)據(jù)
cmpedx,ecx ;比較個(gè)數(shù)
jbmean1 ;循環(huán)
cdq ;將累加和EAX符號(hào)擴(kuò)展到EDX
idivecx ;有符號(hào)數(shù)除法,EAX=平均值
popedx ;恢復(fù)寄存器
popecx popebx popebp retmean endp示意圖求和溢出與個(gè)數(shù)為0的問題?利用堆棧傳遞參數(shù)返回4.3.4程序模塊程序分段、子程序等是進(jìn)行程序模塊化開發(fā)大型程序時(shí)采用的方法子程序模塊子程序庫庫文件包含宏匯編源文件包含1.子程序模塊子程序單獨(dú)編寫,匯編形成目標(biāo)模塊OBJ文件連接時(shí)輸入子程序模塊文件名用共用偽指令PUBLIC和外部偽指令EXTERN聲明PUBLIC標(biāo)識(shí)符[,標(biāo)識(shí)符…] ;定義標(biāo)識(shí)符的模塊使用EXTERN標(biāo)識(shí)符:類型[,標(biāo)識(shí)符:類型…] ;調(diào)用標(biāo)識(shí)符的模塊使用子程序在代碼段,與主程序文件采用相同的存儲(chǔ)模型,沒有開始執(zhí)行和結(jié)束執(zhí)行點(diǎn)處理好子程序與主程序之間的參數(shù)傳問題〔例4-19〕數(shù)據(jù)輸入輸出程序-1;eg0419s.asm(子程序文件)
includeio32.incpublic read,write,mean ;子程序共用extern temp:dword ;外部變量
.data ;定義的變量集中起來writebuf byte12dup(0) ;顯示緩沖區(qū)readbuf byte30dup(0) .code ;代碼段write procc ;明確采用C語言規(guī)范
…… ;輸出子程序read pro
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 律師合作咨詢協(xié)議書范本
- 縣城門面轉(zhuǎn)讓協(xié)議書范本
- 車輛質(zhì)押貸款合同模板(含車輛評(píng)估條款)
- 節(jié)日促銷活動(dòng)員工激勵(lì)合同
- 事業(yè)單位停薪留職人員原單位業(yè)績(jī)考核及獎(jiǎng)勵(lì)協(xié)議
- 餐飲企業(yè)股東合作協(xié)議與供應(yīng)鏈優(yōu)化
- 彩鋼板房建筑項(xiàng)目施工安全與環(huán)境保護(hù)合同
- 離婚彩禮退還爭(zhēng)議調(diào)解及仲裁協(xié)議
- 員工感恩培訓(xùn)
- 冬季檢修安全培訓(xùn)
- 國(guó)家開放大學(xué)2025春《公共部門人力資源管理》形考任務(wù)1-4參考答案
- 本人飲酒免責(zé)協(xié)議書
- 2025年臨床執(zhí)業(yè)醫(yī)師考試重要技能試題及答案
- 歷史七年級(jí)歷史下冊(cè)期末測(cè)試卷(1~21課) 2024-2025學(xué)年七年級(jí)歷史下(統(tǒng)編版2024)
- 住宅性能評(píng)定技術(shù)標(biāo)準(zhǔn)
- 駕駛員汛期專項(xiàng)安全培訓(xùn)
- 《生成式人工智能服務(wù)管理暫行辦法》知識(shí)培訓(xùn)
- 旅游景區(qū)安全事故課件
- 中國(guó)心力衰竭診斷和治療指南2024解讀
- 《飼料添加劑學(xué)》課件
- 2025年長(zhǎng)江財(cái)產(chǎn)保險(xiǎn)股份有限公司招聘筆試參考題庫含答案解析
評(píng)論
0/150
提交評(píng)論