學習windows32彙編程式設計(筆記)

2021-04-24 14:42:57 字數 3924 閱讀 2692

今天想學習win32彙編程式設計,在taowen部落格中閱讀了其翻譯的win32asm教程,摘抄了一些我自己需要學習的要點。原教程的部落格位址是:http://www.cnblogs.com/taowen/articles/11237.html  。很高興網上有這麼多愛學習的朋友們奉獻資料。

在windows中程式設計,你不再需要了解dos中斷(interrupt)和埠(port)in/out函式。在windows中,windowsapi提供了你可在你的程式中使用的標準函式

需要參考一些api函式的用法,現在有極好的msdn供選擇

eax (ax/ah/al) 加法器

ebx (bx/bh/bl) 基(base)

ecx (cx/ch/cl) 計數器

edx (dx/dh/dl) 資料

段暫存器定義了哪一段記憶體被使用。你可能在win32asm中用不著它們,因為windows有乙個平坦(flat)的記憶體系統。在windows中,段有4gb的大小,所以你在windows中不需要段。段總是16位暫存器。

cs  **段

ds  資料段

ss  棧段

es  擴充套件段

fs (only 286+)  全功能段

gs (only 386+)  全功能段

你可以把指標暫存器當作全功能暫存器來使用(除了eip),只要你儲存並恢復它們的原始值。指標暫存器之所以這麼叫是因為它們經常被用來儲存記憶體位址。一些偽**(movb,scasb等)也要用它們。

esi (si)  源索引

edi (di)  目標索引

eip (ip)  指令指標

2個棧暫存器:esp和ebp。esp裝有記憶體中當前棧的位置。ebp在函式中被用成指向區域性變數的指標。

在執行於dos和win3.xx的16位程式中,記憶體被分成許多個段。這些段的大小為64kb。最多有65536個段。為了指向段中的位置,需要使用offset。乙個offset是段內部的乙個位置。每個段最多有65536個offset。在32位windows(95及以上),你仍然有段,但不用管他們了。因為它們不再是64kb,而是4gb。你如果嘗試著改變段暫存器中的乙個,windows甚至會崩潰。這稱為平坦(flat)記憶體模式。只有offset,而且是32位的,因而範圍從0到4,294,967,295。記憶體中的每乙個位址都是用offset表示的。

32位的值也就是4位元組大小。

十六進製制dword(32位)值放在記憶體中時是這樣:40, 30, 20, 10(每個值佔乙個位元組(8位))

十六進製制word(16位)值放在記憶體中時是這樣:50, 40

mov cl, byte ptr [34h] ; cl得到值0dh(參考上表)

mov dx, word ptr [3eh] ; dx將得到值 7defh (記住反序), 因為儲存在記憶體中的值使用了little endian格式。這意味著越靠右的位元組位數越高:位元組順序被反轉了

大小有時不是必須的。

mov eax,[00403045h]

因為eax是32位暫存器,編譯器假定(也只能這麼做)它應該從位址403045(十六進製制)取個32位的值。

可以直接使用數值:

mov edx, 5006

這只是使得edx暫存器裝有值5006,綜括號[和]用來從括號間的記憶體位址處取值,沒有括號就只是這個值。暫存器和記憶體位址也可以(他應該是32位程式中的32位暫存器):

mov eax,403045h;使eax裝有值403045h(十六進製制)

mov cx,[eax];把位於記憶體位址eax的word大小的值(403045)移入cx暫存器。

在mov cx, [eax]中,處理器會先檢視eax裝有什麼值(=記憶體位址),然後在那個記憶體位址中有什麼值,並把這個word(16位,因為目標-cx-是個16位暫存器)移入cx。

彙編原始檔被分成了幾個部分。這些部分是code,data,未初始化data,constants,resource和relocations,資源部分是資源檔案建立的。

在你的原始檔(*.asm)中,你可以用部分識別符號定義各部分:

.code;**部分由此開始

.data;資料部分由此開始

.data?;未初始化資料部分由此開始

.const;常量部分由此開始

可執行檔案(*.exe,*.dll和其他)是(在win32中)可移植執行格式(pe)。部分(sections)的一些屬性定義在pe頭中:

