(完整)32位匯編語言程序設計17稿b_第1頁
(完整)32位匯編語言程序設計17稿b_第2頁
(完整)32位匯編語言程序設計17稿b_第3頁
(完整)32位匯編語言程序設計17稿b_第4頁
(完整)32位匯編語言程序設計17稿b_第5頁
已閱讀5頁,還剩799頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、32位匯編語言程序設計計算機科學與信息工程學院 趙建州7/22/20221前 言32位匯編語言程序設計是計算機軟件課程。也是計算機專業(yè)學生的必修課程,與其他程序設計語言相比,匯編語言對機器的硬件層封裝最少,在操作系統(tǒng)的控制下允許程序員最大限度地直接訪問計算機硬件。匯編語言從語言的角度逼真地描述了微處理器的體系結構,從軟件角度描述了計算機系統(tǒng)硬件層的運行規(guī)則。不同的CPU體系有不同的匯編語言。本課介紹的是Intel 80X86CPU系列的32位匯編語言。 7/22/20222在學習計算機專業(yè)其他課程時,會遇到一些該課程不能解答的問題:常數(shù)為什么不能修改,數(shù)據(jù)為什么要有數(shù)據(jù)類型,指針為什么也要有數(shù)

2、據(jù)類型,為什么C/C+語言中數(shù)組的下標從0 開始,為什么不能用值傳遞參數(shù)或自動局部變量從函數(shù)帶回信息,函數(shù)的形參變量和自動局部變量放在內存的哪一部分,它們?yōu)槭裁磿S著函數(shù)的結束而消失, C/C+語言中為什么要區(qū)分整數(shù)運算和浮點數(shù)運算等等,通過學習32位匯編語言程序設計,會幫助你理解許多其他課程留下的問題。7/22/20223 第一章 匯編語言單詞 第二章 CPU映像和機器數(shù) 第三章 內存數(shù)據(jù)映像 第四章 操作數(shù)尋址方式第五章輸入輸出函數(shù) 第六章 整型運算 第七章 整型控制結構結束放映7/22/20224 第八章 浮點型運算 第九章 指針和字符串 第十章 數(shù)組和串第十二章 過程 結束放映7/22

3、/20225第一章 匯編語言單詞1.1 匯編語言字符集和單詞1.2 注釋符1.3 專用符號1.4 保留字1.5 標識符1.6 匯編語言程序格式7/22/202261.1 匯編語言字符集和單詞匯編語言采用ASCII碼字符作為自己語言的字符集。 匯編語言的單詞由一個或多個ASCII碼字符組成,它們對于匯編程序有預定的語法意義。匯編語言的單詞包括注釋符、專用符號、保留字、標識符等。7/22/202271.2 注釋符 匯編語言的注釋符分單行注釋符和跨行注釋符。單行釋符 / 可以放在程序某行中任何位置,編譯程序忽略從 / 開始到行尾的所有內容。 跨行注釋符 /* */ 編譯程序忽略從 /* 開始到 */

4、 之間的所有內容。7/22/20228例1:注釋的用法 (1)跨行注釋符 /* 下面的程序段對數(shù)組 實施快速排序算法 */ mov ( 365 , ecx); /* 給計數(shù)器賦初值 */ (2)單行注釋符 mov ( 365 , ecx); / 給計數(shù)器賦初值7/22/202291.3 專用符號專用符號主要包括匯編語言的運算符、分隔符、數(shù)制標識符。專用符號有一個字符的也有兩個字符的。下面是一個字符的專用符號。 * / + - ( ) : ; , . = & | ! $ % 下面是兩個字符的專用符號。 & | = != = := . 7/22/202210例2:專用符號舉例 mov( &data

5、 , eax ); stdout.put( 32位匯編語言, nl ); stdout.put(pi=,pi:10:3, nl ); stdout.put( $6f, nl ); stdout.put( % 10101010, nl ); 7/22/2022111.4 保留字 保留字也稱關鍵字,保留字包括 CPU中的寄存器名,匯編語言的指令助記符,語句,數(shù)據(jù)類型名稱等。匯編語言的保留字不區(qū)分大小寫。7/22/202212 CPU中的寄存器名AL AH AX EAX BL BH BX EBX CL CH CX ECX DL DH DX EDX SI ESIDI EDIBP EBPSP ESPST

6、0 ST1 ST2 ST3 ST4 ST5 ST6 ST77/22/202213 指令助記符和語句ADD INC ADCSUB DEC CMP NEG SBBMUL IMUL INTMUL DIV IDIV MOD IMODIF ELSE ENDIFWHILE ENDWHILE FOR ENDFORFOREVER ENDFOR REPEAT UNTIL 7/22/202214 數(shù)據(jù)類型名稱int8 int16 int32uns8 uns16 uns32real32 real64 real80byte word dword qword lword char string cset array b

7、oolean7/22/202215 其他符號 program begin end procedure type val static var readonly const 如果想了解匯編語言專用符號和保留字的更多的相關信息,請參考HLA手冊。 7/22/2022161.5 標識符標識符可用作程序名、變量名、常量名、函數(shù)名、過程名、標號等。匯編語言的標識符必須以字母或下劃線開始,后面可跟字母、數(shù)字、下劃線。由于受MASM的限制,標識符的長度不能超過236個ASCII字符。匯編語言的標識符區(qū)分大小寫字母。 標識符不能與保留字同名。7/22/202217 例3:合法的標識符和非法的標識符(1)合法的

8、標識符 addtion big first last a1 s1 small Small(2)非法的標識符 %a1 5s AL s17/22/2022181.6 匯編語言程序格式 program 程序名; begin 程序名; / 代碼段 end 程序名;7/22/202219 程序中的program,begin,end 是匯編語言的保留字。程序名要按標識符取名。聲明段用來聲明各種變量、常量為它們賦予初值;還用來聲明過程。begin和end之間是代碼段。 匯編語言提供了輸入輸出標準庫,為了使用輸入輸出標準庫,必須在程序開始用包含語句把標準庫的頭文件stdlib.hhf包含到程序中來。 7/22

