32位匯編語(yǔ)言程序設(shè)計(jì) 第3版 課件 錢曉捷 第5-9章 模塊化程序設(shè)計(jì)-浮點(diǎn)、多媒體及64位指令_第1頁(yè)
32位匯編語(yǔ)言程序設(shè)計(jì) 第3版 課件 錢曉捷 第5-9章 模塊化程序設(shè)計(jì)-浮點(diǎn)、多媒體及64位指令_第2頁(yè)
32位匯編語(yǔ)言程序設(shè)計(jì) 第3版 課件 錢曉捷 第5-9章 模塊化程序設(shè)計(jì)-浮點(diǎn)、多媒體及64位指令_第3頁(yè)
32位匯編語(yǔ)言程序設(shè)計(jì) 第3版 課件 錢曉捷 第5-9章 模塊化程序設(shè)計(jì)-浮點(diǎn)、多媒體及64位指令_第4頁(yè)
32位匯編語(yǔ)言程序設(shè)計(jì) 第3版 課件 錢曉捷 第5-9章 模塊化程序設(shè)計(jì)-浮點(diǎn)、多媒體及64位指令_第5頁(yè)
已閱讀5頁(yè),還剩272頁(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)介

32位匯編語(yǔ)言程序設(shè)計(jì)第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)鍵盤(pán)輸入和顯示輸出掌握子程序、文件包含、宏匯編等各種多模塊編程的方法45.1子程序結(jié)構(gòu)經(jīng)常用到的應(yīng)用問(wèn)題編寫(xiě)成一個(gè)通用子程序大型處理過(guò)程分解成能夠解決的模塊使用子程序可以使程序的結(jié)構(gòu)更為清楚程序的維護(hù)更為方便有利于大程序開(kāi)發(fā)時(shí)的多個(gè)程序員分工合作子程序(Subroutine)=函數(shù)(Function)=過(guò)程(Procedure)55.1.1子程序指令子程序與主程序分開(kāi)、完成特定功能的一段程序主程序(調(diào)用程序)執(zhí)行調(diào)用指令CALL調(diào)用子程序子程序(被調(diào)用程序)執(zhí)行返回指令RET返回主程序CALLlabel主程序RET子程序回到CALL指令后的指令處61.子程序調(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ǔ)單元指定地址的子程序72.子程序返回指令RETRET指令用在子程序結(jié)束,實(shí)現(xiàn)返回主程序

RET

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

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

;ESP←ESP+i16MASM會(huì)根據(jù)存儲(chǔ)模型等信息確定子程序的遠(yuǎn)近調(diào)用,并相應(yīng)產(chǎn)生返回指令8name …

RET

CALLnamenext:… ;下條指令CALL的調(diào)用和RET的返回主程序子程序堆棧next;思考如下代碼片段的功能 callnextnext: popeax

;EAX=?93.過(guò)程定義偽指令MASM利用過(guò)程定義偽指令獲得子程序信息

過(guò)程名 PROC

…… ;過(guò)程體

過(guò)程名 ENDP

;過(guò)程名為符合語(yǔ)法的標(biāo)識(shí)符PROC后面可加參數(shù):NEAR或FAR簡(jiǎn)化段定義源程序格式中,通常不需指定10〔例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

calldisprd11〔例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?示意圖12子程序調(diào)用的堆棧返回135.1.2子程序設(shè)計(jì)子程序的編寫(xiě)方法與主程序一樣但需要留意幾個(gè)問(wèn)題:利用過(guò)程定義,獲得子程序名和調(diào)用屬性RET指令返回主程序,CALL指令調(diào)用子程序壓入和彈出操作要成對(duì)使用,保持堆棧平衡開(kāi)始保護(hù)寄存器,返回前相應(yīng)恢復(fù)安排在代碼段的主程序之外子程序允許嵌套和遞歸最好有完整的注釋難點(diǎn)是參數(shù)傳遞14〔例5-2〕回車換行子程序dpcrlf proc ;回車換行子程序

pusheax ;保護(hù)寄存器

moval,0dh ;輸出回車字符

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

moval,0ah ;輸出換行字符

calldispc

popeax ;恢復(fù)寄存器

ret ;子程序返回dpcrlf

endp155.2參數(shù)傳遞主程序與子程序間通過(guò)參數(shù)傳遞建立聯(lián)系入口參數(shù)(輸入?yún)?shù)):主程序→子程序出口參數(shù)(輸出參數(shù)):子程序→主程序傳遞參數(shù)的多少反映程序模塊間的耦合程度參數(shù)的具體內(nèi)容數(shù)據(jù)本身(傳遞數(shù)值)數(shù)據(jù)的存儲(chǔ)地址(傳遞地址,傳遞引用)參數(shù)傳遞方法寄存器變量堆棧165.2.1寄存器傳遞參數(shù)最簡(jiǎn)單和常用的參數(shù)傳遞方法把參數(shù)存于約定的寄存器少量數(shù)據(jù)直接傳遞數(shù)值大量數(shù)據(jù)只能傳遞地址帶有出口參數(shù)的寄存器不能保護(hù)和恢復(fù)帶有入口參數(shù)的寄存器可以保護(hù)、也可以不保護(hù),但最好能夠保持一致17〔例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',018〔例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