section名,rva,offset,原始大小,虛擬大小和標誌。rva(相對虛擬位址)是將要裝入的section部分的相對記憶體位址。這裡相對的意思是相對於程式載入的基位址。這個位址也在pe頭中,但可以由pe-loader改變(使用relocation部分)。offset是初始化資料所在的exe檔案本身的原始offset。虛擬大小是程式在記憶體中將達到的大小。標誌是讀/寫/可執行等。

你和處理器都不能看出乙個值是signed還是unsigned。好訊息是對於加法和減法來說,乙個數是signed還是unsigned沒有關係。

計算:-4+9

fffffffc+00000009=00000005(這是對的)

計算:5-(-9)

00000005-fffffff7=0000000e(這也是對的,5――9=4)

壞訊息是對於乘法,除法和比較(compare)並不是這樣。因此,對於signed數有特殊的乘除偽**:imul和idiv

imul也有乙個比mul好的地方在於它可以接受直接數值:

imul src

imul src, immed

imul dest,src, 8-bit immed

imul dest,src

idiv src

它們幾乎和mul,div一樣,只是它們可以計算signed值。比較(compare)可以和unsigned一樣用。但標誌作不同的設定。因此,對於符號和無符號數字有不同的jump指令:

cmp ax, bx

ja somewhere

ja是乙個無符號跳轉指令。如果大於就跳轉。考慮這個ax=ffffh(無符號時為ffffh,有符號時為-1)和bx=0005h(無符號時為5,有符號時為5)。由於ffffh在無符號時比0005大,ja指令會跳轉,但如果用的是jg(指乙個有符號跳轉):

cmp ax, bx

jg somewhere

jg指令不會跳轉,因為-1不比5大。

只要記住這點:乙個數字是有符號還是無符號取決於你怎樣對待這個數。

test對兩個引數(目標,源)執行and邏輯操作,並根據結果設定標誌暫存器。結果本身不會儲存。test用來測試乙個位,例如暫存器:

test eax, 100b;b字尾意為二進位制

jnz bitset

如果eax右數第三個位被設定了,jnz將會跳轉。test的乙個非常普遍的用法是用來測試一方暫存器是否為空:

test ecx, ecx

jz somewhere

如果ecx為零,jz跳轉

棧是記憶體的乙個地方,esp為指向棧的指標。棧是用來儲存臨時數值的地方,有兩個指令來放入乙個指和再把它取出來:push和pop。push把乙個指壓入棧。pop再把它彈出來。最後乙個放入的值最先出來。乙個值被放入棧中,棧指標步減,當它移出來的時候,棧指標步增。棧頂總是棧中位址最小的位置

call跳轉到某段**而且一發現ret指令就返回。你可以把它們看成在其他程式語言中的函式或子程式。call把eip(指向將要執行指令的指標)壓入棧,而ret指令在它返回的時候把它彈出來。你也可以給乙個call指定的引數。這是由壓棧來完成的:

push something

push something2

call procedure

在乙個呼叫的內部,引數從棧中讀出並使用。注意,只在過程中需要的區域性變數也儲存在棧中。只要記住你可以寫過程,而且它們可以由引數。乙個重要的地方:

eax幾乎總是用來裝乙個過程的返回值。

對於windows函式也是如此。但然,你可以在你的過程使用其他的暫存器,但這是標準。

windows32位下安裝Redis 連線PHP

為了省去用cmd進入資料夾的麻煩可以直接進入到你的redis資料夾下shift 滑鼠右鍵 如右圖 接著輸入以下指令 redis.conf為redis的配置檔案,有需要的可以修改過後執行,這個是我從網上copy下來改好能用的 如果你能看到cmd顯示以下內容,恭喜你,你的redis服務端已經能用了 以後...

Windows 32位64位區別,檢視方法

術語 32 位 和 64 位 是指計算機的處理器 也稱為 cpu 處理資訊的方式。64 位版本的 windows 可處理大量的隨機訪問記憶體 ram 其效率遠遠高於 32 位的系統。檢視我的計算機執行的是32位還是64位的windows?1.對於win 7 單擊 開始 按鈕,右鍵單擊 計算機 單擊屬...

STM32彙編程式設計

1.實驗環境 1.野火stm32指南者 stm32f103vet6 2.keil5 2.環境搭建新建工程 新增原始檔 s 連線開發板,開始debug 生成的hex檔案 原始碼led0 equ 0x40010c00 rcc apb2enr equ 0x40021018 gpioa crh equ 0x...