第4章匯編語(yǔ)言程序設(shè)計(jì)_第1頁(yè)
第4章匯編語(yǔ)言程序設(shè)計(jì)_第2頁(yè)
第4章匯編語(yǔ)言程序設(shè)計(jì)_第3頁(yè)
第4章匯編語(yǔ)言程序設(shè)計(jì)_第4頁(yè)
第4章匯編語(yǔ)言程序設(shè)計(jì)_第5頁(yè)
已閱讀5頁(yè),還剩92頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第4章匯編語(yǔ)言程序設(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++語(yǔ)言的混合編程本章內(nèi)容4.1分支程序結(jié)構(gòu)4.2循環(huán)程序結(jié)構(gòu) 4.3子程序結(jié)構(gòu)4.4Windows應(yīng)用程序編程4.5與C++語(yǔ)言的混合編程本章內(nèi)容4.1分支程序結(jié)構(gòu)改變程序執(zhí)行順序、形成分支、循環(huán)、調(diào)用等程序結(jié)構(gòu)是很常見的程序設(shè)計(jì)問題高級(jí)語(yǔ)言采用IF等語(yǔ)句表達(dá)條件,并根據(jù)條件是否成立轉(zhuǎn)向不同的程序分支匯編語(yǔ)言需要首先利用比較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無(wú)條件轉(zhuǎn)移指令程序代碼在代碼段CS:指明代碼段在主存中的段基地址EIP:給出將要執(zhí)行指令的偏移地址當(dāng)程序順序執(zhí)行,處理器根據(jù)被執(zhí)行指令的字節(jié)長(zhǎng)度自動(dòng)增加EIP當(dāng)程序控制轉(zhuǎn)移,EIP隨之改變當(dāng)程序轉(zhuǎn)移到另外的代碼段,EIP和CS都改變控制轉(zhuǎn)移類指令:改變EIP(有些也改變CS),即改變程序執(zhí)行順序(實(shí)現(xiàn)程序控制轉(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)地址來(lái)自寄存器或存儲(chǔ)單元、間接獲得寄存器間接尋址:用寄存器保存目標(biāo)地址存儲(chǔ)器間接尋址:用存儲(chǔ)單元保存目標(biāo)地址目標(biāo)地址=目的地址=轉(zhuǎn)移地址3.JMP指令無(wú)條件轉(zhuǎn)移:無(wú)任何先決條件就能使程序改變執(zhí)行順序JMP指令相當(dāng)于高級(jí)語(yǔ)言的goto語(yǔ)句

JMPlabel ;程序轉(zhuǎn)向label標(biāo)號(hào)指定的地址

;段內(nèi)相對(duì)尋址,段間直接尋址

JMPreg32/reg16 ;程序轉(zhuǎn)向寄存器指定的地址

;寄存器間接尋址

JMPmem48/mem32/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〕無(wú)條件轉(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〕無(wú)條件轉(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

SF≠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)還是無(wú)進(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è)試程序-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)過(guò)另一個(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)過(guò)另一個(gè)分支體!yesm: moveax,offsetyes_msg ;顯示準(zhǔn)備好done: calldispmsg〔例4-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)移指令無(wú)符號(hào)數(shù)用高(Above)、低(Below)低于(不高于等于):JB(JNAE)不低于(高于等于):JNB(JAE)低于等于(不高于):JBE(JNA)不低于等于(高于):JNBE(JA)有符號(hào)數(shù)用大(Greater)、小(Less)小于(不大于等于):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)單分支程序結(jié)構(gòu)只有一個(gè)分支的程序類似高級(jí)語(yǔ)言的IF-THEN語(yǔ)句結(jié)構(gòu)注意采用正確的條件轉(zhuǎn)移指令當(dāng)條件滿足(成立),發(fā)生轉(zhuǎn)移,跳過(guò)分支體條件不滿足,順序向下執(zhí)行分支體條件轉(zhuǎn)移指令與高級(jí)語(yǔ)言的IF語(yǔ)句正好相反IF語(yǔ)句是條件成立,執(zhí)行分支體〔例4-6〕求絕對(duì)值程序

;代碼段

callreadsid ;輸入一個(gè)有符號(hào)數(shù),從EAX返回值

cmpeax,0 ;比較EAX與0

jgenonneg ;條件滿足:EAX≥0,轉(zhuǎn)移