endp19〔例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é)果20〔例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)依次從高位開(kāi)始顯示各位數(shù)字21〔例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ù)22〔例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ù)23〔例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ù)先低位后高位壓入堆棧

jmpwrite324〔例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 endp255.2.2共享變量傳遞參數(shù)子程序和主程序使用同一個(gè)變量名存取數(shù)據(jù)如果變量定義和使用不在同一個(gè)程序模塊中,需要利用PUBLIC、EXTREN聲明共享變量傳遞參數(shù),子程序的通用性較差特別適合在多個(gè)程序段間、尤其在不同的程序模塊間傳遞數(shù)據(jù)26〔例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ù)27〔例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

rderr28〔例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ù)29〔例5-5〕二進(jìn)制輸入程序-4rderr: mov

eax,offset

errmsg ;顯示錯(cuò)誤信息

calldispmsg

jmprdbd1errmsg db0dh,0ah,'Inputerror,enteragain:',0rdbd

endp30〔例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ù)值保存31〔例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ù)32〔例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ò)誤33〔例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ǔ)碼

jzread334〔例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ù)位35〔例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

readerr36〔例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ù)375.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ī)方法38〔例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ù)39〔例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ù)40〔例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)題?示意圖41利用堆棧傳遞參數(shù)返回425.3多模塊程序結(jié)構(gòu)程序分段、子程序等實(shí)現(xiàn)了程序模塊化開(kāi)發(fā)大型應(yīng)用程序時(shí)常使用多個(gè)源程序文件、目標(biāo)代碼模塊等組成完整的程序MASM具體支持的方法源文件包含模塊連接子程序庫(kù)庫(kù)文件包含435.3.1源文件包含大型源程序可以合理地分放在若干個(gè)文本文件中各種常量定義、聲明語(yǔ)句等組織在包含文件(*.INC)常用的或有價(jià)值的宏定義存放在宏定義文件(*.MAC)常用的子程序形成匯編語(yǔ)言源文件(*.ASM)任何文本文件使用源文件包含偽指令I(lǐng)NCLUDE將指定的文本文件內(nèi)容插入主體源程序文件

INCLUDE文件名利用INCLUDE偽指令包含其他文件,其實(shí)質(zhì)仍然是一個(gè)源程序,只不過(guò)是分在了幾個(gè)文件書(shū)寫(xiě)子程序庫(kù)文件名要符合操作系統(tǒng)規(guī)范44〔例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ū)包含文件45〔例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主程序文件46〔例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主程序文件47〔例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子程序文件48〔例5-8〕存儲(chǔ)器數(shù)據(jù)顯示程序-5

cmp

al,'A'

jb

rderr

cmp

al,'F'

jberdhd3 ;輸入大寫(xiě)字母:A~F,減7后、再減30H

cmp

al,'a'

jb

rderr

cmp

al,'f' ;輸入小寫(xiě)字母:a~f,減20H、減7后、再減30H

ja

rderr subal,20h ;減20Hrdhd3: subal,7 ;減7rdhd4: subal,30h ;減30H 子程序文件49〔例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子程序文件示意圖50例5-8程序的運(yùn)行示例返回515.3.2模塊連接子程序單獨(dú)編寫(xiě),匯編形成目標(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)有開(kāi)始執(zhí)行和結(jié)束執(zhí)行點(diǎn)處理好子程序與主程序之間的參數(shù)傳問(wèn)題52〔例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é)束子程序文件53〔例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ò)程545.3.3子程序庫(kù)子程序庫(kù):統(tǒng)一管理子程序模塊遵循更加嚴(yán)格的子程序模塊要求子程序文件編寫(xiě)完成、匯編形成目標(biāo)模塊利用庫(kù)管理工具程序LIB.EXE:把子程序模塊逐個(gè)加入到子程序庫(kù)(.LIB) 使用子程序庫(kù):在連接主程序模塊時(shí)提供子程序庫(kù)文件名LIB32/OUT:eg0508.libeg0508es.objLINK32/subsystem:consoleeg0508e.objeg0508.lib/libpath:bin操作過(guò)程55庫(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.INC565.4宏結(jié)構(gòu)本書(shū)統(tǒng)稱的宏結(jié)構(gòu)宏匯編重復(fù)匯編條件匯編用于簡(jiǎn)化源程序結(jié)構(gòu)子程序等多模塊結(jié)構(gòu)用于簡(jiǎn)化目標(biāo)代碼575.4.1宏匯編宏(Macro):具有宏名的一段匯編語(yǔ)句序列宏需要先定義宏名 MACRO形參表

…… ;宏定義體

ENDM然后程序中進(jìn)行宏調(diào)用宏名實(shí)體參數(shù)在匯編時(shí),宏指令被匯編程序用宏定義的代碼序列替代,實(shí)現(xiàn)宏展開(kāi)581.宏定義和宏調(diào)用宏定義WriteString macromsg

pusheax leaeax,msg calldispmsg popeax

endm宏展開(kāi)

pusheax leaeax,msg calldispmsg popeax宏調(diào)用

WriteString

msg59OF1131

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,060OF1131

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) ……61OF1131

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位置622.宏的參數(shù)和宏的操作符(1)宏定義asciiz macrostring db'&string&',0