9、/202220例3:顯示“匯編語言編程開始了!” 的匯編語言程序program HelloWorld;#include( stdlib.hhf ) / 包含標準庫頭文件begin HelloWorld;stdout.put( 匯編語言編程開始了!, nl );stdout.put( “擊回車鍵退出 );stdin.readLn();end HelloWorld;7/22/2022217/22/2022227/22/2022237/22/202224如果用C+編寫同樣的程序,編寫的代碼如下:#include stdafx.h#include stdio.hint main(int argc, c

10、har* argv)printf(匯編語言編程開始了!n);return 0;7/22/202225#include stdafx.h#include iostreamusing namespace std;int main(int argc, char* argv)cout匯編語言編程開始了!endl;return 0;7/22/202226匯編語言程序具有占用空間小,運行效率高的優(yōu)點,與這個匯編語言程序相似的C/C+程序經編譯后產生的執(zhí)行代碼約有152KB,而匯編語言編譯的結果不到8K,匯編語言程序常用于嵌入系統(tǒng),控制系統(tǒng)編程,也用于編寫設備驅動程序,而設計圖形界面不是匯編語言的特長,每種

11、程序語言都各有擅長,在應用中注意要揚長避短。7/22/202227第二章 機器數(shù)和CPU映像2.1 整數(shù)機器數(shù)編碼2.2 機器整數(shù)的加減法運算及溢出問題2.3 字符機器數(shù)編碼2.4 Intel 80 x86 CPU映像7/22/2022282.1整數(shù)機器數(shù)編碼 匯編語言語法把二進制整數(shù)分為兩種,無符號和有符號整數(shù)。無符號整數(shù)是指數(shù)據(jù)的每一位都代表數(shù)值。在匯編語言程序設計里,內存地址(指針),循環(huán)次數(shù),ASCII 碼等都是無符號整數(shù)。數(shù)學運算中整數(shù)值有正數(shù)和負數(shù)之分,在計算機元件級怎樣表示正號和負號?答案是只能用數(shù)字表示正號和負號。因此必須進行符號和數(shù)值混合編碼。 7/22/202229 (一)

12、原碼表示法 如果正數(shù)的符號用0 表示,負數(shù)的符號用1 表示,絕對值用二進制數(shù)表示,這就是原碼表示法。假設計算機字長是n 位,能表示n-1位有符號整數(shù),設X=Xn-2Xn-3X0,原碼表示是: 0Xn-2Xn-3X0 X 0X源碼= 1Xn-2Xn-3X0 X 07/22/202230例1:設n=8,求二進制數(shù)10010, -10010的原碼。二進制數(shù) 10010的原碼是00010010,在此最高位的0代表 + 號。二進制數(shù)-10010的原碼是10010010,在此最高位的1代表 號。根據(jù)定義, 0 在原碼中有兩種表示,所以計算機內整數(shù)不采用原碼表示法。7/22/202231 (二)補碼表示法

13、n位二進制補碼的定義是: X 0 X2n-1-1X補碼= 2n+X -2n-1X0X是n-1位二進制整數(shù)7/22/202232二進制數(shù)轉換為補碼二進制正數(shù)轉換成補碼與原碼相同。二進制負數(shù)轉換成補碼有兩種方法:方法1:根據(jù)定義求補碼例2:n=8,求( -1010111) 2和-119的補碼。-1010111補碼 = 28-1010111 =100000000-1010111 =10101001 -119補碼 = 28-1110111 =100000000-1110111 =10001001 100000000 1010111 10101001 100000000 1110111 10001001

14、7/22/202233 方法2:寫出負數(shù)的絕對值,求絕對值的補碼,然后對每位取反(包括符號位),末位加1。例3:n=8,求(- 1010111)2和-119的補碼。 計算(- 1010111)2 的補碼1 求負數(shù)絕對值 10101112 求補碼 01010111 / n位補碼 3 取反碼 101010004 加1 101010017/22/202234 計算 - 119 的補碼1. 十進制換成二進制 - 11101112求負數(shù)絕對值 11101113求補碼 011101114取反碼 100010005末位加1 100010017/22/2022350在補碼中只有一種表示法。整數(shù)數(shù)值在計算機元件

15、級用二進制補碼表示。注意補碼表示是非對稱性的。8位補碼表示有符號數(shù)的范圍是-128127,16位補碼表示有符號數(shù)的范圍是-3276832767 。我們將補碼逐位取反,再加1的運算稱為求補運算。正數(shù)的補碼經過求補運算結果是它相反數(shù)的補碼;負數(shù)的補碼經過求補運算結果也是它相反數(shù)的補碼。 7/22/202236從機器數(shù)計算它的真值對于正數(shù),直接用權的多項式展開求和。例:已知n=8位,求01001010的真值用權的多項式展開求和:原式=26+23+21=74對于負數(shù),有兩種方法,每種方法有多個計算步驟。7/22/202237方法一:根據(jù)補碼的定義X補碼 = 2n+X- X = 2n - X補碼 注意X

16、本身是負數(shù)。方法二:對負數(shù)的補碼求補,得到它的絕對值,計算絕對值的權的多項式的和,然后對和實施取負運算。7/22/202238我們看同一個整數(shù)補碼用不同位數(shù)表示時有何差別。例4:求117,-117的8位和16位的補碼。 117 的補碼n = 8 01110101n = 16 0000000001110101 -117 的補碼n = 8 10001011n = 16 1111111110001011從例子中得出:一個8位補碼數(shù)要變成16位補碼數(shù)時,只需用它的符號位的值填滿高8位。這個操作稱為符號擴展。7/22/202239因為在計算機元件級無法區(qū)分一個二進制數(shù)是有符號的還是無符號的。所以在機器內

