win32彙編快速入門

2021-08-30 11:58:52 字數 4018 閱讀 6973

彙編可以開發windows程式?答案是肯定的,用win32組合語言開發出來的windows程式具有執行效率高、占用空間小等特點。

m32v9r.zip

二、知識預備

1、暫存器

為了提高運算速度和資料的訪問速度,在計算機的cpu內,有一組硬體裝置,第乙個裝置內存放cpu運算需要的數,這些數值可供cpu直接訪問,這組裝置叫暫存器。暫存器分為通用暫存器、段暫存器、程式指標暫存器、標誌暫存器。

程式設計最常用就是通用暫存器,常用的通用暫存器有eax,ebx,ecx,edx,esi,edi等等,現代計算機的cpu一般是以32位為單位進行運算,因此乙個暫存器最大能存放32位的二進位制數。每個暫存器通常都有它預設的用法,所謂預設只是一種程式設計的習慣,你可以不遵守這些用法,但是有些情況下必須遵守,因為我們開發的是windows程式,要遵守windows作業系統的規定和彙編語法本身的約束,比如呼叫乙個windowsapi函式,返回值放在eax,堆疊的棧頂位址在esp,在組合語言的迴圈中,ecx內存放迴圈的次數。具體暫存器的使用會在以後介紹。

2、堆疊

堆疊是個非常古老的概念,在dos時代就有了,也是個非常重要的東西,程式沒了它就活不了,堆疊就是在記憶體裡分配乙個區域,使用這個區域必須遵守乙個規定:後進先出,後進來的先出去,可以把它想像成乙個空木箱,首先往裡面放棉衣,然後往裡面放書,最後放上運動服。如果要取出書,必須得把最後放上的運動服取出,放的順序是棉衣->書->運動服,取的順序是運動服->書->棉衣,堆疊也是如此。

先解釋一下什麼是位址,記憶體**的便宜和記憶體容量的擴大,windows虛擬記憶體早已出現,記憶體中放著眾多的資料,必須要有方法表示記憶體某個地點,這個地點就用位址來表示。把記憶體以位元組為單位劃分,某個位址表示某個位元組的位址,如左下圖是乙個內有4個成員的堆疊,堆疊裡的成員以乙個位元組為單位(數的右邊標明了以十六進製制表示的位址,如1001)

+--+

+--+

+--+

+--+

+--+

堆疊是向下增長的,每增加乙個成員,棧頂(堆疊頂部的位址)的位址減1,對於這個堆疊,棧頂位址是af18,如果再往這個堆疊裡增加乙個成員的話,它的位址是:af18-1=af17。如果往這個堆疊裡增加乙個32位的數,棧頂的位址是多少呢,32位的數佔4個成員的位置,棧頂的位址為:af18-4=af14。

在這個堆疊中增加乙個32位數dab0cd90,新的堆疊如下:

+--+

+--+

+--+

+--+

+--+

+--+

+--+

+--+

+--+

三、win32組合語言的語法

為了方便大家理解和入門,下面盡量使用巨集彙編和偽指令地方進行描述,也正因為有了巨集彙編和偽指令的幫助,win32彙編才具有很多高階語言的特性,很多語法和c差不多。

1、win32匯程式設計序基本結構

.386

.model flat,stdcall

.data

初始化值的全域性變數定義

.data?

未初始化值的全域性變數定義

.const

常量定義

.code

..............

...............     

程式入口label

............

............

end程式入口label

2、變數定義

(1)定義全域性變數

全域性變數定義在.data和.data?內,

初始化變數的定義方式如下:

.data

變數名  型別  初始值1,初始值2,.......

變數名  型別  重複次數dup(初始值1,初始值2,....)

注意:如果用?表示初始值的話,則表示0

未初始化變數的定義方式是

.data?

變數名  型別 ?

(2)條件測試語句

(a)基本結構

.if條件

程式**

[.elseif]條件比較

程式**

.......

[.else]

程式**

.endif

(3)操作符

(a)比較操作符

== 相等

!=  不等於

>   大於

>=  大於或等於

<   小於

<=  小於或等於

&   位測試

!  邏輯非

&&  邏輯與

||  邏輯或

(b)位操作符

and按位與

or  按位或

xor 異或

shl邏輯左移

shr邏輯右移

(c)標誌暫存器操作符

carry?是否進製

overflow? 是否溢位

parity?  奇偶位是否置位

sign?   符號位標誌位是否被置位

zero?   零位標誌位是否置位

(4)迴圈語句  

(a)while語句 

while 條件

..........

..........

[.break[.if 退出條件]]

[.contine[.if 退出條件]]]

.end

(b)repeat語句

.repeat

...........

..........

[.break[.if 退出條件]]

[.contine[.if 退出條件]]]

.until 條件(或.untilcxz [條件])

(5)子程式定義

1、定義

子程式名 proc [距離][語言型別][可視區域][users 暫存器列表][,引數:型別]...[vararg]local 區域性變數列表

..............

...............

...............

子程式名 endp

2、如果在未定義前使用,要宣告、

函式名 proto [距離][語言][引數1]:資料型別,[引數2]:資料型別,...............

(6)資料結構

(a)宣告

wndclass struct

....

.....

......

wndclass ends

(b)定義

mystruct wndclass<1,1,...,1>

mystruct wndclass <>

(c)使用

mov eax,mystruct.lpfnwndproc

mov esi,offset mystruct

assume esi: ptr wndclass

mov eax,[esi].lpfnwndproc

.......

assume esi:nothing

四、在win32彙編中的使用windows api

win32彙編如果沒有api的幫助無法實現很多功能,筆者沒見過在win32匯程式設計序不呼叫api的。

呼叫api實際上是靠堆疊來完成引數傳遞的,既然是堆疊,那就要遵守後進先出的原則,這意味api的第乙個引數是最後乙個放入堆疊的,最後乙個引數是第乙個放入堆疊的。  

呼叫方式如下:

push 引數n

..........  

push 引數2

push 引數1

call api函式名

為了簡化**,也可以使用以下這種方式呼叫api

invoke api函式名,引數1,引數2,.....,引數n

Win32彙編基礎

常用指令 mov 目標運算元,源運算元 mov eax,0x0 進行資料傳遞 movzx mov zero x 以0填充高位,用法同上,push poppushad 所有暫存器壓棧 8個 popad 所有暫存器出棧 8個 lea 取位址指令,類似c語言中的 call 呼叫函式指令 add 加 sub...

Win32彙編 實數

386 選擇的處理器 model flat,stdcall option casemap none 指明識別符號大小寫敏感 include kernel32.inc 要引用的標頭檔案 includelib kernel32.lib 要引用的庫檔案 includelib msvcrt.lib 引用c庫...

開始學習win32彙編

前段時間對於csdn的部落格系統徹底失望,在我現在寫的東西都還不知道能不能正常發出去,鬱悶,加上過年有這麼久沒有來了。這段時間開始學習彙編,說到彙編,大學開過兩門相關課程,微機原理和微控制器都是學這方面的,不過那都是8086,51級別的彙編,感覺根本跟不上時代,那時候學的還不錯 現在想學習學習win...