Windows 匯編語言編程教程_第1頁
Windows 匯編語言編程教程_第2頁
Windows 匯編語言編程教程_第3頁
Windows 匯編語言編程教程_第4頁
Windows 匯編語言編程教程_第5頁
已閱讀5頁,還剩16頁未讀, 繼續免費閱讀

下載本文檔

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

文檔簡介

1、Windows 匯編語言編程教程Version 1.02Copyright2005,Jeff Huang.All rights reserved Translator:fqh 2005.7.10JEFF HUANG 作,fqh 譯目錄介 紹 2為什么選用匯編語言 2為什么選擇Windows系統2開始學習之旅 .3編譯器 3編輯器 3第一個程序 4控制臺程序 4窗體程序 6ADDR 與 OFFSET6匯編基礎7cpu 寄存器 7指令集基礎 8Push 和 Pop8Invoke 9程序例子 9IV. 窗體程序基礎10預備知識10變量10一個簡單的窗體程序11IV. 深入匯編和系統13控制15附加資

2、源 16MASM3216MSDN16IRC 16介 紹“Thisisforallyoufolksoutthere,whowanttolearnthemagicartofAssembly programming”-MAD介 紹我最近才開始學習windowsIRC 通訊工具請問他人,本側重于X86知識。為什么選用匯編語言?匯編語言具有若干的特色,使得在某此情況下,匯編語言是一種很好的選擇。序是用匯編語言編寫的。在實現某些特定的要求時變得困難。是非常有用的。為什么選擇Windows 系統?人在使用基于x86 處理器的Windows序。第 一 章 勝任這些工作的運行于Windows編譯器Windows

3、.exe 為后綴的。下面給出一些流行的編譯器:1 MASM先由微軟公司開發,現在被包括在MASM32v8MASM32v8 程序包還包括了其他的工具。你可以從這個網址得到它: HYPERLINK / /.注意:教程中有一些指令和宏指令,只有在MASM 編譯器才是有效的,所以強烈建議您從開始學習時選用MASM。TASM 這是另一個受歡迎的編譯器。由Borland所以你不能免費地獲取到它。NASM址獲取到 HYPERLINK /projects/nasm/ /projects/nasm/記住編輯器器,你可以試用一下它們并選擇一種你喜歡的。Notepad 記事本,WindowsVisual Studi