17、一個二進制數(shù)可代表有符號數(shù),也可代表無符號數(shù)。例如:假定n=8位,機器內有個整數(shù) %10001010,它可以代表無符號數(shù)138;也可以代表有符號數(shù)-118。匯編語言程序員對程序中的整數(shù)哪些是無符號的,哪些是有符號的必須一清二楚。7/22/2022402.2 機器整數(shù)加減法運算及溢出問題(一)零擴展和符號擴展計算機內整數(shù)的加法和減法運算要求參加運算數(shù)據(jù)的長度要相同。如果參加運算的數(shù)據(jù)長度不同時,在運算之前要把位數(shù)短的擴展為長的,否則運算結果可能是錯誤的。對于無符號的數(shù),高位部分全部用0填滿(零擴展);對于有符號的數(shù),高位部分全部用符號值填滿(符號擴展)。加減運算時符號值與數(shù)值一樣參加運算。7/2

18、2/202241例5:計算兩個無符號數(shù)加法 1010 + 01100000分析:無符號數(shù)位數(shù)不同時,位數(shù)短的必須進行零擴展,即高4位必須填滿0。 1左加數(shù)零擴展 000010102加右加數(shù) 011000003運算結果 011010107/22/202242例6:計算兩個有符號數(shù)的加法 00001000 + 1100 即(8+(-4)分析:有符號數(shù)位數(shù)不同時,必須進行符號擴展。因為右加數(shù)最高位是1,代表負號,把它變成8位時,高4位必須填滿符號值1。1左加數(shù)不變 000010002右加數(shù)符號擴展 111111003運算結果 100000100因為數(shù)據(jù)位指定為8位,進位丟失,和等于00000100即

19、4,結果正確。7/22/202243如果不進行符號擴展,計算兩個有符號數(shù)加法 00001000+11001左加數(shù)不變 000010002右加數(shù)不符號擴展 11003運算的結果 00010100結果等于20,顯然是錯誤的。7/22/202244(二)整數(shù)加減運算可能出現(xiàn)的溢出問題在計算機內運算與人類運算最大的不同之一是計算機只能用有限位數(shù)表示數(shù)值。如果運算結果超出了有限位數(shù),稱為溢出。溢出是一種錯誤,運算到此只能中斷,要程序員修改程序后,重新編譯,再執(zhí)行。7/22/202245無符號數(shù)加減運算和有符號數(shù)加減運算都有可能發(fā)生溢出。對于無符號數(shù)的加法,運算中最高位如產生進位;對于無符號數(shù)減法,運算中

20、最高位如產生了借位,這都是溢出。7/22/202246例7:n=8,計算 130+145 1130的機內表示 100000102145的機內表示 100010013運算的結果 100001011 運算中最高位產生進位,由于機器內數(shù)據(jù)規(guī)定是8 位,進位丟失,這就是溢出,結果是錯誤的。7/22/202247例8:n=8,計算 130-145 1130的機內表示 100000102145的機內表示 100010013運算的結果 11111001 運算中最高位產生借位,由于機器內數(shù)據(jù)規(guī)定是 8 位,借位丟失,這也是溢出,結果是錯誤的。 7/22/202248根據(jù)補碼定義和數(shù)學公理,有符號數(shù)加減法溢出可

21、能發(fā)生在兩個同號數(shù)相加或兩個異號數(shù)相減的時候。如果兩個同號數(shù)相加,結果的符號與加數(shù)的符號相反;兩個異號數(shù)相減,結果的符號與減數(shù)的符號相同時,這就是溢出。因為,兩個正數(shù)相加結果絕對不可能是負數(shù);同樣一個負數(shù)減正數(shù),結果絕對不可能是正數(shù)等等7/22/202249例9:n=8, 計算 72+98 172的機內表示 01001000298的機內表示 011000103運算的結果 10101010結果不是正數(shù),而是負數(shù)-86。顯而易見結果是錯誤的。7/22/202250例10:n=8, 計算 -83 +(-80)1-83的機內表示 101011012-80的機內表示 101100003運算結果 1010

22、11101由于機器是8位,結果的最高位丟失,結果變成正數(shù)93,是錯誤的。7/22/202251例11:n=8, 計算72-(-98) 1 72的機內表示 010010002- 98的機內表示 100111103 運算的結果 10101010結果與減數(shù)符號相同,正數(shù)減負數(shù)結果是負數(shù)。它的值是-86。結果是錯誤的。7/22/202252例12:n=8, 計算-83 80 1-83的機內表示 101011012 80的機內表示 010100003運算的結果 01011101結果與減數(shù)符號相同,負數(shù)減正數(shù)結果是正數(shù)。它的值是93。結果是錯誤的。 7/22/2022532.3 字符型機器數(shù)編碼在計算機內

23、,字符也必須用二進制數(shù)編碼表示。最通用的字符是 ASCII 碼字符,它是美國標準信息交換碼。它用二進制代碼規(guī)定了英文字母、阿拉伯數(shù)字、算術運算符、英文標點符號和其他常用符號以及控制符號的表示,ASCII 碼包括了 128 個字符,具體內容見本書附錄1。7/22/202254中國在1980年發(fā)表GB2312-80信息交換碼標準,這一標準后來被國際標準化組織接納為國際標準,它是個雙字節(jié)編碼標準,一個漢字用兩個字節(jié)表示,每個字節(jié)只用了低七位,每個字節(jié)的最高位值是0。因為ASCII碼字符用一個字節(jié)的低七位表示,最高位的值也是0,而且它已經是機器數(shù)編碼了,所以為了在機器里區(qū)分漢字和ASCII碼,在機器里

24、把漢字的GB2312碼的每個字節(jié)的最高位的值規(guī)定為1后作為漢字的機器碼。7/22/202255例13:輸出漢字的機器碼例如漢字“水”,它的機器碼值是$AE_CB,要把機器碼變成GB2312-80碼,用機器碼減$80_80即可,“水”字的GB2312碼值是$2E_4B。7/22/2022562.4 Intel 80 x86映像Intel 80 x86 CPU 系列屬于Von Neumann結構的機器,Von Neumann 計算機體系結構包括三個主要部分:中央處理單元(CPU),存儲器,輸入/輸出設備(I/O)。這三部分由系統(tǒng)總線連在一起,見圖2.1。系統(tǒng)總線包括控制總線、數(shù)據(jù)總線、地址總線。7

25、/22/202257中央處理機 CPU總線控制 邏輯接 口接 口內 存 大容量外存儲器I/O設備I/O子系統(tǒng)系統(tǒng)總線.圖 2.1 計算機硬件結構 7/22/202258從80486開始,Intel 把浮點運算協(xié)處理器集成到CPU內,在CPU內稱它為浮點運算單元(FPU),現(xiàn)暫不介紹浮點運算單元。CPU內部最顯著的部件是寄存器。Intel CPU寄存器可分為四類:段寄存器,內核模式專用寄存器,通用寄存器,應用程序可訪問的專用寄存器。7/22/202259 段寄存器組包括CS、DS、SS、ES、FS、GS等6個16位寄存器。CS是代碼段寄存器,SS是堆棧段寄存器,其余的是數(shù)據(jù)段寄存器。 內核模式專

26、用寄存器供系統(tǒng)編程使用,這里不做介紹。 7/22/202260 圖2.2 80 x86通用寄存器7/22/202261通用寄存器組包括EAX, EBX, ECX, EDX, ESI, EDI, EBP 和ESP 8個32位寄存器(圖3.2)。每個名字開頭字母 “E” 代表擴展(extended)。這個前綴用來區(qū)分8個32位寄存器和以下 8 個 16 位寄存器:AX, BX, CX, DX, SI, DI, BP和SP AX, BX, CX, DX 又可分成8 個8位寄存器:AL, AH, BL, BH, CL, CH, DL和DH Intel CPUs的這些寄存器不都是獨立的寄存器, 當修改一

27、個寄存器時則至少同時修改了另一個寄存器。7/22/202262 應用程序可訪問的專用寄存器(1)標志寄存器Eflag 它是32 位寄存器。Bit 0 CF 最高位有進位或借位時置1Bit 2 PF 低8位有偶數(shù)個1時置1Bit 4 AF D3位有進位或借位時置1Bit 6 ZF 運算結果是零時置1 31 . 22 13 12 11 10 9 8 7 6 5 4 3 2 1 0CFPFAFZFSFTFIFDFOFIOPL保留7/22/202263Bit 7 SF 運算結果最高位是1時置1Bit 8 TF 如置1每執(zhí)行一條指令發(fā)生中斷Bit 9 IF 如置1允許響應可屏蔽中斷Bit 10 DF 請

28、參考第十一章Bit 11 OF 指令執(zhí)行后發(fā)生溢出時置17/22/202264 很多指令執(zhí)行后會影響條件標志,尤其在進行加減運算時,CPU并不知操作數(shù)是有符號還是無符號數(shù),它只是按照運算結果設置條件標志,需要程序員自己來判斷運算結果是否正確。7/22/202265例14:計算 01001011+00111000 左加數(shù) 01001011 右加數(shù) 00111000 相加結果 10000011運算結果使AF=1,OF=1,SF=1,ZF=0,CF=0,PF=0。如果這兩個數(shù)是無符號數(shù),運算結果是正確的,因為沒發(fā)生溢出(CF=0);如果這兩個數(shù)是有符號數(shù),運算結果是錯誤的,因為發(fā)生了溢出(OF =

29、1)。這要由程序員自己判斷。計算機硬件不保證運算結果是否正確,只負責按結果設標志。7/22/202266(2)指令計數(shù)器EIP指令計數(shù)器EIP是32位寄存器,它存放著下一條要執(zhí)行的機器指令的偏移地址。程序裝入內存時,由操作系統(tǒng)負責把第一條指令的偏移地址裝入EIP,CPU每取一條指令就自動修改EIP,將它的值變成下一條指令的偏移地址。由于EIP起著直接保證程序正確執(zhí)行的關鍵作用,在80 x86指令集中看不見EIP7/22/202267偏移地址是為了方便計算機內存系統(tǒng)管理而引入的一個邏輯地址概念,因為程序員在編程時,無法知道將來程序運行時放在內存的哪個位置,所以讓編譯程序在編譯源程序時,以字節(jié)為單

30、位按順序給每條指令、每個數(shù)據(jù)賦予一個邏輯地址,并且每個段都從零開始編址,這個邏輯地址就稱作偏移地址。在程序執(zhí)行中,由內存管理機構將邏輯地址映射到真正的物理地址。這部分內容將在尋址方式一章中介紹。指令B指令A代碼段047/22/202268(3)堆棧指針寄存器ESP32位寄存器ESP它只用來作為堆棧棧頂指針。它是棧頂?shù)钠频刂贰6褩2僮髦噶疃家运闹翟L問堆棧。(4)堆棧指針、數(shù)據(jù)寄存器EBP32位EBP寄存器除了可用作數(shù)據(jù)寄存器外,還可用作訪問堆棧的指針寄存器,也是具有特殊用途的寄存器。 7/22/202269 堆棧段棧頂指針 ESP基址指針EBP016k7/22/202270第三章 內存數(shù)據(jù)映

