版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第5章模塊化程序設(shè)計(jì)5.1子程序結(jié)構(gòu)5.2參數(shù)傳遞5.3多模塊程序結(jié)構(gòu)5.4宏結(jié)構(gòu)第5章模塊化程序設(shè)計(jì)以子程序結(jié)構(gòu)為主體,圍繞數(shù)碼轉(zhuǎn)換實(shí)現(xiàn)鍵盤輸入和顯示輸出掌握子程序、文件包含、宏匯編等各種多模塊編程的方法35.1子程序結(jié)構(gòu)經(jīng)常用到的應(yīng)用問(wèn)題編寫成一個(gè)通用子程序大型處理過(guò)程分解成能夠解決的模塊使用子程序可以使程序的結(jié)構(gòu)更為清楚程序的維護(hù)更為方便有利于大程序開發(fā)時(shí)的多個(gè)程序員分工合作子程序(Subroutine)=函數(shù)(Function)=過(guò)程(Procedure)45.1.1子程序指令子程序與主程序分開、完成特定功能的一段程序主程序(調(diào)用程序)執(zhí)行調(diào)用指令CALL調(diào)用子程序子程序(被調(diào)用程序)執(zhí)行返回指令RET返回主程序CALLlabel主程序RET子程序回到CALL指令后的指令處51.子程序調(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)指定的子程序
CALLreg32/reg16
;調(diào)用寄存器指定地址的子程序
CALLmem48/mem32/mem16 ;調(diào)用存儲(chǔ)單元指定地址的子程序62.子程序返回指令RETRET指令用在子程序結(jié)束,實(shí)現(xiàn)返回主程序
RET
;無(wú)參數(shù)返回:出棧返回地址
RETi16 ;有參數(shù)返回:出棧返回地址
;ESP←ESP+i16MASM會(huì)根據(jù)存儲(chǔ)模型等信息確定子程序的遠(yuǎn)近調(diào)用,并相應(yīng)產(chǎn)生返回指令7name …
RET
CALLnamenext:… ;下條指令CALL的調(diào)用和RET的返回主程序子程序堆棧next;思考如下代碼片段的功能 callnextnext: popeax
;EAX=?83.過(guò)程定義偽指令MASM利用過(guò)程定義偽指令獲得子程序信息
過(guò)程名 PROC
…… ;過(guò)程體
過(guò)程名 ENDP
;過(guò)程名為符合語(yǔ)法的標(biāo)識(shí)符PROC后面可加參數(shù):NEAR或FAR簡(jiǎn)化段定義源程序格式中,通常不需指定9〔例5-1〕子程序調(diào)用程序-1
;代碼段,主程序00000000 B800000001
moveax,100000005 BD00000005
movebp,50000000A E800000016
callsubp
;子程序調(diào)用0000000F B900000003 retp1: movecx,300000014 BA00000004 retp2: movedx,400000019 E800000000E
calldisprd10〔例5-1〕子程序調(diào)用程序-2 ;代碼段,子程序subp proc ;過(guò)程定義,過(guò)程名為subp
pushebp
mov
ebp,esp
movesi,[ebp+4] ;ESI=CALL下條指令(標(biāo)號(hào)RETP1)偏移地址
mov
edi,offsetretp2 ;EDI=標(biāo)號(hào)RETP2的偏移地址
movebx,2
popebp ;彈出堆棧,保持堆棧平衡
ret ;子程序返回subp
endp ;過(guò)程結(jié)束MOV[EBP+4],EDI?示意圖11子程序調(diào)用的堆棧返回125.1.2子程序設(shè)計(jì)子程序的編寫方法與主程序一樣但需要留意幾個(gè)問(wèn)題:利用過(guò)程定義,獲得子程序名和調(diào)用屬性RET指令返回主程序,CALL指令調(diào)用子程序壓入和彈出操作要成對(duì)使用,保持堆棧平衡開始保護(hù)寄存器,返回前相應(yīng)恢復(fù)安排在代碼段的主程序之外子程序允許嵌套和遞歸最好有完整的注釋難點(diǎn)是參數(shù)傳遞13〔例5-2〕回車換行子程序dpcrlf proc ;回車換行子程序
pusheax ;保護(hù)寄存器
moval,0dh ;輸出回車字符
calldispc ;子程序中調(diào)用子程序,實(shí)現(xiàn)子程序嵌套
moval,0ah ;輸出換行字符
calldispc
popeax ;恢復(fù)寄存器
ret ;子程序返回dpcrlf
endp145.2參數(shù)傳遞主程序與子程序間通過(guò)參數(shù)傳遞建立聯(lián)系入口參數(shù)(輸入?yún)?shù)):主程序→子程序出口參數(shù)(輸出參數(shù)):子程序→主程序傳遞參數(shù)的多少反映程序模塊間的耦合程度參數(shù)的具體內(nèi)容數(shù)據(jù)本身(傳遞數(shù)值)數(shù)據(jù)的存儲(chǔ)地址(傳遞地址,傳遞引用)參數(shù)傳遞方法寄存器變量堆棧155.2.1寄存器傳遞參數(shù)最簡(jiǎn)單和常用的參數(shù)傳遞方法把參數(shù)存于約定的寄存器少量數(shù)據(jù)直接傳遞數(shù)值大量數(shù)據(jù)只能傳遞地址帶有出口參數(shù)的寄存器不能保護(hù)和恢復(fù)帶有入口參數(shù)的寄存器可以保護(hù)、也可以不保護(hù),但最好能夠保持一致16〔例5-3〕十六進(jìn)制顯示程序-1
mov
eax,1234abcdh ;假設(shè)一個(gè)數(shù)據(jù)
xor
ebx,ebx
movecx,8 ;8位十六進(jìn)制數(shù)again: roleax,4 ;高4位循環(huán)移位進(jìn)入低4位
pusheax ;mov
edx,eax
callhtoasc ;調(diào)用子程序
movregd+4[ebx],al ;保存轉(zhuǎn)換后的ASCII碼
popeax ;mov
eax,edx
incebx
dec
ecx
jnzagain
mov
eax,offset
regd calldispmsg ;顯示regddb'EAX=',8dup(0),'H',017〔例5-3〕十六進(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
jbe
htoend
addal,7 ;是A~F,ASCII碼再加上7htoend:
ret ;子程序返回htoasc
endp18〔例5-3〕十六進(jìn)制顯示程序-3
;子程序htoasc proc
andeax,0fh ;取AL低4位
mov
al,ASCII[eax] ;換碼
ret ;子程序的局部數(shù)據(jù)(只讀)ASCII db'0123456789ABCDEF'htoasc
endpEAX=1234ABCDH運(yùn)行結(jié)果19〔例5-4〕有符號(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ù)字20〔例5-4〕有符號(hào)十進(jìn)制數(shù)顯示程序-2
;數(shù)據(jù)段array dd1234567890,-1234,0,1,...count equ($-array)/4writebuf db12dup(0) ;顯示緩沖區(qū)
;代碼段
mov
ecx,count
movebx,0again: mov
eax,array[ebx*4] ;EAX=入口參數(shù)
callwrite ;調(diào)用子程序,顯示一個(gè)數(shù)據(jù)
calldispcrlf ;換行以便顯示下一個(gè)數(shù)據(jù)
incebx
dec
ecx
jnzagain寄存器傳遞參數(shù)21〔例5-4〕有符號(hào)十進(jìn)制數(shù)顯示程序-3 ;顯示有符號(hào)十進(jìn)制數(shù)的子程序write proc ;EAX=入口參數(shù)
pushebx ;保護(hù)寄存器
pushecx pushedx
mov
ebx,offset
writebuf ;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)寄存器傳遞參數(shù)22〔例5-4〕有符號(hào)十進(jìn)制數(shù)顯示程序-4
movbyteptr[ebx],'-';是負(fù)數(shù),設(shè)置負(fù)號(hào)
incebx
neg
eax ;數(shù)據(jù)求補(bǔ)(絕對(duì)值)write2: movecx,10
pushecx ;10壓入堆棧,作為退出標(biāo)志write3: cmpeax,0 ;數(shù)據(jù)(商)為零,轉(zhuǎn)向保存
jzwrite4
xor
edx,edx ;零位擴(kuò)展被除數(shù)為EDX.EAX
divecx ;數(shù)據(jù)除以10:EDX.EAX÷10
addedx,30h ;余數(shù)(0~9)轉(zhuǎn)換為ASCII碼
pushedx ;數(shù)據(jù)先低位后高位壓入堆棧
jmpwrite323〔例5-4〕有符號(hào)十進(jìn)制數(shù)顯示程序-5write4: popedx ;數(shù)據(jù)先高位后低位彈出堆棧
cmp
edx,ecx ;是結(jié)束標(biāo)志10,轉(zhuǎn)向顯示
jewrite5
mov[ebx],dl ;數(shù)據(jù)保存到緩沖區(qū)
incebx
jmpwrite4write5: movbyteptr[ebx],0 ;顯示內(nèi)容加上結(jié)尾標(biāo)志
mov
eax,offset
writebuf calldispmsg
popedx ;恢復(fù)寄存器
popecx popebx
ret ;子程序返回write endp245.2.2共享變量傳遞參數(shù)子程序和主程序使用同一個(gè)變量名存取數(shù)據(jù)如果變量定義和使用不在同一個(gè)程序模塊中,需要利用PUBLIC、EXTREN聲明共享變量傳遞參數(shù),子程序的通用性較差特別適合在多個(gè)程序段間、尤其在不同的程序模塊間傳遞數(shù)據(jù)25〔例5-5〕二進(jìn)制輸入程序-1
;數(shù)據(jù)段count equ5array ddcountdup(0)temp dd0 ;共享變量
;代碼段,主程序
mov
ecx,count
mov
ebx,offsetarrayagain: callrdbd
;調(diào)用子程序,輸入一個(gè)數(shù)據(jù)
mov
eax,[temp]
;獲得出口參數(shù)
mov[ebx],eax
;存放到數(shù)據(jù)緩沖區(qū)
addebx,4 loopagain共享變量傳遞參數(shù)26〔例5-5〕二進(jìn)制輸入程序-2
;代碼段,子程序rdbd proc
;二進(jìn)制輸入子程序
pusheax
;出口參數(shù):共享變量TEMP
pushebx pushecxrdbd1: xor
ebx,ebx
;EBX用于存放二進(jìn)制結(jié)果
movecx,32
;限制輸入字符的個(gè)數(shù)rdbd2: callreadc
;輸入一個(gè)字符
cmpal,'0'
;檢測(cè)鍵入字符是否合法
jb
rderr
;不合法則返回重新輸入
cmpal,'1'
ja
rderr27〔例5-5〕二進(jìn)制輸入程序-3
subal,'0'
;對(duì)輸入的字符進(jìn)行轉(zhuǎn)化
shlebx,1
;EBX的值乘以2
orbl,al
;BL和AL相加
looprdbd2
;循環(huán)鍵入字符
mov
[temp],ebx
;把二進(jìn)制結(jié)果存放TEMP返回
calldispcrlf
;分行
popecx popebx popeax
ret共享變量傳遞參數(shù)28〔例5-5〕二進(jìn)制輸入程序-4rderr: mov
eax,offset
errmsg ;顯示錯(cuò)誤信息
calldispmsg
jmprdbd1errmsg db0dh,0ah,'Inputerror,enteragain:',0rdbd
endp29〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-1十進(jìn)制有符號(hào)整數(shù)轉(zhuǎn)換為補(bǔ)碼的算法如下: 1)判斷輸入了正數(shù)、還是負(fù)數(shù),用一個(gè)寄存器記錄 2)判斷下一個(gè)字符是否為有效數(shù)碼 字符無(wú)效,提示錯(cuò)誤重新輸入,并轉(zhuǎn)向(1) 字符有效,繼續(xù) 3)字符有效,減30H轉(zhuǎn)換為二進(jìn)制數(shù);然后將前面輸入的數(shù)值乘10,并與剛輸入的數(shù)字相加得到新的數(shù)值 4)判斷輸入的數(shù)據(jù)是否超出有效范圍超出范圍,提示錯(cuò)誤重新輸入,并轉(zhuǎn)向(1)沒(méi)有超出范圍,則繼續(xù) 5)重復(fù)第(2)~(4)步,輸入字符都有效,一直處理完 6)是負(fù)數(shù)進(jìn)行求補(bǔ),轉(zhuǎn)換成補(bǔ)碼;否則直接將數(shù)值保存30〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-2
;數(shù)據(jù)段count equ10array ddcountdup(0)temp dd0readbuf db30dup(0) ;代碼段
mov
ecx,count
mov
ebx,offsetarrayagain: callread ;調(diào)用子程序,輸入一個(gè)數(shù)據(jù)
mov
eax,[temp] ;獲得出口參數(shù)
mov[ebx],eax ;存放到數(shù)據(jù)緩沖區(qū)
addebx,4
dec
ecx
jnzagain共享變量傳遞參數(shù)31〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-3 ;輸入有符號(hào)十進(jìn)制數(shù)的子程序read proc ;出口參數(shù):變量TEMP=補(bǔ)碼表示的二進(jìn)制數(shù)值
pusheax ;說(shuō)明:負(fù)數(shù)用“-”引導(dǎo)
pushebx
pushecx pushedxread0: mov
eax,offset
readbuf
callreadmsg ;輸入一個(gè)字符串
testeax,eax
jz
readerr ;沒(méi)有輸入數(shù)據(jù),錯(cuò)誤
cmpeax,12
ja
readerr ;輸入超過(guò)12個(gè)字符,錯(cuò)誤32〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-4
mov
edx,offset
readbuf;EDX指向輸入緩沖區(qū)
xor
ebx,ebx ;EBX保存結(jié)果
xor
ecx,ecx ;ECX為正負(fù)標(biāo)志,0為正,-1為負(fù)
mov
al,[edx] ;取一個(gè)字符
cmpal,'+' ;是“+”,繼續(xù)
jzread1
cmpal,'-' ;是“-”,設(shè)置-1標(biāo)志
jnzread2
movecx,-1read1: incedx ;取下一個(gè)字符
mov
al,[edx]
testal,al ;是結(jié)尾0,轉(zhuǎn)向求補(bǔ)碼
jzread333〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-5read2: cmpal,'0' ;不是0~9之間的數(shù)碼,錯(cuò)誤
jb
readerr
cmpal,'9'
ja
readerr subal,30h ;是0~9之間的數(shù)碼,轉(zhuǎn)換
imulebx,10 ;原數(shù)值乘10:EBX=EBX×10
jc
readerr ;CF=1,乘積溢出,出錯(cuò)
movzx
eax,al ;零位擴(kuò)展,便于相加
addebx,eax ;原數(shù)乘10后,與新數(shù)碼相加
cmpebx,80000000h ;數(shù)據(jù)超過(guò)231,出錯(cuò)
jberead1 ;繼續(xù)轉(zhuǎn)換下一個(gè)數(shù)位34〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-6readerr: mov
eax,offset
errmsg ;顯示出錯(cuò)信息
calldispmsg
jmpread0 ;read3: testecx,ecx ;判斷是正數(shù)還是負(fù)數(shù)
jzread4
neg
ebx ;是負(fù)數(shù),進(jìn)行求補(bǔ)
jmpread5read4: cmpebx,7fffffffh ;正數(shù)超過(guò)231-1,出錯(cuò)
ja
readerr35〔例5-6〕有符號(hào)十進(jìn)制數(shù)輸入程序-7read5: mov
[temp],ebx ;設(shè)置出口參數(shù)
popedx popecx popebx popeax
ret ;子程序返回errmsg db'Inputerror,enteragain:',0read endp共享變量傳遞參數(shù)365.2.3堆棧傳遞參數(shù)主程序?qū)⑷肟趨?shù)壓入堆棧,子程序從堆棧中取出參數(shù)出口參數(shù)通常不使用堆棧傳遞高級(jí)語(yǔ)言進(jìn)行函數(shù)調(diào)用時(shí)提供的參數(shù),實(shí)質(zhì)也利用堆棧傳遞采用堆棧傳遞參數(shù)是程式化的,它是編譯程序處理參數(shù)傳遞、以及匯編語(yǔ)言與高級(jí)語(yǔ)言混合編程時(shí)的常規(guī)方法37〔例5-7〕計(jì)算有符號(hào)數(shù)平均值程序-1
;數(shù)據(jù)段array dd675,354,-34,...count equ($-array)/4 ;代碼段
pushdwordptrcount ;壓入數(shù)據(jù)個(gè)數(shù)
pushoffsetarray ;壓數(shù)組的偏移地址
callmean ;調(diào)用求平均值子程序
;出口參數(shù):EAX=平均值(整數(shù))
addesp,8 ;平衡堆棧(壓入了8個(gè)字節(jié)數(shù)據(jù))
calldispsid ;顯示堆棧傳遞參數(shù)38〔例5-7〕計(jì)算有符號(hào)數(shù)平均值程序-2
;計(jì)算32位有符號(hào)數(shù)平均值子程序mean proc ;入口參數(shù):順序壓入數(shù)據(jù)個(gè)數(shù)和數(shù)組偏移地址
pushebp ;出口參數(shù):EAX=平均值
mov
ebp,esp
pushebx ;保護(hù)寄存器
pushecx pushedx
movebx,[ebp+8] ;EBX=取出的偏移地址
movecx,[ebp+12]
;ECX=取出的數(shù)據(jù)個(gè)數(shù)
xor
eax,eax ;EAX保存和值
xor
edx,edx ;EDX=指向數(shù)組元素堆棧傳遞參數(shù)39〔例5-7〕計(jì)算有符號(hào)數(shù)平均值程序-3mean1: addeax,[ebx+edx*4] ;求和
addedx,1 ;指向下一個(gè)數(shù)據(jù)
cmp
edx,ecx ;比較個(gè)數(shù)
jbmean1 ;循環(huán)
cdq ;將累加和EAX符號(hào)擴(kuò)展到EDX
idiv
ecx ;有符號(hào)數(shù)除法,EAX=平均值
popedx ;恢復(fù)寄存器
popecx popebx
popebp
retmean endp求和溢出與個(gè)數(shù)為0的問(wèn)題?示意圖40利用堆棧傳遞參數(shù)返回415.3多模塊程序結(jié)構(gòu)程序分段、子程序等實(shí)現(xiàn)了程序模塊化開發(fā)大型應(yīng)用程序時(shí)常使用多個(gè)源程序文件、目標(biāo)代碼模塊等組成完整的程序MASM具體支持的方法源文件包含模塊連接子程序庫(kù)庫(kù)文件包含425.3.1源文件包含大型源程序可以合理地分放在若干個(gè)文本文件中各種常量定義、聲明語(yǔ)句等組織在包含文件(*.INC)常用的或有價(jià)值的宏定義存放在宏定義文件(*.MAC)常用的子程序形成匯編語(yǔ)言源文件(*.ASM)任何文本文件使用源文件包含偽指令I(lǐng)NCLUDE將指定的文本文件內(nèi)容插入主體源程序文件
INCLUDE文件名利用INCLUDE偽指令包含其他文件,其實(shí)質(zhì)仍然是一個(gè)源程序,只不過(guò)是分在了幾個(gè)文件書寫子程序庫(kù)文件名要符合操作系統(tǒng)規(guī)范43〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-1;文件名:eg0508.inc,例5-8程序的數(shù)據(jù)段內(nèi)容
.data ;數(shù)據(jù)段dvar
dd1234abcdhinmsg db'EnterMemoryAddress:',0outmsg1 db'MemoryDataInHexDecimal:',0outmsg1 db'MemoryDataInSignedDecimal:',0temp dd0 ;共享變量writebuf db12dup(0) ;十進(jìn)制輸出的顯示緩沖區(qū)包含文件44〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-2;文件名:eg0508.asm,例5-8主程序
includeio32.inc ;源文件包含:32位I/O文件
includeeg0508.inc ;源文件包含:數(shù)據(jù)段文件
.code ;代碼段,主程序start: mov
dwordptr[temp],offset
dvar calldphd ;十六進(jìn)制輸出,顯示變量DVAR地址以便輸入
calldispcrlf
mov
eax,offset
inmsg calldispmsg
callrdhd ;輸入存儲(chǔ)器地址,EAX返回
calldispcrlf主程序文件45〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-3
mov
ebx,[eax] ;EBX=存儲(chǔ)器數(shù)據(jù)
mov
eax,offsetoutmsg1 calldispmsg
mov[temp],ebx ;共享變量傳遞參數(shù)
calldphd ;十六進(jìn)制輸出
calldispcrlf
mov
eax,offsetoutmsg2 calldispmsg
mov
eax,ebx ;寄存器傳遞參數(shù)
callwrite ;十進(jìn)制輸出
exit0 ;主程序結(jié)束,退出
includeeg0508s.asm ;源文件包含:子程序文件
endstart主程序文件46〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-4;文件名:eg0508s.asm,例5-8程序的子程序rdhd proc ;十六進(jìn)制輸入子程序
pushebx ;出口參數(shù):EAX=輸入的數(shù)據(jù)
pushecxrdhd1: xor
ebx,ebx ;EBX用于存放十六進(jìn)制結(jié)果
movecx,8 ;限制輸入字符的個(gè)數(shù)rdhd2: callreadc ;輸入一個(gè)字符
cmpal,'0' ;檢測(cè)鍵入字符是否合法
jb
rderr ;不合法則返回重新輸入
cmpal,'9'
jberdhd4 ;輸入數(shù)碼:0~9,減30H子程序文件47〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-5
cmp
al,'A'
jb
rderr
cmp
al,'F'
jberdhd3 ;輸入大寫字母:A~F,減7后、再減30H
cmp
al,'a'
jb
rderr
cmp
al,'f' ;輸入小寫字母:a~f,減20H、減7后、再減30H
ja
rderr subal,20h ;減20Hrdhd3: subal,7 ;減7rdhd4: subal,30h ;減30H 子程序文件48〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-6
shlebx,4 ;EBX左移4位對(duì)應(yīng)十六進(jìn)制一位
orbl,al ;BL和AL相加
looprdhd2 ;循環(huán)鍵入字符
mov
eax,ebx ;通過(guò)EAX返回結(jié)果
popecx popebx retrderr: mov
eax,offset
errmsg calldispmsg
jmprdhd1errmsg db0dh,0ah,'Inputerror,enteragain:',0rdhd
endp子程序文件示意圖49例5-8程序的運(yùn)行示例返回505.3.2模塊連接子程序單獨(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ǔ)模型,沒(méi)有開始執(zhí)行和結(jié)束執(zhí)行點(diǎn)處理好子程序與主程序之間的參數(shù)傳問(wèn)題51〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-7;文件名:eg0508es.asm,例5-8程序的子程序
includeio32.inc
publicrdhd,dphd,write ;子程序共用
externtemp:dword ;外部變量
.data ;數(shù)據(jù)段writebuf db12dup(0) ;顯示緩沖區(qū)
.code ;代碼段,子程序rdhd proc
c ;十六進(jìn)制輸入子程序 … ;略,同EG0508S.ASM文件
end ;匯編結(jié)束子程序文件52〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-8;文件名:eg0508e.asm,例5-8主程序 includeio32.inc
…… ;數(shù)據(jù)段
externrdhd:near,dphd:near,write:near
;外部子程序
publictemp ;變量共用
.code ;代碼段
……主程序文件ML/c/coffeg0508e.asmML/c/coffeg0508es.asmLINK32/subsystem:consoleeg0508e.objeg0508es.obj/libpath:bin操作過(guò)程535.3.3子程序庫(kù)子程序庫(kù):統(tǒng)一管理子程序模塊遵循更加嚴(yán)格的子程序模塊要求子程序文件編寫完成、匯編形成目標(biāo)模塊利用庫(kù)管理工具程序LIB.EXE:把子程序模塊逐個(gè)加入到子程序庫(kù)(.LIB) 使用子程序庫(kù):在連接主程序模塊時(shí)提供子程序庫(kù)文件名LIB32/OUT:eg0508.libeg0508es.objLINK32/subsystem:consoleeg0508e.objeg0508.lib/libpath:bin操作過(guò)程54庫(kù)文件包含直接在源文件中用庫(kù)文件包含偽指令I(lǐng)NCLUDELIB說(shuō)明不用在連接時(shí)輸入庫(kù)文件名
INCLUDELIB文件名;declareprocedures
externreadc:near,readmsg:near externdispc:near,dispmsg:near,dispcrlf:near ...;declareI/Olibraries
includelibio32.libIO32.INC555.4宏結(jié)構(gòu)本書統(tǒng)稱的宏結(jié)構(gòu)宏匯編重復(fù)匯編條件匯編用于簡(jiǎn)化源程序結(jié)構(gòu)子程序等多模塊結(jié)構(gòu)用于簡(jiǎn)化目標(biāo)代碼565.4.1宏匯編宏(Macro):具有宏名的一段匯編語(yǔ)句序列宏需要先定義宏名 MACRO形參表
…… ;宏定義體
ENDM然后程序中進(jìn)行宏調(diào)用宏名實(shí)體參數(shù)在匯編時(shí),宏指令被匯編程序用宏定義的代碼序列替代,實(shí)現(xiàn)宏展開571.宏定義和宏調(diào)用宏定義WriteString macromsg
pusheax leaeax,msg calldispmsg popeax
endm宏展開
pusheax leaeax,msg calldispmsg popeax宏調(diào)用
WriteString
msg58OF1131
12SF7ZF6AF40PF2CF0〔例5-9〕狀態(tài)標(biāo)志顯示程序-1 ;宏定義rfbit macrobit1,bit2
xor
ebx,ebx ;EBX清0,用于保存字符
roleax,bit1 ;將某個(gè)標(biāo)志左移BIT1位,進(jìn)入當(dāng)前CF
adcebx,30h ;轉(zhuǎn)換為ASCII字符
mov[rfmsg+bit2],bl ;保存于字符串BIT2位置
endm ;數(shù)據(jù)段rfmsg db'OF=0,SF=0,ZF=0,AF=0,PF=0,CF=0',13,10,059OF1131
12SF7ZF6AF40PF2CF0〔例5-9〕狀態(tài)標(biāo)志顯示程序-2 ;代碼段
moveax,50 subeax,80 ;假設(shè)一個(gè)運(yùn)算
pushfd ;將標(biāo)志位寄存器的內(nèi)容壓入堆棧
popeax ;將標(biāo)志位寄存器的內(nèi)容存入EAX
rfbit21,3 ;顯示OF(原來(lái)的OF需左移21位,進(jìn)入當(dāng)前CF)
rfbit4,9 ;顯示SF(原來(lái)的SF再左移4位,進(jìn)入當(dāng)前CF) ……60OF1131
12SF7ZF6AF40PF2CF0〔例5-9〕狀態(tài)標(biāo)志顯示程序-3
rfbit21,3 ;顯示OF(原來(lái)的OF需左移21位,進(jìn)入當(dāng)前CF)1 xor
ebx,ebx ;EBX清0,用于保存字符1 roleax,21 ;將某個(gè)標(biāo)志左移BIT1位,進(jìn)入當(dāng)前CF1 adcebx,30h ;轉(zhuǎn)換為ASCII字符1 mov[rfmsg+3],bl ;保存于字符串BIT2位置612.宏的參數(shù)和宏的操作符(1)宏定義asciiz macrostring db'&string&',0
endm宏展開
db’Thisisaexample.’,0宏調(diào)用
asciiz<Thisisaexample.>傳遞操作符替換操作符622.宏的參數(shù)和宏的操作符(2)宏定義asciiz macrostring db'&string&',0
endm宏展開
db’0<Number<10’,0宏調(diào)用
asciiz<0!<Number!<10>轉(zhuǎn)義操作符632.宏的參數(shù)和宏的操作符(3)宏定義asciiz macrostring db'&string&',0
endm宏展開
db’1023’,0宏調(diào)用
asciiz%(1024-1)表達(dá)式操作符643.宏的偽指令局部偽指令
LOCAL標(biāo)號(hào)列表
;宏定義體采用了標(biāo)號(hào),應(yīng)使用LOCAL加以說(shuō)明
;它必須是宏定義MACRO語(yǔ)句之后的第一條語(yǔ)句刪除宏定義偽指令
PURGE宏名表
;不需要某個(gè)宏定義時(shí),可以把它刪除宏定義退出偽指令
EXITM
;表示結(jié)束當(dāng)前宏調(diào)用的展開65局部偽指令宏定義absol macrooprd
localnext
cmpoprd,0
jgenext
neg
oprdnext:
endm
;;這個(gè)偽指令要獨(dú)占一行宏調(diào)用和宏展開
absolwordptr[ebx]
cmpwordptr[ebx],0
jge
??0000
negwordptr[ebx]??0000:66〔例5-10〕通用寄存器顯示程序-1dreg32 macroreg32
localdreg1,dreg2
moveax,reg32 ;;顯示reg32寄存器
movecx,8
xor
ebx,ebxdreg1:
roleax,4
mov
edx,eax anddl,0fh adddl,30h
;;轉(zhuǎn)化為相應(yīng)的ASCII碼值
cmpdl,39h
;;區(qū)別0~9和A~F數(shù)碼
jbe
dreg2 adddl,767〔例5-10〕通用寄存器顯示程序-2dreg2:
movrd®32&[ebx+4],dl ;;存于對(duì)應(yīng)的字符串
incebx
cmp
ebx,ecx
jb
dreg1
endm ;數(shù)據(jù)段rdeax db'EAX=00000000,'
……
;代碼段,顯示EAX dreg32eax
……
684.宏與子程序僅是源程序級(jí)的簡(jiǎn)化:宏調(diào)用在匯編時(shí)進(jìn)行程序語(yǔ)句的展開,不需要返回;不減小目標(biāo)程序,執(zhí)行速度沒(méi)有改變通過(guò)形參、實(shí)參結(jié)合實(shí)現(xiàn)參數(shù)傳遞,簡(jiǎn)捷直觀、靈活多變當(dāng)程序段較短或要求較快執(zhí)行時(shí),應(yīng)選用宏還是目標(biāo)程序級(jí)的簡(jiǎn)化:子程序調(diào)用在執(zhí)行時(shí)由CALL指令轉(zhuǎn)向、RET指令返回;形成的目標(biāo)代碼較短,執(zhí)行速度減慢需要利用寄存器、存儲(chǔ)單元或堆棧等傳遞參數(shù)當(dāng)程序段較長(zhǎng)或?yàn)闇p小目標(biāo)代碼時(shí),要選用子程序695.4.2重復(fù)匯編重復(fù)匯編指在匯編過(guò)程中,重復(fù)展開一段相同或基本相同的語(yǔ)句重復(fù)匯編沒(méi)有名字,不能被調(diào)用重復(fù)匯編常用在宏定義體中,也可以在一般匯編語(yǔ)句中使用重復(fù)匯編偽指令有3個(gè):REPEAT ;按參數(shù)值重復(fù)FOR ;按參數(shù)個(gè)數(shù)重復(fù)FORC ;按參數(shù)的字符個(gè)數(shù)重復(fù)最后,用ENDM結(jié)束701.按參數(shù)值重復(fù)偽指令REPEATREPEAT重復(fù)次數(shù)
……
;重復(fù)體ENDMchar=20hdbcharrepeat95-1char=char+1dbcharendmdbchar ;等效于db20hchar=char+1dbchar ;等效于db21h ...char=char+1dbchar ;等效于db7eh712.按參數(shù)個(gè)數(shù)重復(fù)偽指令FORFOR形參,〈實(shí)參表〉
……
;重復(fù)體ENDMforregad,<eax,ebx,ecx,edx>
pushregadendmpusheaxpushebxpushecxpushedx723.按參數(shù)字符個(gè)數(shù)重復(fù)偽指令FORCFORC
形參,字符串
……
;重復(fù)體ENDMforcregad,dcbapope®ad&xendmpopedxpopecxpopebxpopeax735.4.3條件匯編根據(jù)某種條件確定是否匯編某段語(yǔ)句序列它與高級(jí)語(yǔ)言的條件編譯命令類似條件匯編偽指令的一般格式:
IFxx
表達(dá)式
;條件滿足,匯編分支語(yǔ)句體1
分支語(yǔ)句體1 [ELSE ;條件不滿足,匯編分支語(yǔ)句體2
分支語(yǔ)句體2]
ENDIF ;條件匯編結(jié)束741.IF/IFE偽指令pdata macronum
ifnumlt100 ;如果num<100,匯編如下語(yǔ)句dbnumdup(?)
else ;否則,匯編如下語(yǔ)句db100dup(?)
endif
endmpdata12 ;宏調(diào)用①db12dup(?) ;宏匯編結(jié)果①----------------------------pdata102 ;宏調(diào)用②db100dup(?) ;宏匯編結(jié)果②752.IFDEF/IFNDEF偽指令ifdef
RealMode ;當(dāng)定義有RealMode符號(hào)時(shí),匯編如下語(yǔ)句
mov
ax,@data
mov
ds,axendifRealMode=1 ;定義RealMode符號(hào)763.IFB/IFNB偽指令maxnum macrodvar1:req,dvar2,dvar3 localmaxnum1,maxnum2
moveax,dvar1
ifnb<dvar2>
;當(dāng)有DVAR2實(shí)參時(shí),匯編如下語(yǔ)句
cmpeax,dvar2
jgemaxnum1
moveax,dvar2
endifmaxnum1: ……
endm
maxnum3,5 ;宏調(diào)用
moveax,3
cmpeax,5
jge??0002
moveax,5??0002:774.IFIDN/IFDIF和IFIDNI/IFDIFI偽指令print macroformat,var
mov
al,var
ifidni<format>,<b> calldispbb
;二進(jìn)制顯示用格式符“b”
exitm
;不再進(jìn)行宏展開
endif
……
endmprint
b,var;二進(jìn)制形式顯示:01100100第5章習(xí)題:模塊化程序設(shè)計(jì)5.1簡(jiǎn)答題(1、4、5、6、7)5.2
判斷題(2、5、6、7、8)5.3
填空題(1、4、5、6、7)5.7、5.8、5.11、5.13第6章Windows編程6.1操作系統(tǒng)函數(shù)調(diào)用6.2控制臺(tái)應(yīng)用程序6.3圖形窗口應(yīng)用程序第6章Windows編程熟悉匯編語(yǔ)言調(diào)用API函數(shù)的方法掌握控制臺(tái)輸入輸出函數(shù)熟悉MASM的高級(jí)特性理解Windows圖形窗口程序的編寫816.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的API826.1.1
動(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)836.1.2MASM的過(guò)程聲明和調(diào)用過(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ù),...]846.1.3
程序退出函數(shù)Win32程序員參考手冊(cè)VOIDExitProcess(UINTuExitCode //exitcodeforallthreads);匯編語(yǔ)言聲明ExitProcess
PROTO,:DWORD匯編語(yǔ)言調(diào)用invoke
ExitProcess,0將函數(shù)調(diào)用定義成宏exit MACROdwexitcode
invokeExitProcess,dwexitcode
ENDM宏調(diào)用exit 0856.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ù)866.2.1控制臺(tái)輸出編寫控制臺(tái)程序需要調(diào)用控制臺(tái)函數(shù),實(shí)現(xiàn)控制臺(tái)(顯示器)輸出控制臺(tái)(鍵盤)輸入幾乎所有的控制臺(tái)函數(shù)都要求將控制臺(tái)句柄作為第一個(gè)參數(shù)傳遞給它們本節(jié)介紹的控制臺(tái)函數(shù)存在于KERNEL32.DLL動(dòng)態(tài)庫(kù)中程序開發(fā)需要使用KERNEL32.LIB導(dǎo)入庫(kù)文件871.
控制臺(tái)句柄句柄(Handle)是一個(gè)32位無(wú)符號(hào)整數(shù)用來(lái)唯一確定一個(gè)對(duì)象例如某個(gè)輸入設(shè)備、輸出設(shè)備或者一個(gè)圖形標(biāo)準(zhǔn)輸入句柄
STD_INPUT_HANDLE
equ-10標(biāo)準(zhǔn)輸出句柄
STD_OUTPUT_HANDLE
equ-11標(biāo)準(zhǔn)錯(cuò)誤句柄
STD_ERROR_HANDLE
equ-12GetStdHandle函數(shù)獲取控制臺(tái)輸入或輸出的句柄實(shí)例用于控制臺(tái)程序的輸入輸出操作882.
控制臺(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è)置為089〔例6-1〕控制臺(tái)輸出程序-1
.686 .modelflat,stdcall optioncasemap:none
includelib
bin\kernel32.libExitProcess
proto,:dwordGetStdHandle proto,:dwordWriteConsoleA proto,:dword,:dword,:dword,:dword,:dwordWriteConsole equ<WriteConsoleA>STD_OUTPUT_HANDLEequ-11 .datamsg db'Hello,Assembly!',13,10count equ$-msgoutsize dd090〔例6-1〕控制臺(tái)輸出程序-2 .codestart:
;獲得輸出句柄 invokeGetStdHandle,STD_OUTPUT_HANDLE
;顯示信息 invokeWriteConsole,eax,offsetmsg,count,offsetoutsize,0
;退出 invokeExitProcess,0 endstartHello,Assembly!運(yùn)行結(jié)果916.2.2
控制臺(tái)輸入鍵盤輸入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é)92〔例6-2〕信息輸入輸出程序-1
.686 .modelflat,stdcall optioncasemap:none
includelib
bin\kernel32.libExitProcess
proto,:dwordexit MACROdwexitcode invokeExitProcess,dwexitcode ENDMGetStdHandle
proto,:dwordWriteConsoleA
proto,:dword,:dword,:dword,:dword,:dwordWriteConsole
equ<WriteConsoleA>93〔例6-2〕信息輸入輸出程序-2ReadConsoleA proto,:dword,:dword,:dword,:dword,:dwordReadConsole equ<ReadConsoleA>STD_INPUT_HANDLEequ-10STD_OUTPUT_HANDLEequ-11 .datamsg1 db'Pleaseenteryourname:',0msg2 db'Welcome',0nbuf db80dup(0)msg3 db'toWin32Console!',0
;設(shè)置輸入緩沖區(qū)最大255個(gè)字符94〔例6-2〕信息輸入輸出程序-3
.codestart:
mov
eax,offsetmsg1 ;提示輸入
calldispmsg
mov
eax,offset
nbuf
;輸入信息
callreadmsg
mov
eax,offsetmsg2
calldispmsg
mov
eax,offset
nbuf
;顯示輸入信息
calldispmsg
mov
eax,offsetmsg3
calldispmsg
exit095〔例6-2〕信息輸入輸出程序-4 .data_outsize dd0_outhandle dd0dispmsg proc
;字符串顯示子程序
pusheax
;入口參數(shù):EAX=字符串地址
pushebx pushecx pushedx pusheax
;保存入口參數(shù),即字符串地址
invokeGetStdHandle,STD_OUTPUT_HANDLE
mov[_outhandle],eax
popebx
;EBX=字符串地址
xor
ecx,ecx
;計(jì)算字符串長(zhǎng)度96〔例6-2〕信息輸入輸出程序-5dispm1: moval,[ebx+ecx] testal,al jzdispm2 incecx jmpdispm1dispm2:
invokeWriteConsole,[_outhandle],ebx,ecx,offset_outsize,0
popedx popecx popebx popeax retdispmsg
endp97〔例6-2〕信息輸入輸出程序-6 .data_insize dd0_inbuffer db255dup(0)readmsg proc ;字符串輸入子程序
pushebx ;入口參數(shù):EAX=緩沖區(qū)地址
pushecx pushedx pusheax
;保護(hù)輸入的緩沖區(qū)地址參數(shù)
invokeGetStdHandle,STD_INPUT_HANDLE invokeReadConsole,eax,offset_inbuffer,255,offset_insize,0
subdwordptr[_insize],2
xor
ecx,ecx popebx
;獲得緩沖區(qū)地址98〔例6-2〕信息輸入輸出程序-7readm1: moval,_inbuffer[ecx] mov[ebx+ecx],al ;將輸入的字符串復(fù)制到用戶緩沖區(qū)
incecx cmpecx,[_insize] jbreadm1
movbyteptr[ebx+ecx],0
;最后填入結(jié)尾字符0
mov
eax,ecx popedx popecx popebx retreadmsg
endpPleaseenteryourname:JerryWelcomeJerrytoWin32Console!運(yùn)行結(jié)果996.2.3單字符輸入默認(rèn)模式下ReadConsole函數(shù)實(shí)現(xiàn)一行字符輸入最后必須用回車鍵結(jié)束設(shè)置為單字符輸入模式后ReadConsole函數(shù)實(shí)現(xiàn)一個(gè)字符輸入自動(dòng)結(jié)束調(diào)用需要修改輸入模式獲取控制臺(tái)模式函數(shù)GetConsoleMode設(shè)置控制臺(tái)模式函數(shù)SetConsoleMode100〔例6-3〕單字符輸入程序-1 …GetConsoleModeproto,:dword,:dwordSetConsoleModeproto,:dword,:dword .datamsg db'Pressanykeytoend'count equ$-msgoutsize dd0inhandle dd0savemode dd0 ;保存控制臺(tái)模式insize dd0inbuffer db255dup(0) ;設(shè)置輸入緩沖區(qū)最大255個(gè)字符101〔例6-3〕單字符輸入程序-2
.codestart: invokeGetStdHandle,STD_OUTPUT_HANDLE
;提示按任意鍵
invokeWriteConsole,eax,offsetmsg,count,offsetoutsize,0 invokeGetStdHandle,STD_INPUT_HANDLE mov[inhandle],eax
invokeGetConsoleMode,[inhandle],offsetsavemode
;獲得控制臺(tái)模式
invokeSetConsoleMode,[inhandle],0
;設(shè)置為單字符輸入模式102〔例6-3〕單字符輸入程序-3
invokeReadConsole,[inhandle],offsetinbuffer,1,offsetinsize,0
;輸入字符
invokeSetConsoleMode,[inhandle],[savemode]
;恢復(fù)原控制臺(tái)模式
invokeExitProcess,0 ;退出Pressanykeytoend運(yùn)行結(jié)果1036.3
圖形窗口應(yīng)用程序Windows圖形界面以窗口、對(duì)話框、菜單、按鈕等實(shí)現(xiàn)用戶交互用匯編語(yǔ)言編寫圖形窗口應(yīng)用程序就是調(diào)用這些API函數(shù)1046.3.1
消息窗口消息窗口是常見的Windows圖形窗口顯示形式使用MessageBox函數(shù)Win32程序員參考手冊(cè)的定義int
MessageBox(HWNDhWnd,LPCTSTRlpText,LPCTSTRlpCaption,UINTuType);hWnd:父窗口的句柄lpText:要顯示字符串的地址指針,字符串的首地址lpCaption:消息窗標(biāo)題的地址指針uType:指明該消息窗的類型105〔例6-4〕消息窗口程序-1
.686 .modelflat,stdcall optioncasemap:none
includelib
bin\kernel32.lib
includelib
bin\user32.libExitProcess
proto,:dwordMessageBoxA
PROTO,:dword,:dword,:dword,:dwordMessageBox
equ<MessageBoxA>NULL equ0MB_OK equ0 .dataszCaption db‘歡迎',0outbuffer db‘你好,匯編語(yǔ)言!',0106〔例6-4〕消息窗口程序-2 .codestart:
invoke
MessageBox,NULL,offsetoutbuffer,offset
szCaption,MB_OK invokeExitProcess,NULL endstart連接時(shí)應(yīng)該使用參數(shù)/subsystem:windows1076.3.2結(jié)構(gòu)變量結(jié)構(gòu)類型的說(shuō)明 結(jié)構(gòu)名STRUCT …… ;數(shù)據(jù)定義語(yǔ)句 結(jié)構(gòu)名ENDS結(jié)構(gòu)變量的定義 變量名結(jié)構(gòu)名<字段初值表>結(jié)構(gòu)變量及其字段的引用引用結(jié)構(gòu)變量,只要直接書寫結(jié)構(gòu)變量名引用其中某個(gè)字段,采用圓點(diǎn)“.”操作符結(jié)構(gòu)變量名.結(jié)構(gòu)字段名108〔例6-5〕系統(tǒng)時(shí)鐘顯示程序-1
;系統(tǒng)時(shí)間的結(jié)構(gòu)類型說(shuō)明SYSTEMTIME
struct
wYear dw0 ;年(4位數(shù))
wMonth dw0 ;月(1~12)wDayOfWeek dw0 ;星期(0~6,0=星期日,……)wDay dw0 ;日(1~31)
wHour dw0 ;時(shí)(0~23)
wMinute dw0 ;分(0~59)
wSecond dw0
;秒(0~59)
wMillisconds dw0 ;毫秒(0~999)SYSTEMTIME ends
;函數(shù)聲明,參數(shù)是指向結(jié)構(gòu)變量的指針GetLocalTime proto,:dword109〔例6-5〕系統(tǒng)時(shí)鐘顯示程序-2 .datamytime SYSTEMTIME<> ;系統(tǒng)時(shí)間的結(jié)構(gòu)變量定義timestring db'--:--:--',0timecaption db'當(dāng)前時(shí)間',0 .codestart: invokeGetLocalTime,offsetmytime ;獲得當(dāng)前時(shí)間
movebx,offsettimestring ;EBX指向“時(shí)”的保存位置
writedec
[mytime.wHour]
;轉(zhuǎn)換為ASCII字符
…
invokeMessageBox,0,offsettimestring,offsettimecaption,1writedec110宏:writedecwritedec macrotime ;;將二進(jìn)制數(shù)轉(zhuǎn)換為2位十進(jìn)制數(shù)
;;再轉(zhuǎn)為ASCII字符保存
movax,time movcl,10 divcl ;;商AL是百位,余數(shù)AH是個(gè)位
addax,3030h ;;轉(zhuǎn)換為ASCII
mov[ebx],ax ;;對(duì)應(yīng)顯示順序,百位先顯示保存在低地址
endm返回1116.3.3MASM的高級(jí)語(yǔ)言特性MASM6.0引入高級(jí)語(yǔ)言的程序設(shè)計(jì)特性擴(kuò)展的過(guò)程定義PROC過(guò)程聲明和過(guò)程調(diào)用偽指令PROTOINVOKE條件控制偽指令.IF.ELSE.ENDIF循環(huán)控制偽指令.WHILE.ENDW.REPEAT.UNTIL要調(diào)用帶參數(shù)過(guò)程定義的過(guò)程,不應(yīng)采用CALL指令,因?yàn)楸容^煩瑣應(yīng)該采用過(guò)程調(diào)用偽指令I(lǐng)NVOKE使用INVOKE偽指令的前提是需要用PROTO偽指令對(duì)過(guò)程進(jìn)行聲明過(guò)程名 PROC
調(diào)用距離語(yǔ)言類型作用范圍<起始參數(shù)> USES寄存器列表,參數(shù):類型
LOCAL參數(shù)表
… ;匯編語(yǔ)言語(yǔ)句過(guò)程名 ENDP過(guò)程聲明偽指令:事先聲明過(guò)程的結(jié)構(gòu)過(guò)程名 PROTO調(diào)用距離語(yǔ)言類型,參數(shù):類型過(guò)程調(diào)用偽指令
INVOKE
過(guò)程名,參數(shù),...如何調(diào)用1.擴(kuò)展的過(guò)程定義113〔例6-6〕使用擴(kuò)展過(guò)程定義程序-1mean protoc,:dword,:dword
;過(guò)程聲明,使用C語(yǔ)言規(guī)范
.dataarray dd675,…,-67,4257count equ($-array)/4 .codestart: ;主程序:調(diào)用求平均值子程序,然后顯示
invokemean,offsetarray,count
calldispsid
;顯示 exit0 ;子程序:計(jì)算32位有符號(hào)數(shù)平均值 ;入口參數(shù):D表示數(shù)組地址、NUM表示元素個(gè)數(shù) ;出口參數(shù):EAX=平均值114〔例6-6〕使用擴(kuò)展過(guò)程定義程序-2mean proccusesebxecxedx,d:dword,num:dword
movebx,d ;EBX=數(shù)組指針
movecx,num ;ECX=元素個(gè)數(shù)
xoreax,eax ;EAX保存和值
xoredx,edx ;EDX=指向數(shù)組元素mean1: 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=平均值
retmean endp用“/Sa”參數(shù)匯編,最大化源代碼列表115〔例6-6〕列表文件-1start:
;主程序:調(diào)用求平均值子程序,然后顯示
invokemean,offsetarray,count* push+00000000Ah* pushOFFSETarray* callmean* addesp,000000008h
calldispsid
;顯示
exit0* push+000000000h* callExitProcess1 invokeExitProcess,0116〔例6-6〕列表文件-2mean proccusesebxecxedx,d:dword,num:dword* pushebp* movebp,esp* pushebx* pushecx* pushedx …… ;這部分同源程序,省略
ret* popedx* popecx* popebx* leave
;movesp,ebp/popebp* ret00000hmean endpmovebx,dwordptr[ebp+8]movecx,dwordptr[ebp+0ch]1172.條件控制類似高級(jí)語(yǔ)言中IF、THEN、ELSE和ENDIF的相應(yīng)功能在匯編時(shí)要展開,自動(dòng)生成相應(yīng)的比較和條件轉(zhuǎn)移指令序列,實(shí)現(xiàn)程序分支
.IF條件表達(dá)式
;條件為真(值為非0)
分支體
;執(zhí)行分支體[ .ELSEIF ;前面IF[以及前面ELSEIF]條件為假 ;并且當(dāng)前ELSEIF條件為真
分支體
]
;執(zhí)行分支體[ .ELSE ;前面IF[以及前面ELSEIF]條件為假
分支體
]
;執(zhí)行分支體
.ENDIF ;分支結(jié)束條件118條件表達(dá)式中的操作符操作符功能操作符功能操作符功能==等于&&邏輯與CARRY?CF=1?!=不等于||邏輯或OVERFLOW?OF=1?>大于!邏輯非PARITY?PF=1?>=大于等于SIGN?SF=1?<小于&位測(cè)試ZERO?ZF=1?<=小于等于()改變優(yōu)先級(jí)返回〔例6-7〕使用條件控制的程序-1求EAX絕對(duì)值程序單分支結(jié)構(gòu)
callreadsid
.
溫馨提示
- 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 軍事理論(2024年版)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 咖啡廳裝修設(shè)計(jì)施工合同
- 咨詢服務(wù)居間合作協(xié)議書
- 寵物活體安全運(yùn)輸協(xié)議
- 高端會(huì)所石膏吊頂裝修合同
- 造紙廠擴(kuò)建沙石配送合同
- 藥店改造協(xié)議及預(yù)算
- 石油制品裝卸運(yùn)輸合同樣本
- 燈具行業(yè)運(yùn)輸合同范本
- 游泳館升級(jí)改造裝修協(xié)議
- 人教版八年級(jí)上冊(cè)數(shù)學(xué)期中考試試題含答案
- 國(guó)開2024年秋《生產(chǎn)與運(yùn)作管理》形成性考核1-4答案
- 三級(jí)醫(yī)療機(jī)構(gòu)檢查檢驗(yàn)結(jié)果互認(rèn)工作情況報(bào)告
- 礦山生態(tài)環(huán)境保護(hù)與恢復(fù)技術(shù)考核試卷
- 2024安全行業(yè)大模型技術(shù)應(yīng)用態(tài)勢(shì)發(fā)展報(bào)告
- 2.2.1 有理數(shù)的乘法(第一課時(shí))-課件
- 人大代表視察項(xiàng)目座談會(huì)發(fā)言
- 外部供應(yīng)商合作管理制度
- 重慶市南開中學(xué)2025屆高三上學(xué)期8月第一次質(zhì)量檢測(cè)數(shù)學(xué)試題(原卷版)
- 2024年廣東省珠海高新區(qū)綜合治理局招聘6人歷年(高頻重點(diǎn)復(fù)習(xí)提升訓(xùn)練)共500題附帶答案詳解
- 意大利迪賽品牌
評(píng)論
0/150
提交評(píng)論