negeax ;條件不滿足:EAX<0,為負(fù)數(shù)

;需求補(bǔ)得正值nonneg: calldispuid ;分支結(jié)束,顯示結(jié)果單分支結(jié)構(gòu)的流程圖negeax〔例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í)語(yǔ)言的IF-THEN-ELSE語(yǔ)句順序執(zhí)行的分支體1最后一定要有一條JMP指令跳過(guò)分支體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 ;一定要跳過(guò)另一個(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 ;無(wú)溢出,保存差值

moveax,offsetokmsg ;顯示正確

jmpdisperror: moveax,offseterrmsg ;顯示錯(cuò)誤disp: calldispmsg

4.1分支程序結(jié)構(gòu)4.2循環(huán)程序結(jié)構(gòu)

4.3子程序結(jié)構(gòu)4.4Windows應(yīng)用程序編程4.5與C++語(yǔ)言的混合編程本章內(nèi)容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í)語(yǔ)言的WHILE語(yǔ)句“先循環(huán)、后判斷”的循環(huán)程序結(jié)構(gòu)對(duì)應(yīng)高級(jí)語(yǔ)言的DO語(yǔ)句循環(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ù)組求和程序

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)通過(guò)次數(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)單加密解密程序4.2.3條件控制循環(huán)復(fù)雜的循環(huán)程序結(jié)構(gòu)需要利用條件轉(zhuǎn)移指令,根據(jù)條件決定是否進(jìn)行循環(huán),這就是所謂的條件循環(huán)控制。計(jì)數(shù)控制循環(huán)往往至少執(zhí)行一次循環(huán)體之后,才判斷次數(shù)是否為0,即所謂的“先循環(huán),后判斷”循環(huán)結(jié)構(gòu)。條件控制循環(huán)更多見的是“先判斷,后循環(huán)”結(jié)構(gòu)〔例4-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字符剔除程序課后練習(xí)4.1分支程序結(jié)構(gòu)4.2循環(huán)程序結(jié)構(gòu) 4.3子程序結(jié)構(gòu)4.4Windows應(yīng)用程序編程4.5與C++語(yǔ)言的混合編程本章內(nèi)容4.3子程序結(jié)構(gòu)經(jīng)常用到的應(yīng)用問題編寫成一個(gè)通用子程序大型處理過(guò)程分解成能夠解決的模塊使用子程序可以使程序的結(jié)構(gòu)更為清楚程序的維護(hù)更為方便有利于大程序開發(fā)時(shí)的多個(gè)程序員分工合作子程序(Subroutine)=函數(shù)(Function)=過(guò)程(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/mem48 ;調(diào)用存儲(chǔ)單元指定地址的子程序2.子程序返回指令RETRET指令用在子程序結(jié)束,實(shí)現(xiàn)返回主程序

RET

;無(wú)參數(shù)返回:出棧返回地址

RETi16 ;有參數(shù)返回:出棧返回地址

;ESP←ESP+i16MASM會(huì)根據(jù)存儲(chǔ)模型等信息確定子程序的遠(yuǎn)近調(diào)用,并相應(yīng)產(chǎn)生返回指令3.過(guò)程定義偽指令MASM利用過(guò)程定義偽指令獲得子程序信息

過(guò)程名 PROC

…… ;過(guò)程體

過(guò)程名 ENDP

;過(guò)程名為符合語(yǔ)法的標(biāo)識(shí)符PROC后面可加參數(shù):NEAR或FAR簡(jiǎn)化段定義源程序格式中,通常不需指定過(guò)程屬性,采用默認(rè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 ;過(guò)程定義,過(guò)程名為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 ;過(guò)程結(jié)束MOV[EBP+4],EDI?子程序調(diào)用的堆棧4.3.2子程序設(shè)計(jì)子程序的編寫方法與主程序一樣但需要留意幾個(gè)問題:利用過(guò)程定義,獲得子程序名和調(diào)用屬性RET指令返回主程序,CALL指令調(diào)用子程序壓入和彈出操作要成對(duì)使用,保持堆棧平衡開始保護(hù)寄存器,返回前相應(yīng)恢復(fù)安排在代碼段的主程序之外子程序允許嵌套和遞歸最好有完整的注釋難點(diǎn)是參數(shù)傳遞回車換行子程序DPCRLFdpcrlf proc ;回車換行子程序

pusheax ;保護(hù)寄存器

moval,0dh ;輸出回車字符

calldispc ;子程序中調(diào)用子程序,實(shí)現(xiàn)子程序嵌套

moval,0ah ;輸出換行字符

calldispc ;子程序中調(diào)用子程序,實(shí)現(xiàn)子程序嵌套

popeax ;恢復(fù)寄存器

ret ;子程序返回dpcrlf endp4.3.3參數(shù)傳遞主程序與子程序間通過(guò)參數(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-15〕十六進(jìn)制顯示程序-1

moveax,1234abcdh ;假設(shè)一個(gè)數(shù)據(jù)

xorebx,ebx movecx,8 ;8位十六進(jìn)制數(shù)again: roleax,4 ;高4位循環(huán)移位進(jìn)入低4位

pusheax ;movedx,eax callhtoasc ;調(diào)用子程序

movregd+4[ebx],al ;保存轉(zhuǎn)換后的ASCII碼

popeax ;moveax,edx 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 endp2.共享變量傳遞參數(shù)子程序和主程序使用同一個(gè)變量名存取數(shù)據(jù)就是利用共享變量(全局變量)進(jìn)行參數(shù)傳遞如果變量定義和使用不在同一個(gè)程序模塊中,需要利用PUBLIC、EXTREN聲明利用共享變量傳遞參數(shù),子程序的通用性較差特點(diǎn):特別適合在多個(gè)程序段間、尤其在不同的程序模塊間傳遞數(shù)據(jù)〔例4-17〕二進(jìn)制輸入程序3.堆棧傳遞參數(shù)傳遞傳輸還可以通過(guò)堆棧這個(gè)臨時(shí)存儲(chǔ)區(qū)主程序?qū)⑷肟趨?shù)壓入堆棧,子程序從堆棧中取出參數(shù)出口參數(shù)通常不使用堆棧傳遞高級(jí)語(yǔ)言堆棧高級(jí)語(yǔ)言進(jìn)行函數(shù)調(diào)用時(shí)提供的參數(shù),實(shí)質(zhì)也利用堆棧傳遞的,高級(jí)語(yǔ)言還利用堆棧創(chuàng)建局部變量。采用堆棧傳遞參數(shù)是程式化的,它是編譯程序處理參數(shù)傳遞、以及匯編語(yǔ)言與高級(jí)語(yǔ)言混合編程時(shí)的常規(guī)方法保存參數(shù)和局部變量的堆棧區(qū)域稱為堆棧幀(StackFrame),他在函數(shù)調(diào)用時(shí)建立,返回后消失。〔例4-19〕計(jì)算有符號(hào)數(shù)平均值程序利用堆棧傳遞參數(shù)返回4.3.4程序模塊程序分段、子程序等是進(jìn)行程序模塊化開發(fā)大型程序時(shí)采用的方法子程序模塊子程序庫(kù)庫(kù)文件包含宏匯編源文件包含4.1分支程序結(jié)構(gòu)4.2循環(huán)程序結(jié)構(gòu) 4.3子程序結(jié)構(gòu)4.4Windows應(yīng)用程序編程(自學(xué))4.5與C++語(yǔ)言的混合編程(自學(xué))本章內(nèi)容4.1分支程序結(jié)構(gòu)4.2循環(huán)程序結(jié)構(gòu) 4.3子程序結(jié)構(gòu)4.4Windows應(yīng)用程序編程4.5與C++語(yǔ)言的混合編程本章內(nèi)容4.4Windows應(yīng)用程序編程匯編語(yǔ)言可以編寫32位Windows應(yīng)用程序調(diào)用Windows的應(yīng)用程序接口API運(yùn)行于Windows操作系統(tǒng)平臺(tái)可以利用Windows的高級(jí)特性,生成的可執(zhí)行文件相對(duì)較小、性能更高從更深層次理解Windows運(yùn)行機(jī)制及程序設(shè)計(jì)思想4.4.1操作系統(tǒng)函數(shù)調(diào)用操作系統(tǒng)以其提供的系統(tǒng)函數(shù)(系統(tǒng)功能Systemfunction)支持程序員進(jìn)行編程Windows的系統(tǒng)函數(shù)(功能)以動(dòng)態(tài)連接庫(kù)DLL(Dynamic-LinkLibrary)形式提供,利用其應(yīng)用程序接口API(ApplicationProgramInterface)調(diào)用DDL庫(kù)中的函數(shù)API是一些類型、常量和函數(shù)的集合,提供了編程中使用庫(kù)函數(shù)的途徑Win16:16位Windows的APIWin32:32位Windows的API1.動(dòng)態(tài)連接庫(kù)靜態(tài)連接:連接程序從庫(kù)文件中抽取需要的子程序插入到最終的可執(zhí)行代碼中動(dòng)態(tài)連接:程序運(yùn)行時(shí)才將代碼加載到主存動(dòng)態(tài)連接庫(kù):保存程序運(yùn)行時(shí)需要重復(fù)使用的代碼的文件3個(gè)最重要的Windows動(dòng)態(tài)連接庫(kù)KERNEL32.DLL:主要處理內(nèi)存管理和進(jìn)程調(diào)度USER32.DLL:主要控制用戶界面GDI32.DLL:負(fù)責(zé)圖形方面的操作導(dǎo)入庫(kù)(ImportLibrary):程序開發(fā)的連接階段使用,與一個(gè)動(dòng)態(tài)連接庫(kù)DLL對(duì)應(yīng)2.MASM的高級(jí)語(yǔ)言特性條件控制偽指令:.IF.ELSEIF.ELSE.ENDIF流程控制偽指令:.WHILE.ENDW.REPEAT.UNTIL.REPEAT.UNTILCXZ.BREAK.CONTINUE過(guò)程聲明偽指令PROTO:事先聲明過(guò)程的結(jié)構(gòu) (包括操作系統(tǒng)API函數(shù)、高級(jí)語(yǔ)言的函數(shù)) 過(guò)程名 PROTO [調(diào)用距離][語(yǔ)言類型] [,參數(shù)∶[類型]]...過(guò)程調(diào)用偽指令I(lǐng)NVOKE:實(shí)現(xiàn)過(guò)程調(diào)用

INVOKE 過(guò)程名[,參數(shù),...]3.程序退出函數(shù)Win32程序員參考手冊(cè)VOIDExitProcess(UINTuExitCode //exitcodeforallthreads);匯編語(yǔ)言聲明ExitProcessPROTO,:DWORD匯編語(yǔ)言調(diào)用invoke

ExitProcess,0將函數(shù)調(diào)用定義成宏exit MACROdwexitcode

invokeExitProcess,dwexitcode

ENDM宏調(diào)用exit 04.4.2控制臺(tái)應(yīng)用程序Windows應(yīng)用程序開始運(yùn)行創(chuàng)建控制臺(tái)(Console)窗口或創(chuàng)建圖形界面窗口32位Windows控制臺(tái)程序像增強(qiáng)版的MS-DOS程序使用標(biāo)準(zhǔn)控制臺(tái)

標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)

標(biāo)準(zhǔn)輸出設(shè)備(顯示器)32位控制臺(tái)程序運(yùn)行在保護(hù)方式通過(guò)API使用Windows的動(dòng)態(tài)鏈接庫(kù)函數(shù)1.處理器識(shí)別指令CPUID返回處理器特征信息的指令當(dāng)EAX=0時(shí)執(zhí)行CPUID指令EAX返回CPUID指令中能夠賦給EAX的最大值EBX、EDX和ECX返回生產(chǎn)廠商的標(biāo)識(shí)串GenuineIntel利用這個(gè)廠商標(biāo)識(shí)串,確認(rèn)是Intel公司處理器當(dāng)EAX=1或2等值時(shí)執(zhí)行CPUID指令返回處理器更詳細(xì)的識(shí)別信息例如處理器型號(hào)、支持的指令集等〔例4-21〕處理器識(shí)別程序-1

.686 .modelflat,stdcall optioncasemap:none

includelibbin\kernel32.libExitProcess proto,:DWORDGetStdHandle proto,:DWORDWriteConsoleA\proto,:DWORD,:DWORD,:DWORD,:DWORD,:DWORDWriteConsole equ<WriteConsoleA>STD_OUTPUT_HANDLE=-11 .dataouthandle dword?outbuffer byte'TheprocessorvendorIDis' byte12dup(0)outbufsize =sizeofoutbufferoutsize dword?控制臺(tái)句柄控制臺(tái)輸出〔例4-21〕處理器識(shí)別程序-2 .codestart: moveax,0 cpuid ;執(zhí)行處理器識(shí)別指令

movdwordptroutbuffer+outbufsize-12,ebx movdwordptroutbuffer+outbufsize-8,edx movdwordptroutbuffer+outbufsize-4,ecx ;獲得輸出句柄

invokeGetStdHandle,STD_OUTPUT_HANDLE

movouthandle,eax ;顯示信息

invokeWriteConsole,outhandle,\ addroutbuffer,outbufsize,addroutsize,0 ;退出

invokeExitProcess,0

endstartTheprocessorvendorIDisGenuineIntel運(yùn)行結(jié)果2.控制臺(tái)句柄句柄(Handle)是一個(gè)32位無(wú)符號(hào)整數(shù)用來(lái)唯一確定一個(gè)對(duì)象例如某個(gè)輸入設(shè)備、輸出設(shè)備或者一個(gè)圖形標(biāo)準(zhǔn)輸入句柄

STD_INPUT_HANDLE

=-10標(biāo)準(zhǔn)輸出句柄

STD_OUTPUT_HANDLE

=-11標(biāo)準(zhǔn)錯(cuò)誤句柄

STD_ERROR_HANDLE

=-12GetStdHandle函數(shù)獲取控制臺(tái)輸入或輸出的句柄實(shí)例用于控制臺(tái)程序的輸入輸出操作返回3.控制臺(tái)輸出函數(shù)顯示器輸出API函數(shù)WriteConsole將一個(gè)字符串輸出到屏幕上支持標(biāo)準(zhǔn)的ASCII控制字符,例如回車、換行等Win32API中可以使用兩種字符集8位ASCII字符集,函數(shù)名以字母A結(jié)尾16位Unicode字符集,函數(shù)名以字母W結(jié)尾WriteConsole參數(shù)第一個(gè):控制臺(tái)輸出句柄實(shí)例第二個(gè):指向字符串的指針、即緩沖區(qū)地址第三個(gè):指明字符串長(zhǎng)度,是一個(gè)32位整數(shù)第四個(gè):指向一個(gè)整數(shù)變量,返回實(shí)際輸出的字符數(shù)第五個(gè):保留,設(shè)置為0返回4.控制臺(tái)輸入函數(shù)鍵盤輸入API函數(shù)ReadConsole將鍵盤輸入的文本保存到一個(gè)緩沖區(qū)第一個(gè):控制臺(tái)輸入句柄實(shí)例第二個(gè):輸入緩沖區(qū)指針第三個(gè):要讀取字符的最大數(shù)量第四個(gè):實(shí)際輸入字符數(shù)量的指針第五個(gè):未使用,設(shè)置為0調(diào)用ReadConsole函數(shù)時(shí)系統(tǒng)等待用戶輸入、并回車確認(rèn)(例如用戶輸入了3個(gè)字符,依次是123)第4個(gè)參數(shù)的變量保存用戶輸入字符個(gè)數(shù)再加2的結(jié)果(例如本例是5)(內(nèi)容用十六進(jìn)制數(shù)表達(dá)依次是3132330D0A)定義輸入緩沖區(qū)要多留兩個(gè)字節(jié)〔例4-22〕信息輸入輸出程序-1

.686 .modelflat,stdcall optioncasemap:none includelibbin\kernel32.libExitProcess proto,:DWORDexit MACROdwexitcode invokeExitProcess,dwexitcode ENDMGetStdHandle proto,:DWORDWriteConsoleAproto,:DWORD,:DWORD,:DWORD,:DWORD,:DWORDWriteConsole equ<WriteConsoleA>ReadConsoleA proto,:DWORD,:DWORD,:DWORD,:DWORD,:DWORDReadConsole equ<ReadConsoleA>STD_INPUT_HANDLE=-10STD_OUTPUT_HANDLE=-11〔例4-22〕信息輸入輸出程序-2 .datamsg1 byte'Pleaseenteryourname:',0msg2 byte'Welcome',0nbuf byte80dup(0)msg3 byte'toWin32Console!',0_outsize dword?_outhandle dword?_insize dword?_inbuffer byte255dup(0) ;設(shè)置輸入緩沖區(qū)最大255個(gè)字符〔例4-22〕信息輸入輸出程序-3

.codestart: moveax,offsetmsg1 ;提示輸入

calldispmsg

moveax,offsetnbuf ;輸入信息

callreadmsg

moveax,offsetmsg2

calldispmsg

moveax,offsetnbuf ;顯示輸入信息

calldispmsg

moveax,offsetmsg3

calldispmsg

exit0〔例4-22〕信息輸入輸出程序-4dispmsg proc ;字符串顯示子程序

pusheax ;入口參數(shù):EAX=字符串地址

pushebx pushecx pushedx pusheax ;保存入口參數(shù),即字符串地址

invokeGetStdHandle,STD_OUTPUT_HANDLE mov_outhandle,eax

popebx ;EBX=字符串地址

xorecx,ecx ;計(jì)算字符串長(zhǎng)度dispm1: moval,[ebx+ecx] testal,al jzdispm2 incecx jmpdispm1〔例4-22〕信息輸入輸出程序-5dispm2:

invokeWriteConsole,_outhandle,\ ebx,ecx,addr_outsize,0 popedx popecx popebx popeax retdispmsg endpreadmsg proc ;字符串輸入子程序

pushebx ;入口參數(shù):EAX=緩沖區(qū)地址

pushecx

pushedx〔例4-22〕信息輸入輸出程序-6

pusheax ;保護(hù)輸入的緩沖區(qū)地址參數(shù)

invokeGetStdHandle,STD_INPUT_HANDLE invokeReadConsole,\ eax,addr_inbuffer,255,addr_insize,0 sub_insize,2

xorecx,ecx popebx ;獲得緩沖區(qū)地址readm1: moval,_inbuffer[ecx] mov[ebx+ecx],al ;將輸入的字符串復(fù)制到用戶緩沖區(qū)

incecx cmpecx,_insize jbreadm1〔例4-22〕信息輸入輸出程序-7 movbyteptr[ebx+ecx],0 ;最后填入結(jié)尾字符0 moveax,ecx popedx popecx popebx retreadmsg endp endstartPleaseenteryourname:JerryWelcomeJerrytoWin32Console!運(yùn)行結(jié)果4.4.3圖形窗口應(yīng)用程序消息窗口是常見的Windows圖形窗口顯示形式使用MessageBox函數(shù)Win32程序員參考手冊(cè)的定義intMessageBox(HWNDhWnd,LPCTSTRlpText,LPCTSTRlpCaption,UINTuType);hWnd:父窗口的句柄lpText:要顯示字符串的地址指針,字符串的首地址lpCaption:消息窗標(biāo)題的地址指針uType:指明該消息窗的類型〔例4-23〕消息窗口程序-1

.686 .modelflat,stdcall optioncasemap:none includelibbin\kernel32.lib includelibbin\user32.libExitProcess proto,:DWORDMessageBoxA PROTO:DWORD,:DWORD,:DWORD,:DWORDMessageBox equ<MessageBoxA>NULL equ0MB_OK equ0 .dataszCaption byte'消息窗口',0outbuffer byte'本機(jī)的處理器是',12dup(0),0outbufsize =sizeofoutbuffer-1〔例4-23〕消息窗口程序-2 .codestart: moveax,0 cpuid ;獲得顯示器信息

movdwordptroutbuffer+outbufsize-12,ebx movdwordptroutbuffer+outbufsize-8,edx movdwordptroutbuffer+outbufsize-4,ecx

invokeMessageBox,\ NULL,addroutbuffer,addrszCaption,MB_OK invokeExitProcess,NULL

endstart操作演示連接時(shí)應(yīng)該使用參數(shù)/subsystem:windows消息窗口程序END4.5與C++語(yǔ)言的混合編程軟件開發(fā)通常采用高級(jí)語(yǔ)言,以提高開發(fā)效率某些部分需要利用匯編語(yǔ)言,以提高程序的運(yùn)行效率,因?yàn)閰R編語(yǔ)言的優(yōu)點(diǎn):開發(fā)的程序占用存儲(chǔ)空間小、運(yùn)行速度快等匯編語(yǔ)言的缺點(diǎn):與機(jī)器密切相關(guān)、移植性差,編程煩瑣、對(duì)匯編語(yǔ)言程序員要求較高混合編程:匯編語(yǔ)言與高級(jí)語(yǔ)言、或高級(jí)語(yǔ)言間,通過(guò)相互調(diào)用、參數(shù)傳遞、共享數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)信息而形成程序的過(guò)程匯編語(yǔ)言與C和C++語(yǔ)言的混合編程嵌入?yún)R編模塊連接MASM6.

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論