31、像3.1 基本數(shù)據(jù)類型3.2 常量3.3 變量3.4 程序分段7/22/2022713.1 基本數(shù)據(jù)類型 匯編語言基本數(shù)據(jù)類型uns8 無符號的8位整數(shù)uns16 無符號的16位整數(shù)uns32 無符號的32位整數(shù)int8 有符號的8位整數(shù)int16 有符號的16位整數(shù)int32 有符號的32位整數(shù)boolean 布爾型,占一個字節(jié)char 字符類型,占一個字節(jié)7/22/202272real32 32位浮點數(shù)real64 64位浮點數(shù)real80 80位浮點數(shù)byte 通用的8位類型tbyte 通用的80位類型word 通用的16位類型dword 通用的32位類型qword 通用的64位類型lw

32、ord 通用的128位類型7/22/202273 匯編語言復合數(shù)據(jù)類型 string 字符串(字符串變量實際是4個字節(jié)長的指針)text 與字符串相似,文本常數(shù)常用于指令中,減小輸入擊鍵次數(shù)7/22/2022743.2 常量3.2.1 數(shù)值常數(shù)和布爾型常數(shù)3.2.2 字符串和字符常量3.2.3 符號常量3.2.4 常量表達式7/22/202275常量是編譯程序時,已經有確定的值,在程序運行中這個值不能改變。每個常量具有數(shù)據(jù)類型,常量的類型可以用HLA的任何一種類型。注意語法認為常量的數(shù)據(jù)類型是不明確的。 7/22/2022763.2.1 數(shù)值常數(shù)和布爾型常數(shù) 十進制整數(shù)進位計數(shù)制是常用的計數(shù)方

