汇编器以及汇编流程
用匯編語言編寫的源程序不能直接在其目標(biāo)計(jì)算機(jī)上執(zhí)行,必須通過翻譯或匯編將其轉(zhuǎn)換為可執(zhí)行代碼。實(shí)際上,匯編器與編譯器 (compiler) 很相似,編譯器是一類程序,用于將 C++ 或 Java 程序翻譯為可執(zhí)行代碼。
?
匯編器生成包含機(jī)器語言的文件,稱為目標(biāo)文件 (object file)。這個文件還沒有準(zhǔn)備好執(zhí)行,它還需傳遞給一個被稱為鏈接器 (linker) 的程序,從而生成可執(zhí)行文件 (executable file)。這個文件就準(zhǔn)備好在操作系統(tǒng)命令提示符下執(zhí)行。
匯編-鏈接-執(zhí)行周期
下圖總結(jié)了編輯、匯編、鏈接和執(zhí)行匯編語言程序的過程。下面詳細(xì)說明每一個步驟。
?
- 步驟1:編程者用文本編輯器 (text editor) 創(chuàng)建一個 ASCII 文本文件,稱之為源文件。
- 步驟2:匯編器讀取源文件,并生成目標(biāo)文件,即對程序的機(jī)器語言翻譯。或者,它也會生成列表文件。只要出現(xiàn)任何錯誤,編程者就必須返回步驟 1,修改程序。
- 步驟3:鏈接器讀取并檢查目標(biāo)文件,以便發(fā)現(xiàn)該程序是否包含了任何對鏈接庫中過程的調(diào)用。鏈接器從鏈接庫中復(fù)制任何被請求的過程,將它們與目標(biāo)文件組合,以生成可執(zhí)行文件。
- 步驟4:操作系統(tǒng)加載程序?qū)⒖蓤?zhí)行文件讀入內(nèi)存,并使 CPU 分支到該程序起始地址,然后程序開始執(zhí)行。
列表文件
列表文件 (listing file) 包括了程序源文件的副本,再加上行號、每條指令的數(shù)字地址、每條指令的機(jī)器代碼字節(jié)(十六進(jìn)制)以及符號表。符號表中包含了程序中所有標(biāo)識符的名稱、段和相關(guān)信息。
高級程序員有時會利用列表文件來獲得程序的詳細(xì)信息。下面的代碼展示了 AddTwo 程序的部分列表文件,現(xiàn)在進(jìn)一步查看這個文件。1?7 行沒有可執(zhí)行代碼,因此它們原封不動地從源文件中直接復(fù)制過來。第 9 行表示代碼段開始的地址為 0000 0000(在 32 位程序中,地址顯示為 8 個十六進(jìn)制數(shù)字)。這個地址是相對于程序內(nèi)存占用起點(diǎn)而言 的,但是,當(dāng)程序加載到內(nèi)存中時,這個地址就會轉(zhuǎn)換為絕對內(nèi)存地址。此時,該程序就會從這個地址開始,比如 0004 0000h。
; AddTwo.asm - adds two 32-bit integers. ; Chapter 3 example .386 .model flat,stdcall .stack 4096 ExitProcess PROTO,dwExitCode:DWORD 00000000 .code 00000000 main PROC 00000000 B8 00000005 mov eax, 5 00000005 83 C0 06 add eax,6 invoke ExitProcess,0 00000008 6A 00 push +000000000h 0000000A E8 00000000 E call ExitProcess 0000000F main ENDP END main第 10 行和第 11 行也顯示了相同的開始地址 0000 0000,原因是:第一條可執(zhí)行語句是 MOV 指令,它在第 11 行。請注意第 11 行中,在地址和源代碼之間出現(xiàn)了幾個十六進(jìn)制字節(jié),這些字節(jié)(B8 0000 0005)代表的是機(jī)器代碼指令(B8 ),而該指令分配給 EAX 的就是 32 位常數(shù)值(0000 0005):
00000000 B8 00000005 mov eax, 5數(shù)值 B8 也被稱為操作代碼(或簡稱為操作碼),因?yàn)樗硎玖颂囟ǖ臋C(jī)器指令,將一個 32 位整數(shù)送入 eax 寄存器。
第 12 行也是一條可執(zhí)行指令,起始偏移量為 0000 0005。這個偏移量是指從程序起始地址開始 5 個字節(jié)的距離。
第 14 行有 invoke 偽指令。注意第 15 行和 16 行是如何插入到這段代碼中的,插入代碼的原因是,INVOKE 偽指令使得匯編器生成 PUSH 和 CALL 語句,它們就顯示在第 15 行和 16 行。
代碼中展示的示例列表文件說明了機(jī)器指令是怎樣以整數(shù)值序列的形式加載到內(nèi)存的,在這里用十六進(jìn)制表示:B8、0000 0005、83、C0、06、6A、00、EB、0000 0000。每個數(shù)中包含的數(shù)字個數(shù)暗示了位的個數(shù):2 個數(shù)字就是 8 位,4 個數(shù)字就是 16 位,8 個數(shù)字就是 32 位,以此類推。所以,本例機(jī)器指令長正好是 15 個字節(jié)(2 個 4 字節(jié)值和 7 個 1 字節(jié)值)。
當(dāng)程序員想要確認(rèn)匯編器是否按照自己的程序生成了正確的機(jī)器代碼字節(jié)時,列表文件就是最好的資源。如果是剛開始學(xué)習(xí)機(jī)器代碼指令是如何生成的,列表文件也是一個很好的教學(xué)工具。
若想告訴 Visual Studio 生成列表文件,則在打開項(xiàng)目時按下述步驟操作:在 Project 菜單中選擇 Properties,在 Configuration Properties 下,選擇 Microsoft Macro Assemblero 然后選擇 Listing File。在對話框中,設(shè)置 Generate Preprocessed Source Listing 為 Yes,設(shè)置 List All Available Information 為 Yes。
下一篇:數(shù)據(jù)類型以及數(shù)據(jù)定義
強(qiáng)力推薦閱讀文章
年薪40+W的大數(shù)據(jù)開發(fā)【教程】,都在這兒!
總結(jié)
- 上一篇: Linux服务器安全之用户密钥认证登录(
- 下一篇: 汇编语言数据类型以及数据定义详解