endm宏展開(kāi)

db’Thisisaexample.’,0宏調(diào)用

asciiz<Thisisaexample.>傳遞操作符替換操作符632.宏的參數(shù)和宏的操作符(2)宏定義asciiz macrostring db'&string&',0

endm宏展開(kāi)

db’0<Number<10’,0宏調(diào)用

asciiz<0!<Number!<10>轉(zhuǎn)義操作符642.宏的參數(shù)和宏的操作符(3)宏定義asciiz macrostring db'&string&',0

endm宏展開(kāi)

db’1023’,0宏調(diào)用

asciiz%(1024-1)表達(dá)式操作符653.宏的偽指令局部偽指令

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)用的展開(kāi)66局部偽指令宏定義absol macrooprd

localnext

cmpoprd,0

jgenext

neg

oprdnext:

endm

;;這個(gè)偽指令要獨(dú)占一行宏調(diào)用和宏展開(kāi)

absolwordptr[ebx]

cmpwordptr[ebx],0

jge

??0000

negwordptr[ebx]??0000:67〔例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,768〔例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

……

694.宏與子程序僅是源程序級(jí)的簡(jiǎn)化:宏調(diào)用在匯編時(shí)進(jìn)行程序語(yǔ)句的展開(kāi),不需要返回;不減小目標(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í),要選用子程序705.4.2重復(fù)匯編重復(fù)匯編指在匯編過(guò)程中,重復(fù)展開(kāi)一段相同或基本相同的語(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é)束711.按參數(shù)值重復(fù)偽指令REPEATREPEAT重復(fù)次數(shù)

……

;重復(fù)體ENDMchar=20hdbcharrepeat95-1char=char+1dbcharendmdbchar ;等效于db20hchar=char+1dbchar ;等效于db21h ...char=char+1dbchar ;等效于db7eh722.按參數(shù)個(gè)數(shù)重復(fù)偽指令FORFOR形參,〈實(shí)參表〉

……

;重復(fù)體ENDMforregad,<eax,ebx,ecx,edx>

pushregadendmpusheaxpushebxpushecxpushedx733.按參數(shù)字符個(gè)數(shù)重復(fù)偽指令FORCFORC

形參,字符串

……

;重復(fù)體ENDMforcregad,dcbapope®ad&xendmpopedxpopecxpopebxpopeax745.4.3條件匯編根據(jù)某種條件確定是否匯編某段語(yǔ)句序列它與高級(jí)語(yǔ)言的條件編譯命令類似條件匯編偽指令的一般格式:

IFxx

表達(dá)式

;條件滿足,匯編分支語(yǔ)句體1

分支語(yǔ)句體1 [ELSE ;條件不滿足,匯編分支語(yǔ)句體2

分支語(yǔ)句體2]

ENDIF ;條件匯編結(jié)束751.IF/IFE偽指令pdata macronum

ifnumlt100 ;如果num<100,匯編如下語(yǔ)句dbnumdup(?)

else ;否則,匯編如下語(yǔ)句db100dup(?)

endif

endmpdata12 ;宏調(diào)用①db12dup(?) ;宏匯編結(jié)果①----------------------------pdata102 ;宏調(diào)用②db100dup(?) ;宏匯編結(jié)果②762.IFDEF/IFNDEF偽指令ifdef

RealMode ;當(dāng)定義有RealMode符號(hào)時(shí),匯編如下語(yǔ)句

mov

ax,@data

mov

ds,axendifRealMode=1 ;定義RealMode符號(hào)773.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:784.IFIDN/IFDIF和IFIDNI/IFDIFI偽指令print macroformat,var

mov

al,var

ifidni<format>,<b> calldispbb

;二進(jìn)制顯示用格式符“b”

exitm