33、法。人們習慣使用十進制,每位的數(shù)字可以是0到9中的任何一個,它的基數(shù)是十,計數(shù)時逢十進一。這也是十進制的名稱由來。7/22/202277在程序里可以用十進制整數(shù)。例1:123, 32_123, 0, -23高級匯編語言允許數(shù)值中用下劃線作為分隔符,便于人們閱讀。從語法上講,數(shù)值前可有正號或負號,數(shù)值中允許有下劃線,從語法上講,下劃線的位置可以在任意兩個數(shù)字之間,在實際應用中將下劃線作為千分號,使人們閱讀方便。 7/22/202278二進制整數(shù) 在數(shù)字電子計算機內,每位數(shù)字要用一個電子元件(如晶體管)的一個物理狀態(tài)來表示,通常一個電子元件存在兩種穩(wěn)定的狀態(tài)(如晶體管的飽和與截止),而一位二進制也

34、存在兩種狀態(tài)0和1。一個電子元件恰好可以表示一位二進制,所以在數(shù)字電子計算機內使用二進制。一個數(shù)值無論用二進制還是十進制表示,其本質是代表一個值。 7/22/202279在程序里可以用二進制整數(shù)。高級匯編語言要求以 % 前綴開始,不能帶符號。例2:%1101_0001高級匯編語言允許在數(shù)值中用下劃線作為分隔符,便于人們閱讀。 7/22/202280n位m進制可以表示mn種狀態(tài)。如三位二進制可以表示23種狀態(tài): %000 %001 %010 %011 %100 %101 %110 %1117/22/202281十六進制整數(shù)用二進制表示數(shù)字對程序員來講閱讀和書寫都不方便,為了方便閱讀和書寫程序,在

35、匯編語言源程序里還可以用十六進制表示數(shù)值。匯編語言要求以 $ 前綴開始,不能帶符號。例3:$123, $12_1ae6高級匯編語言允許在數(shù)值中用下劃線作為分隔符,便于人們閱讀。7/22/202282在匯編語言源程序里程序員可以用上面三種數(shù)制中的任何一種表示自己的數(shù)據(jù),其實機器只識別二進制,源程序中用非二進制表示的數(shù)由匯編程序或編譯程序轉換成二進制數(shù)。7/22/202283(4) 實型常數(shù) HLA的浮點類型常數(shù)表示如下:(1)一個“+” 或 “-”表示尾數(shù)的符號。如沒有 符號,HLA默認它是正數(shù)。(2)跟隨一位或多位十進制數(shù)。(必選項)(3)跟隨小數(shù)點和一位或多位十進制數(shù)(可 選項)。(4)跟隨

36、一個“e”或“E”,其后是符號(“+”或 -)和一位或多位十進制數(shù)。7/22/202284必須有小數(shù)點或”e”/“E”來區(qū)分浮點數(shù)和整數(shù)注意浮點常量不能以小數(shù)點開始,在程序里不能用“.1”表示“0.1” 。 例4:合法的浮點常量 1.234, 3.75e2, -1.0, 1.1e-1 , 0.1, -123.456e+789, +25e0, 1e+4, 1_234_837.25, 1_000.00,789_934.99 9_999.99 7/22/202285布爾常數(shù) HLA預定義兩個布爾型常數(shù),true 和false在內部,HLA定義true 和false值分別是1和0。HLA默認為每個布爾

37、型常量分配一個字節(jié)。實際上布爾操作只看布爾值的#0位而把其他位清零。你不能像在C/C+語言中在用布爾表達式的地方用整型表達式。7/22/2022863.2.2 字符串和字符常量 (1)字符串常量 字符串常量是用雙引號括住的零個或多個字符。例5: 32位匯編語言 a 123性質1:HLA自動將程序中相鄰的字符串聯(lián)接起來。性質2:在字符串常量中插入兩個雙引號來代表一個 雙引號。7/22/202287(2)字符常量格式1:用兩個單引號括住的一個ASCII碼字 符。格式2:#整數(shù)常數(shù)。 整數(shù)常數(shù)可以用十進制、十六進制或二進制,代表字符的ASCII碼值。數(shù)值在0到255的范圍內,但只顯示32到127范圍

38、內的字符。如果指定的數(shù)值超過0到255的范圍,系統(tǒng)在編譯時會報錯。系統(tǒng)默認為每個字符常量分配一個字節(jié)。7/22/202288性質1:在兩個單引號中放兩個單引號代表一個單引號。性質2:HLA可以聯(lián)接任何相鄰的字符常量和字符串常量組成一個字符串常量在程序中,語法認為字符常量的數(shù)據(jù)類型是不明確的。7/22/202289例7: 2 ,a ,#13,#$d,#%1101上面第三個字符表示一個單引號,后面的三個字符都代表回車 。記住在程序中“a” 和 a是不相同的。7/22/2022903.2.3 符號常量 在HLA的CONST段聲明符號常量。該段中聲明的常量的值從編譯到運行都不會改變;該段位于程序中的聲

