600 likes | 846 Views
第 5 章 : 程序. 本章概述. 連結外部函式庫 運用程序的程式設計 堆疊運算 定義和使用程序 運用程序的程式設計. 本書所用的連結函式庫. 連結函市庫概觀 呼叫一個函市庫程序 到一個函市庫連結 函市庫程序-概觀 六個例子. 連結函市庫概觀. 一個包含已經進入機器之內被編譯的程序的檔案 從一個或更多的 OBJ 檔案構造 建立一間函式庫 . . . 從一或更多的 ASM 來源檔案開始 組合每個進入一個 OBJ 檔案 創造一個空的函市庫檔案(延長 LIB ) 把 OBJ 檔案 ( s )加入函市庫檔案,使用微軟 LIB 實效.
E N D
本章概述 • 連結外部函式庫 • 運用程序的程式設計 • 堆疊運算 • 定義和使用程序 • 運用程序的程式設計
本書所用的連結函式庫 • 連結函市庫概觀 • 呼叫一個函市庫程序 • 到一個函市庫連結 • 函市庫程序-概觀 • 六個例子
連結函市庫概觀 • 一個包含已經進入機器之內被編譯的程序的檔案 • 從一個或更多的 OBJ 檔案構造 • 建立一間函式庫 . . . • 從一或更多的ASM來源檔案開始 • 組合每個進入一個 OBJ 檔案 • 創造一個空的函市庫檔案(延長 LIB) • 把 OBJ 檔案 (s)加入函市庫檔案,使用微軟 LIB 實效 藉由在這一個螢幕的底部按下例子快看 Irvine32. asm.
呼叫一個函市庫程序 • 呼叫使用指令的一個函市庫程序.一些程序需要輸入引數.那在程序原型中包括指令的副本(公告). • 下列的例子在控制檯上顯示 "1234" : INCLUDE Irvine32.inc .code mov eax,1234h ; input argument call WriteHex ; show hex number call Crlf ; end of line
到一個函市庫連接 • 對使用一個被命名的檔案裡連接器指令 Irvine32. lib 你的程式連結make32.bat. • 注意二個 LIB 檔案:Irvine32. lib, 和kerne32.lib • 後者是微軟贏 32 軟體發展配套的部份(SDK)
下一章 • 連結外部函式庫 • 本書所用的連結函式庫 • 堆疊運算 • 定義而且使用程序 • 運用程序的程式設計
函式庫程序-概觀(1 of 4) CloseFile -將先前開啟的磁碟檔案予以關閉 Clrscr -清除主控台視窗,並將游標重新定位於左上角 CreateOutputFile -建立一個能在輸出模式下寫入資料的新磁碟檔案 Crlf -寫入一個行末 (end-of-line) 標記到主控台視窗 Delay -將程式的執行暫停n個毫秒的時間間隔 DumpMem -以十六進位的表示方式,將一個區塊的記憶體內容寫入到主控台視窗 DumpRegs –以十六進位的方式顯示EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP、 EFLAGS 及EIP 等暫存器的內容值。同時也顯示最常用到的CPU 狀態旗標 GetCommandtail -複製程式命令列的參數 ( 也稱為command tail) 到一個由位元組所組成的陣列裡 GetMaxXY -取得主控台視窗的緩衝區的行數與列數 GetMseconds -回傳一個從午夜十二點之後所經過的時間值,以毫秒為單位
函式庫程序-概觀(2 of 4) GetTextColor -回傳現行的主控台視窗的文字顏色和底色 Gotoxy -在主控台視窗中,將游標定位到指定的行與列的位置上 IsDigit -如果AL 暫存器所含有的ASCII 碼是十進位數字(0-9),則設定零值旗標 MsgBox, MsgBoxAsk –顯示一個彈出式訊息視窗,在彈出式視窗中顯示是/ 否的問題 OpenInputFile –開啟一個現存的磁碟檔案用於輸入 ParseDecimal32 –將一個無號的十進位整數字串轉換成32 位元二進位整數 ParseInteger32 -將一個有號的十進位整數字串轉換成32 位元二進位整數 Random32 -產生一個32 位元的擬隨機整數,其數值範圍在0到FFFFFFFF 之間 Randomize -以一個唯一值,作為隨機數產生器的種數 RandomRange -產生一個位於某個指定範圍內的擬隨機整數 ReadChar -等待一個由鍵盤所輸入的單一字元,並且回傳該字元
函式庫程序-概觀(3 of 4) ReadFromFile –由輸入的磁碟檔案讀取資料到緩衝區中 ReadDec -由鍵盤讀取一個無號的32 位元十進位整數,並且在接收到Enter 鍵時結束讀取動作 ReadHex -由鍵盤讀取一個32 位元的十六進位整數,並在接收到[Enter] 鍵時結束讀取動作 ReadInt -由鍵盤讀取一個32 位元的有號十進位整數,並且在接收到[Enter ] 鍵時結束讀取動作 ReadKey –在不等待輸入動作的情形下,由鍵盤的輸入緩衝區讀取一個字元 ReadString -由鍵盤讀取一個字串,並且在接收到Enter 鍵時結束讀取的動作 SetTextColor -設定隨後要輸出到主控台的文字的顏色和底色 StrLength –回傳字串的長度 WaitMsg -顯示一個訊息,並且等待一個鍵被按下 WriteBin -以ASCII 二進位格式,寫入一個無號的32 位元整數到主控台視窗 WriteBinB –以位元組、字組或雙字組的格式,將一個二進位整數寫到主控台視窗 WriteChar -將單一個字元寫入到主控台視窗
函式庫程序-概觀(4 of 4) WriteDec -以十進位格式寫入一個無號的32 位元整數到主控台視窗 WriteHex -以十六進位格式寫入一個無號的32 位元整數到主控台視窗 WriteHexB –以十六進位格式,將一個位元組、字組或雙字組整數寫到主控台視窗 WriteInt -以十進位格式寫入一個有號的32 位元整數到主控台視窗 WriteString -將一個以空字元作為結尾的字串寫到主控台視窗 WriteToFile -將一個緩衝區寫到輸出檔案 WriteWindowsMsg -將含有由MS-Windows 所產生最近一個訊息的字串顯示出來
樣本輸出: EAX=00000613 EBX=00000000 ECX=000000FF EDX=00000000 ESI=00000000 EDI=00000100 EBP=0000091E ESP=000000F6 EIP=00401026 EFL=00000286 CF=0 SF=1 ZF=0 OF=0 例子1 清除螢幕,為 500 毫秒延遲計畫,而且傾卸暫存器和旗標. .code call Clrscr mov eax,500 call Delay call DumpRegs
例子 2 顯示零-結束了列而且移動游標到下一個螢幕線的開始. .data str1 BYTE "Assembly language is easy!",0 .code mov edx,OFFSET str1 call WriteString call Crlf
例子 2a 顯示零-結束了字串而且移動游標到下一個螢幕線的開始(使用植入的 CR/LF) .data str1 BYTE "Assembly language is easy!",0Dh,0Ah,0 .code mov edx,OFFSET str1 call WriteString
Sample output : 0000 0000 0000 0000 0000 0000 0010 0011 35 23 例子 3 顯示在二進位,十進位和十六進位的一個未被簽署的整數,每個在一條單獨的列上 IntVal = 35 .code mov eax,IntVal call WriteBin ; display binary call Crlf call WriteDec ; display decimal call Crlf call WriteHex ; display hexadecimal call Crlf
Example 4 輸入來自使用者的字串。 EDX 指向線和 ECX 記載使用者被允許進入的最大字元的數字。 .data fileName BYTE 80 DUP(0) .code mov edx,OFFSET fileName mov ecx,SIZEOF fileName – 1 call ReadString 一個無效力的位元組自動地到字串被附加.
例子 5 產生並且顯示十個假散亂在範圍 0-99 中標示整數.在一條單獨的列上通過每個整數給在 EAX 中的 WriteInt 而且顯示它。 .code mov ecx,10 ; loop counter L1: mov eax,100 ; ceiling value call RandomRange ; generate random int call WriteInt ; display signed int call Crlf ; goto next display line loop L1 ; repeat loop
例子 6 顯示零-和在藍色的背景上的黃色的個性結束了字串. .data str1 BYTE "Color output is easy!",0 .code mov eax,yellow + (blue * 16) call SetTextColor mov edx,OFFSET str1 call WriteString call Crlf 背景顏色在 16 點之前在被加到前景顏色之前被繁殖。
下一章 • 連結外部函式庫 • 本書所用的連結函式庫 • 堆疊運算 • 定義和使用程序 • 運用程序的程式設計
堆疊運算 • 執行時期堆疊 • PUSH 運算 • POP 運算 • PUSH 和 POP指令 • 使用 PUSH 和 POP • 例子:字串倒轉 • 相關的指令
執行時期堆疊 • 想像板塊的堆疊. . . • 板塊只被加到頂端 • 板塊只從頂端被移動 • LIFO結構
執行時期堆疊 • 藉著中央處理器處理,使用二個暫存器 • SS (堆疊片段) • ESP (堆疊指針) * * SP in Real-address mode
PUSH 運算(1 of 2) • 一個 32位元推動行動漸減堆疊指針在 4 之前而且拷貝價值進入被堆疊指針指向的地點。
PUSH 運算 (2 of 2) • 相同的堆疊在推動另外二個整數之後: 在 ESP 下面的區域總是可得的。(除非堆疊已經氾濫)
POP 運算 • 副本進入一個暫存器或變數之內在堆疊〔ESP〕評價. • 把 n 加入 ESP, n 是或 2 或 4. • n 的價值靠接受資料的運算元的屬性
PUSH 和 POP 指令 • PUSH 語法: • PUSH r/m16 • PUSH r/m32 • PUSH imm32 • POP 語法: • POP r/m16 • POP r/m32
使用 PUSH 和 POP 當他們包含重要的價值時候,解救而且回復暫存器.PUSH和POP協議指導在相反的次序中發生 . push esi ; push registers push ecx push ebx mov esi,OFFSET dwordVal ; display some memory mov ecx,LENGTHOF dwordVal mov ebx,TYPE dwordVal call DumpMem pop ebx ; restore registers pop ecx pop esi
例子:築巢環路 當創造一個被巢狀環路的時候,在進入內部的環路之前推動外部的環路櫃台: mov ecx,100 ; set outer loop count L1: ; begin the outer loop push ecx ; save outer loop count mov ecx,20 ; set inner loop count L2: ; begin the inner loop ; ; loop L2 ; repeat the inner loop pop ecx ; restore outer loop count loop L1 ; repeat the outer loop
例子:字串倒轉 • 和編入索引一起使用一個環演說 • push在堆疊上的每個字符 • 從最初的地方開始字串,彈出在反面的次序中的堆疊,進入字串之內把每個字符插入回來 • 原始碼 • Q: 壓入之前,為什麼每個字符必須被提出 EAX? 因為只有字 (16 位元)或 doubleword(32 位元)價值能是急忙前進壓入。
你輪到的. . . • 以相反規劃的字串作為出發點, • #1:修正計畫,如此使用者能輸入在 1 和 50個字符之間包含的字串. • #2:修正計畫,如此它輸入來自使用者的一連串的 32 位元整數,然後在反面的次序中顯示整數.
相關的指令 • PUSHFD 和 POPFD • push 和 pop the EFLAGS 暫存器 • PUSHAD 推動在堆疊上的 32 位元泛用型的暫存器 • 命令: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI • POPAD 在反面的次序中從堆疊彈出相同的暫存器 • PUSHA 和 POPA 為 16 位元暫存器做一樣的
你輪到的. . . • 寫一個跟隨的計畫: • 分配整數價值到 EAX , EBX , ECX , EDX , ESI 和 EDI • 使用 PUSHAD 推動在堆疊上的泛用型的暫存器 • 使用一個環路,你的計畫應該彈出來自堆疊的每個整數而且在螢幕上顯示它
下一章 • 連結外部函式庫 • 本書所用的連結函式庫 • 堆疊運算 • 定義和使用程序 • 運用程序的程式設計
定義和使用程序 • 創造程序 • 程序的註解說明 • 例子: SumOf 程序 • CALL 和 RET 指令 • 巢狀程序呼叫 • Local 和 Global 標籤 • 程序參數 • 流程表象徵 • USES 運算
創造程序 • 大的問題能被區分為更小的工作使他們變成更易辦 • 一個程序是美國金屬學會同等Java 或 C++函數 • 下列各項是一個被命名的組合語言程序 • 例子: • sample PROC • . • . • ret • sample ENDP
程序的註解說明 為每個程序建議了文件: • 所有工作的描述完成的藉著程序. • 接受:一連串的輸入參數;陳述他們的用法和需求。 • 回返:被程序歸還的價值的描述. • 需要:在程序被叫做之前,需求的可選擇目錄呼叫了一定要被滿意的先決條件。 如果一個程序沒有被滿意它的先決條件被叫,它可能將不生產預期的輸出.
例子:程序的總數 • ;--------------------------------------------------------- • SumOf PROC • ; • ; Calculates and returns the sum of three 32-bit integers. • ; Receives: EAX, EBX, ECX, the three integers. May be • ; signed or unsigned. • ; Returns: EAX = sum, and the status flags (Carry, • ; Overflow, etc.) are changed. • ; Requires: nothing • ;--------------------------------------------------------- • add eax,ebx • add eax,ecx • ret • SumOf ENDP
CALL 和 RET 指令 • 呼叫指令呼叫一個程序 • 關於壓入抵銷的下個操作的堆疊 • 複印被叫做的程序位址進入 EIP • RET來自一個程序的指令回返 • 彈出堆疊的頂端進入EIP
CALL-RET 例子(1 of 2) • main PROC • 00000020 call MySub • 00000025 mov eax,ebx • . • . • main ENDP • MySub PROC • 00000040 mov eax,edx • . • . • ret • MySub ENDP 0000025 是指令的抵銷立刻跟隨呼叫指令 00000040 在 MySub 內是第一個指令的抵銷
那RET指令彈出 00000025 從堆疊到 EIP CALL-RET 例子 (2 of 2) 呼叫指令在堆疊之上壓入 00000025,而且進入 EIP 之內裝載 00000040 (以前堆積顯示RET執行)
巢狀了程序呼叫 在時間之前 Sub3 被叫做,堆疊包含所有的三個回返位址:
Local 和Global 標籤 當地標籤只在相同的程序內到陳述是看得見的.全球的標籤各處是看得見的. main PROC jmp L2 ; error L1:: ; global label exit main ENDP sub2 PROC L2: ; local label jmp L1 ; ok ret sub2 ENDP
程序參數(1 of 3) • 一個好程序可能在許多不同的計畫中是可使用的 • 但如果沒提特定的可變名字 • 因為參數價值能在運行時間改變,所以參數幫助使程序有彈性
程序參數(2 of 3) ArraySum 程序計算排列的總數。它作二個關於特定的可變名字的參考: • ArraySum PROC • mov esi,0 ; array index • mov eax,0 ; set the sum to zero • mov ecx,LENGTHOF myarray ; set number of elements • L1: add eax,myArray[esi] ; add each integer to sum • add esi,4 ; point to next integer • loop L1 ; repeat for array size • mov theSum,eax ; store the sum • ret • ArraySum ENDP 如果你想要在相同的計畫裡面計算二或三排列的總數?
程序參數(3 of 3) ArraySum 的這一個版本復原位址在 ESI 的任何 doubleword 排列的總數。總數在 EAX 被復原: • ArraySum PROC • ; Receives: ESI points to an array of doublewords, • ; ECX = number of array elements. • ; Returns: EAX = sum • ;----------------------------------------------------- • mov eax,0 ; set the sum to zero • L1: add eax,[esi] ; add each integer to sum • add esi,4 ; point to next integer • loop L1 ; repeat for array size • ret • ArraySum ENDP
流程表符號 • 下列的符號是流程表的基本方塊: (包括在書的第 166 頁上不被列出的二個符號.)
你輪到的. . . 畫一個表達下列的pseudocode的流程表 input exam grade from the user if( grade > 70 ) display "Pass" else display "Fail" endif
你輪到的. . . • 在先前的幻燈片中修正流程表讓使用者繼續輸入考試得分直到 -1 的價值被進入