4、o易于閱讀。Ultraedit (我個人最喜歡的e) HYPERLINK / /Textpad HYPERLINK / /VIM HYPERLINK / /Emacs HYPERLINK /software/emacs/emacs.html /software/emacs/emacs.htmljEdit HYPERLINK / /第 二 章 現在我們有了自己的工具,打開你的文本編輯器,跟著下面的介紹,開始學習編程吧。這是世上最普通的程序,“Hello World”程序??刂婆_程序控制臺程序是運行在系統控制臺的(也就大家所知的命令行.386.model flat, option casemap

5、include masm32includewindows.inc include masm32includekernel32.inc include masm32includemasm32.inc includelib masm32libkernel32.lib includelib masm32libmasm32.lib.dataHelloWorld db Hello World!, 0.code start:invoke StdOut, addr HelloWorld invoke ExitProcess, 0end start到cmdhello.asmasm32binml/c/Zd/co

6、ff hello.asmmasm32binLink /SUBSYSTEM:CONSOLE Hello.exeHello World!Hello World!,我們只要編寫很少的代碼就可以了。這些代碼都起了什么作用呢?讓我們一行一行地看下去。.386這條指令的作用是告知編譯器使用.386 指令集。當前,幾乎沒有處理器使用比.386 更老的指明令集了。我們還可以選擇使用.486.或 586,但是.386 是兼容性最好的指令集。.model flat, stdcall.MODEL 是一條指定你程序的內存模式的匯編指令。Flat(far(farStdcall 是一種系統函數傳遞參數的方法,它意味著你得

7、以從右到左的順序傳遞你的參數。option casemap :noneHellohello語言同樣是大小寫敏感的,所以這是個編程的良好習慣。include masm32includewindows.inc include masm32includekernel32.inc include masm32includemasm32.incwindows.incWin32 kernel32.inc 包含了我們所使用的ExitProcessmasm32.incStdOutStdOutWin32MASM32v8includelib masm32libkernel32.libincludelib masm

8、32libmasm32.lib函數依賴庫,基于這個目的,這些庫得包含進去。.data.data? 和.const World序中并沒有用到它們。HelloWorld db Hello World!, 0db 代表“字節”,并聲明HelloWorldHello World!NULL”字母,這是因為ANSINULL.code這代表程序代碼段的開始。start:你程序的代碼位于這個標號的后面,但位于” end startinvoke StdOut, addr HelloWorldInvoke HelloWorld World!的地址和調用StdOut。注意StdOut 函數只是在MASM32個調用其

9、它函數來輸出文件的宏。在別的編譯器里,你得使用更多的代碼并要用到win32 WriteConsole.。invoke ExitProcess, 00ExitProcess窗體程序 Worldhellow.asm.386.model flat, option casemap include masm32includewindows.inc include masm32includekernel32.inc include masm32includeuser32.inc includelib masm32libkernel32.lib includelib masm32libuser32.lib.

10、dataHelloWorld db Hello World!, 0.code start:invoke MessageBox, NULL, addr HelloWorld, addr HelloWorld, MB_OK invoke ExitProcess, 0end starthellow.asmmasm32binml /c /Zd /coff hellow.asmmasm32binLink /SUBSYSTEM:WINDOWS hellow.obj注意,subsystem 是WINDOWS 不再是CONSOLEHello World!的信息框。與控制臺版相比,窗體版本的代碼只有3 行是不同

11、的。其中有兩行把masm32 包含文件和庫文件更換為user32MessageBox不是使用StdOut3 個不同的行是用MessageBox 函數代替了StdOut就這么多而已!ADDR 與 OFFSETHello addr 來獲取字符串Hello World! offsetaddr 第三章匯編基礎cpu 寄存器32 位通用寄存器有8168 存取eax168ah916地址名稱描述EAX*累加寄存器進行計算操作和保存數據結果EBX基址寄存器指向數據寄存器中的數據ECX*計數寄存器字符串以及循環的計數EDX*數據寄存器輸入/輸出的指針ESI源變址寄存器字符串操作中的源指針EDI目的變址寄存器字符

12、串操作中的目的指針ESP堆棧指針寄存器堆棧指針,不能人為使用它EBP堆?;芳拇嫫?注意:雖然它們被稱為通用寄存器,但是只有那些標有*號的才能在窗體程序編程中使用。616地址CS代碼段寄存器保存要運行的指令DS,ES,FS,GS數據段寄存器數據段SS堆棧段寄存器 232地址名 稱 描述EFLAGE標志寄存器狀態,控制,系統標志EIP指令指針寄存器下一個要執行的指針的偏移指令集基礎x86 指令集非常宏大,但是我們通常并沒全都使用到了它們。下面介紹一些我們應該掌握的指令。指令描述ADD* reg/memory, reg/memory/constant把兩個操作數相加并把結果保存進第一個操作數。如果

13、有進位的話,它會設置CF 標志位SUB* reg/memory, reg/memory/constant第一個操作數減去第二個操作數,并把結果保存到第一個操作數里AND* reg/memory, reg/memory/constant兩個操作數邏輯與,并把結果存到第一個操作數里OR* reg/memory, reg/memory/constant兩個操作數邏輯或,并把結果存到第一個操作數里XOR* reg/memory, reg/memory/constant兩者異或,并把結果存到第一個操作數里。注意你不能對兩個存儲器操作數進行異或操作MUL reg/memory操作數與累加器寄存器相乘,而后

14、把結果存進累加器寄存器DIV reg/memory累加器寄存器被操作數除并把結果存到累加器INC reg/memory1DEC reg/memory1NEG reg/memory操作數的值取補并把結果存進操作數NOT reg/memory操作數的值取反并把結果存進操作數PUSH reg/memory/constant把操作數壓進堆棧頂端POP reg/memory彈出堆棧頂端的值并保存到操作數MOV* reg/memory, reg/memory/constant把第二個操作數的值保存到第一個操作數里面CMP* reg/memory, reg/memory/constant第一個操作數減第二個

15、操作數,并設置相應當的標志位。通常與 JMP,REP 等指令一起使用JMP* label跳轉到標號處LEA reg, memory取第二個操作數的地址偏移,并把結果保存進第一個操作數CALL subroutine調用另一個過程直到程序返回RET程序返回到調用者INT constant調用操作數指定的中斷*指令不能有兩個存儲器操作數*CF=0 這一條件下才會跳轉。最新的全部指令集參考可以從下面這個網址得到 HYPERLINK /design/pentium4/manuals/index.htm /design/pentium4/manuals/index.htm.Push 和 PopPushpo

16、pPushPop(LIFO議你先掌握這一知識。InvokeInvoke 是 MASM 特有的一個偽指令。它使得在調用函數前不必先傳遞參數。這讓我們省略了很多的代碼。舉個例子說明如下invoke SendMessage, hWnd, WM_CLOSE, 0, 0等效于:push 0push 0push WM_CLOSE push hWndcall SendMessage程序例子下面是一個完整的程序。它說明了如何去使用指令和寄存器。看看是否全部弄懂了它。.386.model flat, option casemap include masm32includewindows.inc include

17、masm32includekernel32.incinclude masm32includemasm32.inc includelib masm32libkernel32.lib includelib masm32libmasm32.lib.dataProgramText db Hello World!, 0BadText db Error: Sum is incorrect value, GoodText db Excellent! Sum is 6, 0Sum sdword 0.code start:; eaxmov ecx, 6 ; set the counter to 6 xor ea

18、x, eax ; set eax to 0 0_label: add eax, ecx ; add the numbers ? dec ecx ; from 0 to 6 ?jnz _label ; mov edx, 7 ; mul edx ; multiply by 7 147push eax ; pushes eax into the stack pop Sum ; pops eax and places it in cmp Sum, 147 ; compares Sum to 147jz _good ; if they are equal, go to _good_bad: invoke

19、 StdOut, addr BadText jmp _quit_good: invoke StdOut, addr GoodText_quit: invoke ExitProcess, 0 end start注意:“;”符號表示注釋。所有跟在它后面的字符都不會被編譯。把提示和注意點放在注釋中是個好主意,它能讓你的代碼易讀。第四章IV. 窗體程序基礎窗體程序通常由一個或幾個窗體組成。因此,做為 windows 程序員至少要懂得怎么創建一個簡單的窗體。很不幸,它不是那么容易的事,但是本教程會指導你怎么去做。預備知識在編寫窗體程序前我們還要討論幾個主題。讓我們花點時間復習一下預備知識。宏MASM 有

20、幾個讓匯編編程變得非常容易的宏。我們已經接觸到invoke,它簡單地調用一個函數。下面列出其他幾種,之前在你用高級語言編程時它們的用法是很明顯的。.if, .else, .endif.while, .break, .endw過程與高級語言類似,MASM 讓你定義各種過程使得你的代碼易于閱讀。它們的格式如下所示: proc :, :, . ret endp返回值保存在eax 寄存器里,這個過程用下面格式來調用invoke , param1, param2, .返回值可以用下面指令來獲取mov RetVal, eax變量.data.data.const 化。格式如下:local : (4 byte

21、s)。還有更多,但是它們常常與這三種類型中的一種是相同的,只不過名稱不同。一個簡單的窗體程序窗體程序有兩個主要的部分。第一部分是WinMainWndProc,它是接收消息的,這部分處理你的鼠標事件及刷新窗口等。.386.model flat, option casemap include masm32includewindows.inc include masm32includeuser32.inc include masm32includekernel32.inc includelib masm32libuser32.lib includelib masm32libkernel32.lib

22、以上是我們通常必需的WinMain proto :DWORD, :DWORD, :DWORD, :DWORDThis is a function prototype. It lets us call the WinMain function later in the program.It can be compared to a C/C+ function declaration.這是函數原型。在稍后的程序里我們稱它為WinMain 函數。.dataClassName db WinClass, 0 AppName db Simple Window, 0 我們聲明我們的字符變量.data?hIn

23、stance HINSTANCE ?變量hInstance 保存模塊實例的句柄,以便與窗體相關聯。稍后我們將把它傳遞到CreateWindow 函數中。.code start:invoke GetModuleHandle, NULL mov hInstance, eaxinvoke WinMain, hInstance, NULL, NULL, 0invoke ExitProcess, eax獲取模塊句柄并把它保存到變量hInstanceWinMainWinMain是這個程序的核心,所以我們將深入研究它。注意:從這點來看,我們假設你能夠從MSDN 中查找windows 函數。它有函數參數,返回

24、值,還有其它你必須了解的信息。你可以在附加資源這個章節里獲取關于MSDN 的信息。WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR,CmdShow:DWORDlocal local msg:MSGlocal hwnd:HWND這是WinMainhwnd。Wc Msg保存我們窗本的句柄。mov wc.cbSize, SIZEOF WNDCLASSEXmov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, offset WndProcmov wc.cbCls

25、Extra, mov wc.cbWndExtra, 注意:在窗體程序中,or操作運算符常常用來聯合參數中的標志。push hInstance pop mov wc.hbrBackground, COLOR_WINDOW+1 mov wc.lpszMenuName, NULLmov wc.lpszClassName, offset ClassName invoke LoadIcon, NULL, IDI_APPLICATION mov wc.hIcon, eaxmov wc.hIconSm, eaxinvoke LoadCursor, NULL, IDC_ARROW mov wc.hCursor

26、, eaxinvoke RegisterClassEx, addr wc這些是填充我們先前聲明的wc 結構。然后以wc 為參數調用RegisterClassEx。至于更多關于wc 的每個成員的信息,請在MSDN 中查找WNDCLASSEX 結構的資料。invoke CreateWindowEx, 0, addr ClassName, addr AppName, WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL, hInst, NULLmo

27、v hwnd, eax調用CreateWindowEx 函數創建窗體。其中有很多參數被傳遞進去來表明怎么創建窗體。窗體的句柄會返回并保存到變量hwnd 中。.while TRUEinvoke GetMessage, addr msg, NULL, 0, 0.break .if (!eax)invoke TranslateMessage, addr invoke DispatchMessage, addr msg.endw這個whileGetMessage 取回這些消息并保存進msgTranslateMessage些消息發送到WndProcWndProcmov eax, msg.wParam r

28、etWinMain endp返回值保存進msg.wParam,WinMain 函數結束。WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM.if uMsg = WM_DESTROY invoke PostQuitMessage, .elseinvoke DefWindowProc, hWnd, uMsg, wParam, lParam ret.endifxor eax, eax retWndProc endpWndProc PostQuitMessageWM_CREATE(當創建窗體時),WM_PAINT (當窗體必須

29、重畫時), 還有WM_CLOSE (關閉窗體時)。其它沒有處理的消息被傳遞給DefWindowProcend start就這些了。你已經了解了怎么去創建一個窗體! 第五章IV. 深入匯編和系統下面有一些資料來擴展你關于匯編以及系統編程方面的知識:字符串操作,文件處理, 還有系統窗體的控制。字符串操作 中的方向控制標志。方向控制標志是指定移動字符串時的方向。一些常見的字符串操作指令是movsb, cmpsb, stasb, and stosb.為了操作字符串,你可以在字符串控制指令中使用某些rep?的形式。下面是在串操 作指令中可以使用到rep?前綴前綴描述rep movsb復制字符串repe

30、cmpsbrepne scasb掃描字符串中一個字符rep stosb保存一個字符到字符串中下面給個復制字符串的例子cld ; sets the direction flag to forwardmov esi, source ; move the source address in to esi mov edi, dest ; move the destination address in to mov ecx, length ; move the length to copy in to ecx rep movsb ; copy length bytes from esi to edi文件

31、管理在舊的DOSwindows過使用系統函數訪問文件。其中可供我們使用的4CreateFile 創建或打開一個文件,并返回它的句柄ReadFile 從文件中讀取數據WriteFile 寫數據到文件里CloseHandle 關閉你用CreateFile 函數得到的句柄存儲為了讀取文件內容,我們必須分配一些內存來存儲數據。內存可以如你所愿地被分配, 鎖定,但是最后記得解鎖和釋放。做這些工作的函數是GlobalAlloc, GlobalLock,GlobalUnlock, 還有GlobalFree程序例子這個程序讀取c:test.txt的內容,并通過一個消息框輸出。.386.model flat,

32、option casemap include masm32includewindows.inc include masm32includeuser32.inc include masm32includekernel32.inc includelib masm32libuser32.lib includelib masm32libkernel32.lib 一些通常的包含文件.dataFileName db c:test.txt, 0.data?hFile HANDLE ?hMemory HANDLE pMemory DWORD ? ReadSize DWORD 我們定義字符串,還聲明了四個將會用

33、到的變量.constMEMORYSIZE equ 65535這是說明分配多大的內存,這樣有足夠的空間保存我們的文件.code start:invoke CreateFile, addr FileName, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULLmov hFile, eax調用CreateFile 函數并保存文件句柄到hFile 變量。通常,放置一個h在句柄之前, 而放置p在指針之前invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINI

34、T, MEMORYSIZE mov hMemory, eaxinvoke GlobalLock, mov pMemory, eax分配并鎖定我們的內存invoke ReadFile, hFile, pMemory, MEMORYSIZE-1, addr ReadSize, invoke MessageBox, NULL, pMemory, addr FileName, MB_OKinvoke GlobalUnlock, pMemory invoke GlobalFree, hMemoryinvoke CloseHandle, hFile invoke ExitProcess, NULL end

35、 start可別忘清除工作啊控制這是容易的事!它的語法非常類似于創建一個窗體,除此外,我們不必調用RegisterClassEx,因為我們的類將為我們預先定義了。為了做到這些,從第4 章內容那里編輯 WndProc 函數來響應WM_CREATE 消息.elseif uMsg = WM_CREATEinvoke CreateWindowEx, NULL, addr ButtonClassName, addr ButtonText, WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON, 10, 50, 80, 30, hWnd, ButtonID, hInstance,NULLmov hButton, eaxinvoke CreateWindowEx, WS_EX_CLIENTEDGE, addr EditClassName, NULL, WS_CHILD or W

溫馨提示

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

評論

0/150

提交評論