39、明段位置。它以CONST保留字開始。 CONST 標識符 :數(shù)據(jù)類型 := 常數(shù)表達式; 標識符 := 常數(shù)表達式; 第二種格式是省略數(shù)據(jù)類型的語法格式,此時系統(tǒng)自動賦予默認數(shù)據(jù)類型。HLA按數(shù)據(jù)類型為符號常量分配內存空間。 7/22/202291 在CONST段聲明常量時,必須對其初始化。 := 在語法里是賦值號且只能用于數(shù)據(jù)定義的場合。在程序運行中,不允許對CONST段中的對象進行修改。在CONST段中聲明字符串常量可以省略數(shù)據(jù)類型,但文本常量不能省略數(shù)據(jù)類型。 雖然,聲明符號常量時,設置了數(shù)據(jù)類型,這里數(shù)據(jù)類型僅僅是為給常量分配內存單元而設置的,在指令中,語法仍然認為符號常量的數(shù)據(jù)類型是

40、不明確的7/22/202292例9:帶數(shù)據(jù)類型的常量聲明。const pi: real32 := 3.14159; Max:uns32 := 15; des:char := /; Mask:byte := $F0; Active: Boolean := true; 例10:不帶數(shù)據(jù)類型的常量聲明。const pi:= 3.14159; / 默認類型是 real80 Max:= 15; / 默認類型是uns32 Des:= /; / 默認類型是char Active:= true; / 默認類型是boolean 7/22/2022933.2.4 常量表達式 常數(shù)表達式的形式與高級語言的相似,他們

41、包括字符、數(shù)字常量和前面已聲明過的符號常量,各種運算符。常量表達式在語法上仍是常量。 7/22/202294 - (一元運算符) 對“-”后的表達式取負 * 乘法 div 整數(shù)除法 整數(shù)除以整數(shù),取商的整數(shù) mod 求余 整數(shù)除以整數(shù),取余數(shù) / 除法 結果是浮點數(shù) + 加法 - 減法 7/22/202295 例13:對于常數(shù)表達式,匯編語言在編譯程序時計算出值。const x:= 10; y:= 6; Sum:= x + y; / 常量表達式HLA在編譯時直接翻譯常量表達式的值。它不為計算常量表達式“x+y”編譯出機器指令,它直接計算這兩個常數(shù)值的和。從此,在本程序里匯編語言把16和常數(shù)Su

42、m聯(lián)系起來。 7/22/2022963.3 變量3.3.1 有符號整型變量3.3.2 無符號整型變量3.3.3 實型變量3.3.4 布爾型變量3.3.5 字符型變量7/22/202297變量要先定義,后使用。程序員要按照變量的性質,在相應的段中定義變量。 定義變量的語法: 變量名:數(shù)據(jù)類型; 變量名:數(shù)據(jù)類型 := 常量表達式;變量名按標識符取名。數(shù)據(jù)類型可以是HLA的任何一種數(shù)據(jù)類型。:= 在語法里是賦值號且只能用于數(shù)據(jù)定義的場合。常量的類型必須與指定的數(shù)據(jù)類型一致。 7/22/2022983.3.1 有符號整型變量 匯編語言常用的三種長度的有符號的十進制整數(shù)類型分別是:int8, int1

43、6,int32。分別對應長度為一個字節(jié)、兩個字節(jié)和四個字節(jié)的有符號整數(shù)。HLA 按照數(shù)據(jù)類型為每個有符號整數(shù)變量分配內存空間。 例15:i8:int8;i16:int16;i32:int32;7/22/202299在聲明變量時,可以賦給變量一個初始值,在程序裝入內存時由操作系統(tǒng)賦予變量。例16:i8:int8 :=8;i16:int16 :=1600;i32:int32 :=-320000; 在賦值號(“:=”)后邊必須是常數(shù)表達式。不能用另一個變量給變量賦值。7/22/20221003.3.2 無符號整型變量 HLA常用的三種長度的無符號十進制整數(shù)類型分別是:uns8,uns16,uns32

44、。分別對應一個字節(jié)、兩個字節(jié)和四個字節(jié)的無符號整數(shù)。HLA按照數(shù)據(jù)類型為每個無符號整數(shù)變量分配內存空間。 例17:聲明無符號整數(shù)變量u8:uns8; u16:uns16; u32:uns32; 7/22/2022101例18:聲明變量時賦初值 u8:uns8:=255; u16:uns16:=6500; u32:uns32:=5900;7/22/20221023.3.3 實型變量 HLA只有三種長度的浮點類型: real32 (4個字節(jié)) 代表單精度浮點數(shù), real64(8個字節(jié)) 代表雙精度浮點數(shù), real80(10個字節(jié))代表擴展精度浮點數(shù)。 匯編語言根據(jù)數(shù)據(jù)類型為每個浮點型變量分配內

45、存空間。系統(tǒng)把浮點類型數(shù)值一律當做有符號的數(shù)值。7/22/2022103例19:定義浮點型變量f32a1: real32; f32a2: real32 := 2.7; pi: real32 := 3.14159; f64b1: real64; f64b2: real64 := 1.23456789e+10; f80c1: real80; f80c2: real80 := -1.0e-104; 7/22/20221043.3.4 布爾型變量HLA匯編語言程序中可以使用布爾型常量和變量,用布爾型變量或常量組成布爾型表達式,一個布爾型變量是最簡單的布爾型表達式。例20:a:boolean; b:bo

