win32asm原理 (轉)

gugu99發表於2007-12-30
win32asm原理 (轉)[@more@]中文翻譯:肖德時

這篇指南是想讓讀者能懂得怎樣使用MASM。如果你不熟悉MASM,請
一個asm.exe並透過本指南學習下去。好的,現在準備好
讓我們一起前進吧!

原理概述:
從80286開始就有了保護下的win32,但是這已經成為歷史。
所以我們這裡所涉及到的都是與我們相關的80386及以後的版本。
在單獨的虛擬空間執行單個win32程式。這個意思就是
說每個win32程式都有自己獨立的4GB定址空間。但這並不意味著每
個win32程式都有4GB的物理空間,只僅僅是這個程式能在這個
範圍裡定址而已。工作是由windows來處理並確認這個程式地址
的有效性。當然,這個程式必須是按照windows程式規則來編譯的
才行。和win16程式不一樣的是所有的win16程式互相“看到”對方。
這在win32下是沒有的。這個特徵幫助減少某程式程式碼覆蓋另一程式
的可能。記憶體模式也和以往的win16世界完全的不同。在win32世界裡,
我們不需要考慮記憶體模式或者是什麼段。這裡只有一種模式:Flat memory model.
這裡也沒有什麼64K段地址的限制。記憶體是一個4GB的連續的大空間。
也就是說我們不必非要和段暫存器玩。我們也能用一些段暫存器來
定址記憶體中的某處。這對程式設計師來說是一個極大的幫助。這也讓
編譯win32程式和c語言一樣。
當你在win32下編譯程式時,你必須要知道一些重要的規則。其中一個是:
windows內部使用esi、edi,ebp和ebx並不能在這暫存器中改變數值。所以
記住這條規則的意思就是:假如你在返回中使用這四個暫存器中某個
的話,不要忘記在返回window時恢復初值。一個返回函式就是在你的程式中
返回window。一個返還函式就是被windows的你自己的私有函式,最典型
的例子就是windows程式。但這並不意味著你不能使用這四個暫存器了,只要
你能確認在返回windows時恢復了它們的初值就行了。

程式碼內容:
下面就是win32匯序程式碼的主,如果你看不懂這些程式碼的話,也不要
著急,我將在後面給予詳細的解釋。
.386
.MODEL FLAT,STDCALL
.DATA
 
 .........
.DATA?
 
 .........
.CONST

.......
.CODE
 
 
 ......
 end
 
就是這些,讓我們分析一下這個主框架吧!
.386
這是一個程式指令,告訴彙編編譯程式使用80386指令集,你也可以用.486,.586。
但可靠的指令集還是用.386。這裡還有兩個實際上差不多的指令集:.386/.386p,.486/.486p;
那個有“p”的指令集只是在用到有特權指令時才用到。特權指令集是隻在保護模式
下被這個/操作所接受的。它們也只能被特權程式碼所使用,例如裝置程式。
多數情況下,你的程式是工作在非特權模式下所以的作法是使用不帶“p"的指令。
.MODEL FLAT,STDCALL
.MODEL是標記記憶體模式的指令,在win32下,也僅僅只有這個模式:FLAT。
STDCALL是告訴引數的傳遞模式。在這個模式中有:左到右或右到左。
並要在完成子程式後平衡堆疊。在win16下,有兩種傳遞模式:c和pascal。C子程式傳遞
是右到左,最右邊的引數將首先被壓入,並在傳遞結束時要求平衡堆疊。例如:一個名為
foo的程式被呼叫,(int first_param,int second_param,int third_param)在C程式傳遞
中的彙編程式碼如下
 push [third_param] ;壓入第三個引數
 push [second_param]     ;壓入第二個引數
 push [first_param] ;壓入第一個引數
 call foo
 add sp,12 ;平衡堆疊
PASCAL正好與C傳遞模式相反,它是透過左到右傳遞引數並在完成子程式後平衡堆疊的。
win16採取PASCAL傳遞方式是因為它的執行程式碼量小。C傳遞模式是在你不知道要傳遞
多少引數比如像wsprintf()子程式。在wsprintf()子程式中,子程式不能預先知道有
多少引數被壓棧,所以你也不知道要怎樣使堆疊平衡。
STDCALL是C和PASCAL傳遞模式的綜合,它是透過右到左傳遞模式傳遞引數並平衡堆疊的,並
只有在win32下才專用的傳遞模式。但也有例外的是wsprintf(),你必須使用C傳遞模式。

.DATA
.DATA?
.CONST
.CODE
這四個指令是幹什麼用的呢?在win32下是沒有段的,你記起來了嗎?但是你仍然能按照
邏輯分割槽劃分你的地址空間。這個最先的分割槽表是上一分割槽的結束。這裡我們分為兩個分割槽,
data和code。data分割槽又被分為三類:
.DATA 這個分割槽包含你的程式的初始化程式碼
.DATA?這個分割槽包含你程式的未初始化資料,有時你想預先分配一些記憶體但不想初始化它,
這個分割槽就是為這個想法而設的。這個未初始化資料的優勢是:它不會增加程式容量大小。
比如,你在.DATA?分配了10,000位元組容量,但你的程式並不是增加了10,1000位元組。它仍然
和原大小一樣。你只是僅僅告訴編譯器當程式載入記憶體時你需要多少空間。就是這些。
.CONST 這個分割槽包含你的程式的常量定義說明。在這個分割槽定義的常量就不能被修改,因為
它們已經被定義。

你也並不是非要在你的程式中都要使用這三個指令,只要說明你需要的指令就行了。

剩下來的分割槽是程式碼區:.CODE。以下是它的主構架:

end
這裡的任意的只是說明你的程式碼區域,還有就是這兩個label要一樣喲!你的所有程式碼
都在和 end 之間。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-996191/,如需轉載,請註明出處,否則將追究法律責任。

相關文章