;不再進(jìn)行宏展開(kāi)

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圖形窗口程序的編寫(xiě)826.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的API836.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):程序開(kāi)發(fā)的連接階段使用,與一個(gè)動(dòng)態(tài)連接庫(kù)DLL對(duì)應(yīng)846.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ù),...]856.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 0866.2

控制臺(tái)應(yīng)用程序Windows應(yīng)用程序開(kāi)始運(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è)備(鍵盤(pán))

標(biāo)準(zhǔn)輸出設(shè)備(顯示器)32位控制臺(tái)程序運(yùn)行在保護(hù)方式通過(guò)API使用Windows的動(dòng)態(tài)鏈接庫(kù)函數(shù)876.2.1控制臺(tái)輸出編寫(xiě)控制臺(tái)程序需要調(diào)用控制臺(tái)函數(shù),實(shí)現(xiàn)控制臺(tái)(顯示器)輸出控制臺(tái)(鍵盤(pán))輸入幾乎所有的控制臺(tái)函數(shù)都要求將控制臺(tái)句柄作為第一個(gè)參數(shù)傳遞給它們本節(jié)介紹的控制臺(tái)函數(shù)存在于KERNEL32.DLL動(dòng)態(tài)庫(kù)中程序開(kāi)發(fā)需要使用KERNEL32.LIB導(dǎo)入庫(kù)文件881.

控制臺(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)程序的輸入輸出操作892.

控制臺(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è)置為090〔例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 dd091〔例6-1〕控制臺(tái)輸出程序-2 .codestart:

;獲得輸出句柄 invokeGetStdHandle,STD_OUTPUT_HANDLE

;顯示信息 invokeWriteConsole,eax,offsetmsg,count,offsetoutsize,0

;退出 invokeExitProcess,0 endstartHello,Assembly!運(yùn)行結(jié)果926.2.2

控制臺(tái)輸入鍵盤(pán)輸入API函數(shù)ReadConsole將鍵盤(pán)輸入的文本保存到一個(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é)93〔例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>94〔例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è)字符95〔例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

exit096〔例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)度97〔例6-2〕信息輸入輸出程序-5dispm1: moval,[ebx+ecx] testal,al jzdispm2 incecx jmpdispm1dispm2:

invokeWriteConsole,[_outhandle],ebx,ecx,offset_outsize,0

popedx popecx popebx popeax retdispmsg

endp98〔例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ū)地址99〔例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é)果1006.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ù)SetConsoleMode101〔例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è)字符102〔例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è)置為單字符輸入模式103〔例6-3〕單字符輸入程序-3

invokeReadConsole,[inhandle],offsetinbuffer,1,offsetinsize,0

;輸入字符

invokeSetConsoleMode,[inhandle],[savemode]

;恢復(fù)原控制臺(tái)模式

invokeExitProcess,0 ;退出Pressanykeytoend運(yùn)行結(jié)果1046.3

圖形窗口應(yīng)用程序Windows圖形界面以窗口、對(duì)話框、菜單、按鈕等實(shí)現(xiàn)用戶交互用匯編語(yǔ)言編寫(xiě)圖形窗口應(yīng)用程序就是調(diào)用這些API函數(shù)1056.3.1

消息窗口消息窗口是常見(jiàn)的Windows圖形窗口顯示形式使用MessageBox函數(shù)Win32程序員參考手冊(cè)的定義int

MessageBox(HWNDhWnd,LPCTSTRlpText,LPCTSTRlpCaption,UINTuType);hWnd:父窗口的句柄lpText:要顯示字符串的地址指針,字符串的首地址lpCaption:消息窗標(biāo)題的地址指針uType:指明該消息窗的類型106〔例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ǔ)言!',0107〔例6-4〕消息窗口程序-2 .codestart:

invoke

MessageBox,NULL,offsetoutbuffer,offset

szCaption,MB_OK invokeExitProcess,NULL endstart連接時(shí)應(yīng)該使用參數(shù)/subsystem:windows1086.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)變量,只要直接書(shū)寫(xiě)結(jié)構(gòu)變量名引用其中某個(gè)字段,采用圓點(diǎn)“.”操作符結(jié)構(gòu)變量名.結(jié)構(gòu)字段名109〔例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,:dword110〔例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,1writedec111宏: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返回1126.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ò)程定義114〔例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=平均值115〔例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ù)匯編,最大化源代碼列表116〔例6-6〕列表文件-1start:

;主程序:調(diào)用求平均值子程序,然后顯示

invokemean,offsetarray,count* push+00000000Ah* pushOFFSETarray* callmean* addesp,000000008h

calldispsid

;顯示

exit0* push+000000000h* callExitProcess1 invokeExitProcess,0117〔例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]1182.條件控制類似高級(jí)語(yǔ)言中IF、THEN、ELSE和ENDIF的相應(yīng)功能在匯編時(shí)要展開(kāi),自動(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é)束條件119條件表達(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)

c

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論