已閱讀5頁,還剩89頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第5章 模塊化程序設(shè)計(jì),5.1 子程序結(jié)構(gòu) 5.2 參數(shù)傳遞 5.3 多模塊程序結(jié)構(gòu) 5.4 宏結(jié)構(gòu),第5章 模塊化程序設(shè)計(jì),問題的引入 子程序、文件包含、宏匯編等各種多模塊編程的方法,3,例1: 利用C語言編寫計(jì)算c=a+b,4,data segment a db ? b db ? c db ? string db c=$ data ends code segment main proc far assume cs:code, ds:data, es:data start: push ds sub ax,ax push ax mov ax,data mov ds,ax mov es,ax,mov a,1 mov b,2 mov al,a add al,b mov c,al lea dx,string mov ah,09 int 21h add c,30h mov dl,c mov ah,2 int 21h mov dl,0ah int 21h mov dl,0dh int 21h ret main endp code ends end start,例2:用匯編編寫:,5,5.1 子程序結(jié)構(gòu),經(jīng)常用到的應(yīng)用問題編寫成一個(gè)通用子程序 大型處理過程分解成能夠解決的模塊 使用子程序可以 使程序的結(jié)構(gòu)更為清楚 程序的維護(hù)更為方便 有利于大程序開發(fā)時(shí)的多個(gè)程序員分工合作,子程序(Subroutine) 函數(shù)(Function) 過程(Procedure),6,5.1.1 子程序指令,子程序 與主程序分開、完成特定功能的一段程序 主程序(調(diào)用程序) 執(zhí)行調(diào)用指令CALL調(diào)用子程序 子程序(被調(diào)用程序) 執(zhí)行返回指令RET返回主程序,CALL label,主程序,RET,子程序,回到CALL指令后的指令處-斷點(diǎn),7,1. 子程序調(diào)用指令CALL,CALL指令用在主程序中,實(shí)現(xiàn)子程序的調(diào)用 分成段內(nèi)調(diào)用(近調(diào)用)和段間調(diào)用(遠(yuǎn)調(diào)用) 目標(biāo)地址采用相對尋址、直接尋址或間接尋址 入棧返回地址:將CALL下條指令的地址壓入堆棧 CALL label ;調(diào)用標(biāo)號指定的子程序 CALL reg32/reg16 ;調(diào)用寄存器指定地址的子程序 CALL mem48/mem32/mem16 ;調(diào)用存儲單元指定地址的子程序,CALL,CS,EIP,Stack,CALL,8,2. 子程序返回指令RET,RET指令用在子程序結(jié)束,實(shí)現(xiàn)返回主程序 RET ;無參數(shù)返回:出棧返回地址 RET i16 ;有參數(shù)返回:出棧返回地址 ;ESPESPi16,MASM會(huì)根據(jù)存儲模型等信息確定子程序的遠(yuǎn)近調(diào)用,并相應(yīng)產(chǎn)生返回指令,RET,CS,EIP,Stack,CALL,RET,9,3. 過程定義偽指令,MASM利用過程定義偽指令獲得子程序信息 過程名 PROC ;過程體 過程名 ENDP ;過程名為符合語法的標(biāo)識符 PROC后面可加參數(shù):NEAR或FAR 簡化段定義源程序格式中,通常不需指定,10,例5-1子程序調(diào)用程序1,;代碼段,主程序 00000000 B8 00000001 mov eax,1 00000005 BD 00000005 mov ebp,5 0000000A E8 00000016 call subp;子程序調(diào)用 0000000F B9 00000003 retp1: mov ecx,3 00000014 BA 00000004 retp2: mov edx,4 00000019 E8 00000000 E call disprd ;代碼段,子程序 00000025 00000025 subp proc,offset retp1,Stack,CALL,11,例5-1子程序調(diào)用程序2,;代碼段,子程序 subp proc ;過程定義,過程名為subp push ebp mov ebp,esp mov esi,ebp+4 ;ESICALL下條指令(標(biāo)號RETP1)偏移地址 mov edi,offset retp2 ;EDI標(biāo)號RETP2的偏移地址 mov ebx,2 pop ebp ;彈出堆棧,保持堆棧平衡 ret ;子程序返回 subp endp ;過程結(jié)束,示意圖,12,子程序調(diào)用的堆棧,retp1,EBP,Stack,CALL SUBP,RET,PUSH EBP,低地址,高地址,POP EBP,ESP=EBP,13,5.1.2 子程序設(shè)計(jì),子程序的編寫方法與主程序一樣 但需要留意幾個(gè)問題: 利用過程定義,獲得子程序名和調(diào)用屬性 RET指令返回主程序,CALL指令調(diào)用子程序 壓入和彈出操作要成對使用,保持堆棧平衡 開始保護(hù)寄存器,返回前相應(yīng)恢復(fù) 安排在代碼段的主程序之外 子程序允許嵌套和遞歸,最好有完整的注釋,難點(diǎn)是參數(shù)傳遞,14,例5-2回車換行子程序,dpcrlf proc ;回車換行子程序 push eax ;保護(hù)寄存器 mov al,0dh ;輸出回車字符 call dispc ;子程序中調(diào)用子程序,實(shí)現(xiàn)子程序嵌套 mov al,0ah ;輸出換行字符 call dispc pop eax ;恢復(fù)寄存器 ret ;子程序返回 dpcrlf endp,15,5.2 參數(shù)傳遞,主程序與子程序間通過參數(shù)傳遞建立聯(lián)系 入口參數(shù)(輸入?yún)?shù)):主程序子程序 出口參數(shù)(輸出參數(shù)):子程序主程序 傳遞參數(shù)的多少反映程序模塊間的耦合程度 參數(shù)的具體內(nèi)容 數(shù)據(jù)本身(傳遞數(shù)值) 數(shù)據(jù)的存儲地址(傳遞地址,傳遞引用) 參數(shù)傳遞方法 寄存器 變量 堆棧,重點(diǎn),16,求校驗(yàn)和,子程序計(jì)算數(shù)組元素的“校驗(yàn)和” 校驗(yàn)和是指不記進(jìn)位的累加 入口參數(shù): 數(shù)組的偏移地址(傳址) 元素個(gè)數(shù)(傳值) 出口參數(shù): 求和結(jié)果(傳值),17,把參數(shù)存于約定的寄存器中,可以傳值,也可以傳址。 子程序?qū)в谐隹趨?shù)的寄存器不能保護(hù)和恢復(fù)(主程序視具體情況進(jìn)行保護(hù)) 子程序?qū)в腥肟趨?shù)的寄存器可以保護(hù),也可以不保護(hù);但最好一致 例a 入口參數(shù):ECX元素個(gè)數(shù), EBX數(shù)組的偏移地址 出口參數(shù):AL校驗(yàn)和,用寄存器傳遞參數(shù),18,;數(shù)據(jù)段 array byte 32,78,56,. count equ $-array result byte ? ;代碼段,設(shè)置入口參數(shù) mov ebx,offset array ;EBX數(shù)組的偏移地址 mov ecx,count ;ECX數(shù)組的元素個(gè)數(shù) call checksuma ;調(diào)用求和過程 mov result,al ;處理出口參數(shù),例a 主程序,19,checksuma proc xor al,al ;累加器清0 suma: add al,ebx ;求和 inc ebx ;指向下一個(gè)字節(jié) loop suma ret checksuma endp end,例a 子程序,20,主程序和子程序直接采用同一個(gè)變量名共享同一個(gè)變量,實(shí)現(xiàn)參數(shù)的傳遞 不同模塊間共享時(shí),需要聲明 例b 入口參數(shù): count元素個(gè)數(shù), array數(shù)組名(偏移地址) 出口參數(shù): result校驗(yàn)和,用變量傳遞參數(shù),21,;數(shù)據(jù)段 array byte 32,78,56,. count dword $-array result byte ? ;主程序 call checksumb ;子程序 checksumb proc push eax push ebx push ecx,例b1/2,22,xor al,al ;累加器清0 mov ebx,offset array ;EBX偏移地址 mov ecx,count ;ECX元素個(gè)數(shù) sumb: add al,ebx ;求和 inc ebx loop sumb mov result,al ;保存校驗(yàn)和 pop ecx pop ebx pop eax ret checksumb endp,例b2/2,23,主程序?qū)⒆映绦虻娜肟趨?shù)壓入堆棧,子程序從堆棧中取出參數(shù) 子程序?qū)⒊隹趨?shù)壓入堆棧,主程序彈出堆棧取得它們 例c 入口參數(shù): 順序壓入偏移地址和元素個(gè)數(shù) 出口參數(shù): AL校驗(yàn)和,用堆棧傳遞參數(shù),24,;數(shù)據(jù)段 array byte 32,78,56,. count equ $-array result byte ? mov eax,offset array push eax mov eax,count push eax call checksumc add esp,8 mov result,al,例c 主程序,offset array,count,EIP,Stack,PUSH AX,PUSH AX,CALL,25,checksumc proc push ebp mov ebp,esp ;EBP間接尋址存取參數(shù) push ebx push ecx mov ebx,ebp+12 ;偏移地址 mov ecx,ebp+8 ;元素個(gè)數(shù),例c 子程序-1/2,offset array,count,EIP,EBP,Stack,PUSH,+4,+8,+12,26,xor al,al sumc: add al,ebx inc ebx loop sumc pop ecx pop ebx pop ebp ret checksumc endp,例c 子程序-2/2,offset array,count,EIP,EBP,Stack,POP,27,5.2.1 寄存器傳遞參數(shù),最簡單和常用的參數(shù)傳遞方法 把參數(shù)存于約定的寄存器 少量數(shù)據(jù)直接傳遞數(shù)值 大量數(shù)據(jù)只能傳遞地址 帶有出口參數(shù)的寄存器不能保護(hù)和恢復(fù) 帶有入口參數(shù)的寄存器可以保護(hù)、也可以不保護(hù),但最好能夠保持一致,28,例5-3十六進(jìn)制顯示程序1,mov eax, 1234abcdh ;假設(shè)一個(gè)數(shù)據(jù) xor ebx,ebx mov ecx,8 ;8位十六進(jìn)制數(shù) again: rol eax,4 ;高4位循環(huán)移位進(jìn)入低4位 push eax ;mov edx,eax call htoasc ;調(diào)用子程序 mov regd+4ebx,al ;保存轉(zhuǎn)換后的ASCII碼 pop eax ;mov eax,edx inc ebx dec ecx jnz again mov eax,offset regd call dispmsg ;顯示,regd byte EAX=,8 dup(0),H,0,29,例5-3十六進(jìn)制顯示程序2,;子程序 htoasc proc ;將AL低4位表達(dá)的一位十六進(jìn)制數(shù)轉(zhuǎn)換為ASCII碼 and al,0fh ;只取AL的低4位 or al,30h ;AL高4位變成3 cmp al,39h ;是09,還是AF jbe htoend add al,7 ;是AF,ASCII碼再加上7 htoend: ret ;子程序返回 htoasc endp,30,例5-3十六進(jìn)制顯示程序3,;子程序 htoasc proc and eax,0fh ;取AL低4位 mov al,ASCIIeax ;換碼 ret ;子程序的局部數(shù)據(jù)(只讀) ASCII byte 0123456789ABCDEF htoasc endp,EAX=1234ABCDH,運(yùn)行結(jié)果,31,例5-4有符號十進(jìn)制數(shù)顯示程序1,轉(zhuǎn)換的算法如下: 1)首先判斷數(shù)據(jù)是零、正數(shù)或負(fù)數(shù),是零顯示“0”退出 2)是負(fù)數(shù),顯示負(fù)號“”,求數(shù)據(jù)的絕對值 3)接著數(shù)據(jù)除以10,余數(shù)為十進(jìn)制數(shù)碼,加30H轉(zhuǎn)換為ASCII碼保存 4)重復(fù)第(3)步,直到商為0結(jié)束 5)依次從高位開始顯示各位數(shù)字,32,例5-4有符號十進(jìn)制數(shù)顯示程序2,;數(shù)據(jù)段 array dword 1234567890,-1234,0,1,. writebuf byte 12 dup(0) ;顯示緩沖區(qū) ;代碼段 mov ecx,lengthof array mov ebx,0 again: mov eax,arrayebx*4 ;EAX入口參數(shù) call write ;調(diào)用子程序,顯示一個(gè)數(shù)據(jù) call dispcrlf ;換行以便顯示下一個(gè)數(shù)據(jù) inc ebx dec ecx jnz again,寄存器傳遞參數(shù),33,例5-4有符號十進(jìn)制數(shù)顯示程序3,;顯示有符號十進(jìn)制數(shù)的子程序 write proc ;EAX入口參數(shù) push ebx ;保護(hù)寄存器 push ecx push edx mov ebx,offset writebuf ;EBX指向顯示緩沖區(qū) test eax,eax ;判斷數(shù)據(jù)是零、正數(shù)或負(fù)數(shù) jnz write1 ;不是零,跳轉(zhuǎn) mov byte ptr ebx,0 ;是零,設(shè)置“0” inc ebx jmp write5 ;轉(zhuǎn)向顯示 write1: jns write2 ;是正數(shù),跳轉(zhuǎn),寄存器傳遞參數(shù),34,例5-4有符號十進(jìn)制數(shù)顯示程序4,mov byte ptr ebx,- ;是負(fù)數(shù),設(shè)置負(fù)號 inc ebx neg eax ;數(shù)據(jù)求補(bǔ)(絕對值) write2: mov ecx,10 push ecx ;10壓入堆棧,作為退出標(biāo)志 write3: cmp eax,0 ;數(shù)據(jù)(商)為零,轉(zhuǎn)向保存 jz write4 xor edx,edx ;零位擴(kuò)展被除數(shù)為EDX.EAX div ecx ;數(shù)據(jù)除以10:EDX.EAX10 add edx,30h ;余數(shù)(09)轉(zhuǎn)換為ASCII碼 push edx ;數(shù)據(jù)先低位后高位壓入堆棧 jmp write3,35,例5-4有符號十進(jìn)制數(shù)顯示程序5,write4: pop edx ;數(shù)據(jù)先高位后低位彈出堆棧 cmp edx,ecx ;是結(jié)束標(biāo)志10,轉(zhuǎn)向顯示 je write5 mov ebx,dl ;數(shù)據(jù)保存到緩沖區(qū) inc ebx jmp write4 write5: mov byte ptr ebx,0 ;顯示內(nèi)容加上結(jié)尾標(biāo)志 mov eax,offset writebuf call dispmsg pop edx ;恢復(fù)寄存器 pop ecx pop ebx ret ;子程序返回 write endp,36,5.2.2 共享變量傳遞參數(shù),子程序和主程序使用同一個(gè)變量名存取數(shù)據(jù) 如果變量定義和使用不在同一個(gè)程序模塊中,需要利用PUBLIC、EXTREN聲明 共享變量傳遞參數(shù),子程序的通用性較差 特別適合在多個(gè)程序段間、尤其在不同的程序模塊間傳遞數(shù)據(jù),37,例5-5二進(jìn)制輸入程序1,;數(shù)據(jù)段 count = 5 array dword count dup(0) temp dword ? ;共享變量 ;代碼段,主程序 mov ecx,count mov ebx,offset array again: call rdbd ;調(diào)用子程序,輸入一個(gè)數(shù)據(jù) mov eax,temp ;獲得出口參數(shù) mov ebx,eax ;存放到數(shù)據(jù)緩沖區(qū) add ebx,4 loop again,38,例5-5二進(jìn)制輸入程序2,;代碼段,子程序 rdbd proc ;二進(jìn)制輸入子程序 push eax ;出口參數(shù):共享變量TEMP push ebx push ecx rdbd1: xor ebx,ebx ;EBX用于存放二進(jìn)制結(jié)果 mov ecx,32 ;限制輸入字符的個(gè)數(shù) rdbd2: call readc ;輸入一個(gè)字符 cmp al,0 ;檢測鍵入字符是否合法 jb rderr ;不合法則返回重新輸入 cmp al,1 ja rderr,39,例5-5二進(jìn)制輸入程序3,sub al,0 ;對輸入的字符進(jìn)行轉(zhuǎn)化 shl ebx,1 ;EBX的值乘以2 or bl,al ;BL和AL相加 loop rdbd2 ;循環(huán)鍵入字符 mov temp,ebx ;把二進(jìn)制結(jié)果存放TEMP返回 call dispcrlf ;分行 pop ecx pop ebx pop eax ret,40,例5-5二進(jìn)制輸入程序4,rderr: mov eax,offset errmsg ;顯示錯(cuò)誤信息 call dispmsg jmp rdbd1 errmsg byte 0dh,0ah,Input error, enter again: ,0 rdbd endp,41,例5-6有符號十進(jìn)制數(shù)輸入程序1,十進(jìn)制有符號整數(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ù)值保存,42,例5-6有符號十進(jìn)制數(shù)輸入程序2,;數(shù)據(jù)段 count = 10 array dword count dup(0) temp dword ? readbuf byte 30 dup(0) ;代碼段 mov ecx,count mov ebx,offset array again: call read ;調(diào)用子程序,輸入一個(gè)數(shù)據(jù) mov eax,temp ;獲得出口參數(shù) mov ebx,eax ;存放到數(shù)據(jù)緩沖區(qū) add ebx,4 dec ecx jnz again,共享變量傳遞參數(shù),43,例5-6有符號十進(jìn)制數(shù)輸入程序3,;輸入有符號十進(jìn)制數(shù)的子程序 read proc ;出口參數(shù):變量TEMP補(bǔ)碼表示的二進(jìn)制數(shù)值 push eax ;說明:負(fù)數(shù)用“”引導(dǎo) push ebx push ecx push edx read0: mov eax,offset readbuf call readmsg ;輸入一個(gè)字符串 test eax,eax jz readerr ;沒有輸入數(shù)據(jù),錯(cuò)誤 cmp eax,12 ja readerr ;輸入超過12個(gè)字符,錯(cuò)誤,44,例5-6有符號十進(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è)字符 cmp al,+ ;是“”,繼續(xù) jz read1 cmp al,- ;是“”,設(shè)置1標(biāo)志 jnz read2 mov ecx,-1 read1: inc edx ;取下一個(gè)字符 mov al,edx test al,al ;是結(jié)尾0,轉(zhuǎn)向求補(bǔ)碼 jz read3,45,例5-6有符號十進(jìn)制數(shù)輸入程序5,read2: cmp al,0 ;不是09之間的數(shù)碼,錯(cuò)誤 jb readerr cmp al,9 ja readerr sub al,30h ;是09之間的數(shù)碼,轉(zhuǎn)換 imul ebx,10 ;原數(shù)值乘10:EBXEBX10 jc readerr ;CF1,乘積溢出,出錯(cuò) movzx eax,al ;零位擴(kuò)展,便于相加 add ebx,eax ;原數(shù)乘10后,與新數(shù)碼相加 cmp ebx,80000000h ;數(shù)據(jù)超過231,出錯(cuò) jbe read1 ;繼續(xù)轉(zhuǎn)換下一個(gè)數(shù)位,46,例5-6有符號十進(jìn)制數(shù)輸入程序6,readerr: mov eax,offset errmsg ;顯示出錯(cuò)信息 call dispmsg jmp read0 ; read3: test ecx,ecx ;判斷是正數(shù)還是負(fù)數(shù) jz read4 neg ebx ;是負(fù)數(shù),進(jìn)行求補(bǔ) jmp read5 read4: cmp ebx,7fffffffh ;正數(shù)超過231-1,出錯(cuò) ja readerr,47,例5-6有符號十進(jìn)制數(shù)輸入程序7,read5: mov temp,ebx ;設(shè)置出口參數(shù) pop edx pop ecx pop ebx pop eax ret ;子程序返回 errmsg byte Input error, enter again: ,0 read endp,共享變量傳遞參數(shù),48,5.2.3 堆棧傳遞參數(shù),主程序?qū)⑷肟趨?shù)壓入堆棧,子程序從堆棧中取出參數(shù) 出口參數(shù)通常不使用堆棧傳遞 高級語言進(jìn)行函數(shù)調(diào)用時(shí)提供的參數(shù),實(shí)質(zhì)也利用堆棧傳遞 采用堆棧傳遞參數(shù)是程式化的,它是編譯程序處理參數(shù)傳遞、以及匯編語言與高級語言混合編程時(shí)的常規(guī)方法,49,例5-7計(jì)算有符號數(shù)平均值程序1,;數(shù)據(jù)段 array dword 675,354,-34, . ;代碼段 push lengthof array ;壓入數(shù)據(jù)個(gè)數(shù) push offset array ;壓數(shù)組的偏移地址 call mean ;調(diào)用求平均值子程序 ;出口參數(shù):EAX平均值(整數(shù)部分) add esp,8 ;平衡堆棧(壓入了8個(gè)字節(jié)數(shù)據(jù)) call dispsid ;顯示,堆棧傳遞參數(shù),50,例5-7計(jì)算有符號數(shù)平均值程序2,;計(jì)算32位有符號數(shù)平均值子程序 mean proc ;入口參數(shù):順序壓入數(shù)據(jù)個(gè)數(shù)和數(shù)組偏移地址 push ebp ;出口參數(shù):EAX平均值 mov ebp,esp push ebx ;保護(hù)寄存器 push ecx push edx mov ebx,ebp+8 ;EBX取出的偏移地址 mov ecx,ebp+12 ;ECX取出的數(shù)據(jù)個(gè)數(shù) xor eax,eax ;EAX保存和值 xor edx,edx ;EDX指向數(shù)組元素,堆棧傳遞參數(shù),51,例5-7計(jì)算有符號數(shù)平均值程序3,mean1: add eax,ebx+edx*4 ;求和 add edx,1 ;指向下一個(gè)數(shù)據(jù) cmp edx,ecx ;比較個(gè)數(shù) jb mean1 ;循環(huán) cdq ;將累加和EAX符號擴(kuò)展到EDX idiv ecx ;有符號數(shù)除法,EAX平均值 pop edx ;恢復(fù)寄存器 pop ecx pop ebx pop ebp ret mean endp,示意圖,52,利用堆棧傳遞參數(shù),返回,Lengthof array,offset array,斷點(diǎn) EIP,EBP,Stack,PUSH,POP,53,5.4 宏結(jié)構(gòu),本書統(tǒng)稱的宏結(jié)構(gòu) 宏匯編 重復(fù)匯編 條件匯編 用于簡化源程序結(jié)構(gòu),子程序等多模塊結(jié)構(gòu)用于簡化目標(biāo)代碼,54,5.4.1 宏匯編,宏(Macro):具有宏名的一段匯編語句序列 宏需要先定義 宏名 MACRO 形參表 ;宏定義體 ENDM 然后程序中進(jìn)行宏調(diào)用 宏名 實(shí)體參數(shù) 在匯編時(shí),宏指令被匯編程序用宏定義的代碼序列替代,實(shí)現(xiàn)宏展開,55,1. 宏定義和宏調(diào)用,宏定義 WriteString macro msg push eax lea eax,msg call dispmsg pop eax endm,宏展開 push eax lea eax,msg call dispmsg pop eax,宏調(diào)用 WriteString msg,56,2. 宏與子程序,僅是源程序級的簡化:宏調(diào)用在匯編時(shí)進(jìn)行程序語句的展開,不需要返回;不減小目標(biāo)程序,執(zhí)行速度沒有改變 通過形參、實(shí)參結(jié)合實(shí)現(xiàn)參數(shù)傳遞,簡捷直觀、靈活多變 當(dāng)程序段較短或要求較快執(zhí)行時(shí),應(yīng)選用宏,還是目標(biāo)程序級的簡化:子程序調(diào)用在執(zhí)行時(shí)由CALL指令轉(zhuǎn)向、RET指令返回;形成的目標(biāo)代碼較短,執(zhí)行速度減慢 需要利用寄存器、存儲單元或堆棧等傳遞參數(shù) 當(dāng)程序段較長或?yàn)闇p小目標(biāo)代碼時(shí),要選用子程序,57,5.3 多模塊程序結(jié)構(gòu),程序分段、子程序等實(shí)現(xiàn)了程序模塊化 開發(fā)大型應(yīng)用程序時(shí)常使用多個(gè)源程序文件、目標(biāo)代碼模塊等組成完整的程序 MASM具體支持的方法 源文件包含 模塊連接 子程序庫 庫文件包含,58,5.3.1 源文件包含,大型源程序可以合理地分放在若干個(gè)文本文件中 各種常量定義、聲明語句等組織在包含文件(*.INC) 常用的或有價(jià)值的宏定義存放在宏定義文件(*.MAC) 常用的子程序形成匯編語言源文件(*.ASM) 任何文本文件 使用源文件包含偽指令I(lǐng)NCLUDE將指定的文本文件內(nèi)容插入主體源程序文件 INCLUDE 文件名 利用INCLUDE偽指令包含其他文件,其實(shí)質(zhì)仍然是一個(gè)源程序,只不過是分在了幾個(gè)文件書寫 子程序庫文件名要符合操作系統(tǒng)規(guī)范,59,例5-8存儲器數(shù)據(jù)顯示程序1,;文件名:eg0508.inc,例5-8程序的數(shù)據(jù)段內(nèi)容 .data ;數(shù)據(jù)段 dvar dword 1234abcdh inmsg byte Enter Memory Address: ,0 outmsg1 byte Memory Data In HexDecimal: ,0 outmsg1 byte Memory Data In Signed Decimal: ,0 temp dword ? ;共享變量 writebuf byte 12 dup(0) ;十進(jìn)制輸出的顯示緩沖區(qū),包含文件,60,例5-8存儲器數(shù)據(jù)顯示程序2,;文件名:eg0508.asm,例5-8主程序 include io32.inc ;源文件包含:32位I/O文件 include eg0508.inc ;源文件包含:數(shù)據(jù)段文件 .code ;代碼段,主程序 start: mov temp,offset dvar call dphd ;十六進(jìn)制輸出,顯示變量DVAR地址以便輸入 call dispcrlf mov eax,offset inmsg call dispmsg call rdhd ;輸入存儲器地址,EAX返回 call dispcrlf,主程序文件,61,例5-8存儲器數(shù)據(jù)顯示程序3,mov ebx,eax ;EBX=存儲器數(shù)據(jù) mov eax,offset outmsg1 call dispmsg mov temp,ebx ;共享變量傳遞參數(shù) call dphd ;十六進(jìn)制輸出 call dispcrlf mov eax,offset outmsg2 call dispmsg mov eax,ebx ;寄存器傳遞參數(shù) call write ;十進(jìn)制輸出 exit 0 ;主程序結(jié)束,退出 include eg0508s.asm ;源文件包含:子程序文件 end start,主程序文件,62,例5-8存儲器數(shù)據(jù)顯示程序4,;文件名:eg0508s.asm,例5-8程序的子程序 rdhd proc ;十六進(jìn)制輸入子程序 push ebx ;出口參數(shù):EAX=輸入的數(shù)據(jù) push ecx rdhd1: xor ebx,ebx ;EBX用于存放十六進(jìn)制結(jié)果 mov ecx,8 ;限制輸入字符的個(gè)數(shù) rdhd2: call readc ;輸入一個(gè)字符 cmp al,0 ;檢測鍵入字符是否合法 jb rderr ;不合法則返回重新輸入 cmp al,9 jbe rdhd4 ;輸入數(shù)碼:09,減30H,子程序文件,63,例5-8存儲器數(shù)據(jù)顯示程序5,cmp al,A jb rderr cmp al,F jbe rdhd3 ;輸入大寫字母:AF,減7后、再減30H cmp al,a jb rderr cmp al,f ;輸入小寫字母:af,減20H、減7后、再減30H ja rderr sub al,20h ;減20H rdhd3: sub al,7 ;減7 rdhd4: sub al,30h ;減30H,子程序文件,64,例5-8存儲器數(shù)據(jù)顯示程序6,shl ebx,4 ;EBX左移4位對應(yīng)十六進(jìn)制一位 or bl,al ;BL和AL相加 loop rdhd2 ;循環(huán)鍵入字符 mov eax,ebx ;通過EAX返回結(jié)果 pop ecx pop ebx ret rderr: mov eax,offset errmsg call dispmsg jmp rdhd1 errmsg byte 0dh,0ah,Input error, enter again: ,0 rdhd endp,子程序文件,示意圖,65,例5-8程序的運(yùn)行示例,返回,66,5.3.2 模塊連接,子程序單獨(dú)編寫,匯編形成目標(biāo)模塊OBJ文件 連接時(shí)輸入子程序模塊文件名 用共用偽指令PUBLIC和外部偽指令EXTERN聲明 PUBLIC 標(biāo)識符 ,標(biāo)識符 ;定義標(biāo)識符的模塊使用 EXTERN 標(biāo)識符:類型 ,標(biāo)識符:類型 ;調(diào)用標(biāo)識符的模塊使用 子程序在代碼段,與主程序文件采用相同的存儲模型,沒有開始執(zhí)行和結(jié)束執(zhí)行點(diǎn) 處理好子程序與主程序之間的參數(shù)傳問題,67,例5-8存儲器數(shù)據(jù)顯示程序7,;文件名:eg0508es.asm,例5-8程序的子程序 include io32.inc public rdhd,dphd,write ;子程序共用 extern temp:dword ;外部變量 .data ;數(shù)據(jù)段 writebuf byte 12 dup(0) ;顯示緩沖區(qū) .code ;代碼段,子程序 rdhd proc c ;十六進(jìn)制輸入子程序 ;略,同EG0508S.ASM文件 end ;匯編結(jié)束,子程序文件,68,例5-8存儲器數(shù)據(jù)顯示程序8,;文件名:eg0508e.asm,例5-8主程序 include io32.inc ;數(shù)據(jù)段 extern rdhd:near,dphd:near,write:near ;外部子程序 public temp ;變量共用 .code ;代碼段 ,主程序文件,ML /c /coff eg0508e.asm ML /c /coff eg0508es.asm LINK32 /subsystem:console eg0508e.obj eg0508es.obj,操作過程,69,5.3.3 子程序庫,子程序庫:統(tǒng)一管理子程序模塊 遵循更加嚴(yán)格的子程序模塊要求 子程序文件編寫完成、匯編形成目標(biāo)模塊 利用庫管理工具程序LIB.EXE:把子程序模塊逐個(gè)加入到子程序庫(.LIB) 使用子程序庫:在連接主程序模塊時(shí)提供子程序庫文件名,LIB32 /OUT:eg0508.lib eg0508es.obj LINK32 /subsystem:console eg0508e.obj eg0508.lib,操作過程,70,庫文件包含,直接在主程序源文件中用庫文件包含偽指令I(lǐng)NCLUDELIB說明 不用在連接時(shí)輸入庫文件名 INCLUDELIB 文件名,;declare procedures extern readc:near, readmsg:near extern dispc:near, dispmsg:near, dispcrlf:near . ;declare I/O libraries includelib io32.lib,IO32.INC,71,5.4 宏結(jié)構(gòu),本書統(tǒng)稱的宏結(jié)構(gòu) 宏匯編 重復(fù)匯編 條件匯編 用于簡化源程序結(jié)構(gòu),子程序等多模塊結(jié)構(gòu)用于簡化目標(biāo)代碼,72,5.4.1 宏匯編,宏(Macro):具有宏名的一段匯編語句序列 宏需要先定義 宏名 MACRO 形參表 ;宏定義體 ENDM 然后程序中進(jìn)行宏調(diào)用 宏名 實(shí)體參數(shù) 在匯編時(shí),宏指令被匯編程序用宏定義的代碼序列替代,實(shí)現(xiàn)宏展開,73,1. 宏定義和宏調(diào)用,宏定義 WriteString macro msg push eax lea eax,msg call dispmsg pop eax endm,宏展開 push eax lea eax,msg call dispmsg pop eax,宏調(diào)用 WriteString msg,74,例5-9狀態(tài)標(biāo)志顯示程序1,;宏定義 rfbit macro bit1,bit2 xor ebx,ebx ;EBX清0,用于保存字符 rol eax,bit1 ;將某個(gè)標(biāo)志左移BIT1位,進(jìn)入當(dāng)前CF adc ebx,30h ;轉(zhuǎn)換為ASCII字符 mov rfmsg+bit2,bl ;保存于字符串BIT2位置 endm ;數(shù)據(jù)段 rfmsg byte OF=0,SF=0,ZF=0,AF=0,PF=0,CF=0,13,10,0,75,例5-9狀態(tài)標(biāo)志顯示程序2,;代碼段 mov eax,50 sub eax,80 ;假設(shè)一個(gè)運(yùn)算 pushfd ;將標(biāo)志位寄存器的內(nèi)容壓入堆棧 pop eax ;將標(biāo)志位寄存器的內(nèi)容存入EAX rfbit 21,3 ;顯示OF(原來的OF需左移21位,進(jìn)入當(dāng)前CF) rfbit 4,9 ;顯示SF(原來的SF再左移4位,進(jìn)入當(dāng)前CF) ,76,例5-9狀態(tài)標(biāo)志顯示程序3,rfbit 21,3 ;顯示OF(原來的OF需左移21位,進(jìn)入當(dāng)前CF) 1 xor ebx,ebx ;EBX清0,用于保存字符 1 rol eax,21 ;將某個(gè)標(biāo)志左移BIT1位,進(jìn)入當(dāng)前CF 1 adc ebx,30h ;轉(zhuǎn)換為ASCII字符 1 mov rfmsg+3,bl ;保存于字符串BIT2位置,77,2. 宏的參數(shù)和宏的操作符(1),宏定義 asciiz macro string byte &string&,0 endm,宏展開 byte This is a example.,0,宏調(diào)用 asciiz ,傳遞操作符,替換操作符,78,2. 宏的參數(shù)和宏的操作符(2),宏定義 asciiz macro string byte &string&,0 endm,宏展開 byte 0 Number 10,0,宏調(diào)用 asciiz ,轉(zhuǎn)義操作符,79,2. 宏的參數(shù)和宏的操作符(3),宏定義 asciiz macro string byte &string&,0 endm,宏展開 byte 1023,0,宏調(diào)用 asciiz %(1024-1),表達(dá)式操作符,80,3. 宏的偽指令,局部偽指令 LOCAL 標(biāo)號列表 ;宏定義體采用了標(biāo)號,應(yīng)使用LOCAL加以說明 ;它必須是宏定義MACRO語句之后的第一條語句 刪除宏定義偽指令 PURGE 宏名表 ;不需要某個(gè)宏定義時(shí),可以把它刪除 宏定義退出偽指令 EXITM ;表示結(jié)束當(dāng)前宏調(diào)用的展開,81,局部偽指令,宏定義 absol macro oprd local next cmp oprd,0 jge next neg oprd next: endm ;這個(gè)偽指令要獨(dú)占一行,宏調(diào)用和宏展開 absol word ptr ebx cmp word ptr ebx,0 jge ?0000 neg word ptr ebx ?0000:,82,例5-10通用寄存器顯示程序1,dreg32 macro reg32 local dreg1,dreg2 mov eax,reg32 ;顯示reg32寄存器 mov ecx,8 xor ebx,ebx dreg1: rol eax,4 mov edx,eax and dl,0fh add dl,30h ;轉(zhuǎn)化為相應(yīng)的ASCII碼值 cmp dl,39h ;區(qū)別09和AF數(shù)碼 jbe dreg2 add dl,7,83,例5-10通用寄存器顯示程序2,dreg2: mov rd代碼段,顯示EAX dreg32 eax ,84,4. 宏與子程序,僅是源程序級的簡化:宏調(diào)用在匯編時(shí)進(jìn)行程序語
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026廣東廣州天河區(qū)工信部電子五所軟件與系統(tǒng)研究部招聘備考題庫帶答案詳解(完整版)
- 2026廣清經(jīng)濟(jì)特別合作區(qū)廣佛(佛岡)產(chǎn)業(yè)園管委會(huì)采購和財(cái)政評審監(jiān)管崗雇員招聘1人備考題庫(廣東)帶答案詳解(完整版)
- 2026上半年貴州事業(yè)單位聯(lián)考貴陽學(xué)院招聘5人備考題庫(含答案詳解)
- 2026四川宜賓市中醫(yī)醫(yī)院第一次自主招聘工作人員3人備考題庫帶答案詳解(培優(yōu)b卷)
- 2026上半年貴州事業(yè)單位聯(lián)考黔西南州招聘1085人備考題庫附參考答案詳解(達(dá)標(biāo)題)
- 2026新疆伊犁州奎屯市招聘公益性崗位2人備考題庫附答案詳解(奪分金卷)
- 2025年醫(yī)療廢棄物處理技術(shù)創(chuàng)新與中心建設(shè)可行性研究新視角報(bào)告
- 化工廠安全管理制度
- 2025年湖北省公務(wù)員面試真題強(qiáng)化練習(xí)題目及參考答案
- 2025年陜西省中考英語試題卷(含答案及解析)
- T/GMIAAC 002-20232型糖尿病強(qiáng)化管理、逆轉(zhuǎn)及緩解診療標(biāo)準(zhǔn)與技術(shù)規(guī)范
- 科學(xué)教師培訓(xùn)課件
- 股權(quán)激勵(lì)協(xié)議范本
- 2024生物樣本庫中生物樣本處理方法的確認(rèn)和驗(yàn)證要求
- 國產(chǎn)電視劇報(bào)審表
- 農(nóng)業(yè)技術(shù)推廣指導(dǎo)-農(nóng)業(yè)推廣的概念與基本原理
- TCSAE 153-2020 汽車高寒地區(qū)環(huán)境適應(yīng)性試驗(yàn)方法
- 乳液聚合乳液聚合機(jī)理
- 4D廚房設(shè)備設(shè)施管理責(zé)任卡
- JJG 195-2019連續(xù)累計(jì)自動(dòng)衡器(皮帶秤)
評論
0/150
提交評論