46、olean := false; c:boolean := true; 每個布爾型變量占一個字節(jié)。你能聲明未初始化的變量也能聲明初始化的變量。 7/22/20221053.3.5 字符型變量你能用char 數(shù)據(jù)類型聲明占一個字節(jié)的ASCII字符變量。例21:字符變量的定義c: char; d: char := A; 7/22/20221063.4 程序分段3.4.1 代碼段3.4.2 靜態(tài)數(shù)據(jù)段3.4.4 堆棧段3.4.5 自動變量段3.4.6 類型段(略)3.4.7 符號常量段(略)3.4.8 在程序中聲明段的組織形式(略)3.4.9 數(shù)據(jù)在內存中存放格式7/22/20221073.4.1代碼

47、段匯編語言程序從begin 開始到end 之間的所有指令和數(shù)據(jù)組成代碼段,代碼段是一個程序的執(zhí)行規(guī)則,它用指令描述了程序的功能,在代碼段里放的是指令及指令中攜帶的數(shù)據(jù)根據(jù)計算機工作原理,CPU從內存取來第一條指令,執(zhí)行,然后取下一條指令,再執(zhí)行直到執(zhí)行完最后一條指令,程序結束。為了實現(xiàn)程序運行,CPU必須知道指令在哪里,為了幫助CPU找到指令,人們做出了這樣設7/22/2022108計,在CPU中設置一個指令計數(shù)器EIP,用它放下條指令的偏移地址,再用一個寄存器保存段起始地址的索引,這是硬件必須提供的支持,在80X86中代碼段起始地址的索引由操作系統(tǒng)在裝入程序時放入CS 中。段寄存器CS中的索

48、引值指向代碼段描述符,代碼段描述符中包括了段的32位起始地址(段基址)、段的長度、段的屬性等內容。7/22/2022109用指令計數(shù)器EIP存放下一條指令在代碼段中的偏移地址,指令的內存地址(線性地址)是: 線性地址 = 段基址(32位) + 偏移地址(32位) 在Windows控制下,線性地址通過頁表換算出物理地址。在32位匯編語言程序中很難看到段寄存器,因為它們被操作系統(tǒng)封裝起來了。任何一個段的起始地址是該段的最小地址,所以偏移地址必須是正數(shù)。每取一條指令,EIP自動修改,指向下條指令的地址。7/22/2022110012315CS寄存器索引字0TIRPL7/22/2022111偏移地址是

49、為了方便計算機內存系統(tǒng)管理而引入的一個邏輯地址概念,因為程序員在編程時,無法知道將來程序運行時放在內存的哪個位置,所以讓編譯程序在編譯源程序時,以字節(jié)為單位按順序給每條指令、每個數(shù)據(jù)賦予一個邏輯地址,并且每個段都從零開始編址,這個邏輯地址就稱作偏移地址。在程序執(zhí)行中,由內存管理機構將邏輯地址映射到真正的物理地址。指令B指令A代碼段04EIPEIP7/22/2022112 偏移地址 內 存 代碼段基址B EIPB + EIP 低地址端 高地址端7/22/20221133.4.2靜態(tài)數(shù)據(jù)段 在靜態(tài)(STATIC)內存段聲明的變量稱靜態(tài)變量,如果沒有初始化,系統(tǒng)默認用0作變量的初值。在裝入程序時給靜

50、態(tài)數(shù)據(jù)段配內存,到程序結束時,和代碼段同時撤內存。7/22/2022114 匯編語言定義了取變量偏移地址的運算,語法是: & 靜態(tài)變量運算的結果是該靜態(tài)變量的偏移地址,它的長度是32位。7/22/2022115例23:計算靜態(tài)變量的偏移地址 mov( & b , eax); 指令將變量b的偏移地址裝入寄存器EAX7/22/2022116除了定義靜態(tài)變量外,你還可使用偽操作碼byte, word, dword, uns32等,把數(shù)據(jù)插入靜態(tài)內存段。7/22/2022117例24:插入數(shù)據(jù)static b:byte := 0; / 為每個數(shù)據(jù)分配1個字節(jié)byte 1,2,3; u:uns32 :=

51、 1; / 為每個數(shù)據(jù)分配4個字節(jié)uns32 5,2,10; HLA在變量定義后,使用偽操作碼將數(shù)據(jù)寫入靜態(tài)內存段。如字節(jié)值 1、2、3嵌入變量b 字節(jié)之后。這些值沒有變量名,在學習尋址方式時,將討論怎樣訪問沒有變量名的值。插入的數(shù)據(jù)在內存怎樣存放?7/22/2022118 0 1 2 3 &b+0 &b+1 &b+2 &b+3 偏移地址 內 存 &u+12 偏移地址 內 存 &u+8 &u+0 &u+4102 51 段基址 段基址7/22/2022119為變量分配地址但不分配空間STATIC段里 變量的NOSTORAGE屬性表示在數(shù)據(jù)段給變量賦予當前的地址,但不給變量分配內存空間,所以變量與

52、段里的下一個對象共用同一個地址,語法表示如下: 變量名:類型;nostorage; 7/22/2022120例25:static x: dword; nostorage; byte a, b, c, d; 假定變量x 的地址是 1120,則數(shù)據(jù)a的地址也是1120,數(shù)據(jù)b的地址是1121,數(shù)據(jù)c的地址是1122,數(shù)據(jù)d的地址是1123。插入的數(shù)據(jù)是這樣存放的:7/22/20221211123abcd內存變量x與后面的4個數(shù)據(jù)共享內存空間。數(shù)據(jù)a的偏移地址= 1120 + 0數(shù)據(jù)b的偏移地址= 1120 + 1數(shù)據(jù)c的偏移地址= 1120 + 2數(shù)據(jù)d的偏移地址= 1120 + 31122112

53、11120 x7/22/20221223.4.4堆棧段堆棧段是用先進后出的動態(tài)數(shù)據(jù)結構維護的一個內存區(qū)。段寄存器SS中的索引值指向堆棧段描述符,描述符保存了段的起始地址(32位段基址 ),而指針寄存器ESP值是當前棧頂?shù)钠频刂贰S蒀PU的內存管理組件把棧頂?shù)倪壿嫷刂酚成錇榫€性地址。系統(tǒng)默認為你的程序建立堆棧段,為它分配16MB空間。7/22/2022123 偏移地址 內 存 堆棧段基址B 棧底 棧頂 espB + esp 低地址端 高地址端 B + 16M 初始棧頂棧頂是浮動的而棧底是固定的7/22/20221243.4.5自動變量段VAR段在堆棧段里分配內存空間。主程序里聲明的var 段與

54、static段具有同樣的生命周期。匯編語言不允許對VAR段的變量初始化。系統(tǒng)也不會對VAR段的變量初始化。7/22/2022125例27: var a:int32; c:char; 7/22/20221263.4.7 符號常量段HLA的CONST段用來聲明符號常量。CONST段中聲明的常量其值從編譯到運行都不會改變;CONST段位于程序中的聲明段位置。它以CONST保留字開始。例:const x:= 10; y:= 6; Sum:= x + y; / 常量表達式7/22/2022127例30:在CONST段聲明文本常量。const i: text := (type int32 edi); j:

55、 text := (type int32 esi); Middle: text := (type uns32 edx); mov( i, eax ); / mov(type int32 edi , eax);add( j, eax ); / add(type int32 esi , eax);shr( 1, eax ); mov( ebx+eax*4, Middle ); / 把中間值裝入EDX 7/22/2022128當HLA匯編源程序時,遇見符號文本常量時,它用那個文本替換標識符(而不是字符串常數(shù)),然后繼續(xù)編譯。這能節(jié)省鍵盤輸入時間,也使程序容易閱讀。匯編上面的源程序段時,匯編程序把源程

56、序段先翻譯成以下的樣子:mov(type int32 edi), eax ); add(type int32 esi), eax ); shr( 1, eax ); mov( ebx+eax*4, (type uns32 edx) );7/22/20221293.4.9數(shù)據(jù)在內存中存放格式 80X86系列的內存每個字節(jié)有一個地址,由于指令和數(shù)據(jù)長度少則一個字節(jié),多則多個字節(jié)。如果數(shù)據(jù)就占一個字節(jié),這個字節(jié)的地址就是數(shù)據(jù)的地址;如果一個數(shù)據(jù)或一條指令占多個字節(jié)(操作系統(tǒng)會為它分配連續(xù)的地址空間),操作系統(tǒng)就按低地址作為數(shù)據(jù)或指令的地址,并遵循低位數(shù)據(jù)(指令)裝入低地址字節(jié),高位數(shù)據(jù)(指令)裝入高

57、地址字節(jié)的規(guī)則將數(shù)據(jù)或指令裝入內存。 7/22/2022130如字節(jié)型數(shù)據(jù)值是A,字類型數(shù)據(jù)值是$1256雙字類型數(shù)據(jù)值是$106f3a6e。三個數(shù)據(jù)的地址分別是186、188、192。數(shù)據(jù)如圖存放: 低放低, 高放高。7/22/2022131例:數(shù)據(jù)在寄存器中存放格式如有數(shù)據(jù)$ 1234abcd要放在寄存器EAX中,根據(jù)規(guī)則存放的結果是: 1 2 3 4 a b c dEAXALAH7/22/2022132例:如有數(shù)據(jù)$ 1234abcd要放在地址是1200的內存單元中,根據(jù)規(guī)則存放的結果是: 1 2 3 41200 a b c d1201120212037/22/2022133第四章 尋址

58、方式匯編語言的指令按其指令格式包含的操作數(shù)的個數(shù)可以分為:無操作數(shù)、單操作數(shù)、雙操作數(shù)三種形式: 指令助記符( ); 指令助記符(源操作數(shù)/目的操作數(shù)); 指令助記符(源操作數(shù),目的操作數(shù)); 7/22/2022134操作數(shù)在指令中最多要表達三種含義:1. 表示操作數(shù)的值(數(shù)值或字符)2. 表示操作數(shù)所在的位置(內存、指令、中央處理器)3. 表示操作數(shù)的數(shù)據(jù)類型至少要表達二種含義即 1.和2.,其中2. 是匯編語言獨有的,它要明確地表示操作數(shù)在哪里,使CPU可以準確地取到操作數(shù)。7/22/2022135 指令助記符表示指令能產生的操作,常用英文的縮寫表示。如“add”代表“addition ”

59、(加法)?!皊ub ”代表“subtracting ”(減法)。 源操作數(shù)參加運算后其值不變,通常目的操作數(shù)參加運算后又用來存放運算結果。指令中的操作數(shù)必須用尋址方式表示。下面我們以操作數(shù)所處的位置分類學習操作數(shù)的尋址方式。7/22/2022136 4.1 寄存器尋址方式 4.2 立即尋址方式 4.3 保護模式的內存尋址方式 4.4 數(shù)據(jù)類型限制7/22/20221374.1 寄存器尋址方式 操作數(shù)格式: 寄存器名 寄存器名是任何一個通用寄存器的名字。寄存器的內容就是指令需要的操作數(shù)。7/22/2022138例1:mov( EBX, EAX ); / 將源操作數(shù) ebx 值復制給目的操作數(shù) e

60、ax 2F67 2F67 547A 547A EBX EAX7/22/2022139 inc( ecx); 13AF 26446679ABCD13AF 2645執(zhí)行前的ECX執(zhí)行后的ECX 13AF2644 + 17/22/20221404.2 立即尋址方式操作數(shù)格式: 常數(shù)或常數(shù)表達式 常數(shù)值就是指令的操作數(shù)的值,它包含在指令中,當從內存取來這樣的指令,指令中就包括了操作數(shù)。 在所有尋址方式里,這種方式的訪問時間是最短的。 但它天生的缺陷是在程序運行中不能修改操作數(shù)。7/22/2022141 例2: mov( -50, AX ); /* 源操作數(shù)是立即尋址方式,目的操作數(shù)是寄存器尋址方式 *

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論