當前位置:編程學習大全網 - 源碼下載 - 用匯編語言編寫壹個小程序(比如hello,word!)請懂的人幫忙提供源碼

用匯編語言編寫壹個小程序(比如hello,word!)請懂的人幫忙提供源碼

您正在看的匯編語言是:hello,world!win32匯編小程序。

首先我們看壹個“復雜”的Win32匯編程序

程序用來顯示壹個消息框

--------------------------------------------------

;文件名:3.asm

.386

.model flat ,stdcall

NULL equ 0

MB_OK equ 0

ExitProcess PROTO :Dword

MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:Dword

includelib kernel32.lib

includelib user32.lib

.data

szText db "Hello, world!",0

szCaption db "Win32Asm",0

.code

start:

push MB_OK

lea eax,szCaption

push eax

lea eax,szText

push eax

push NULL

call messageboxa

xor eax,eax

push eax

call exitprocess

end start

--------------------------------------------------

編譯鏈接:

分下面兩步進行:

ml /c /coff 3.asm

link /subsystem:Windows /libpath:d:\masm7\lib 3.obj

第壹步編譯生成3.obj文件

/c 表示只編譯,不鏈接

/coff 表示生成COFF格式的目標文件

第二步鏈接生成3.exe文件

/subsystem:windows 表示生成Windows文件

/libpath:d:\masm7\lib 表示引入庫的路徑為:d:\masm7\lib。

在安裝Masm32後,引入庫位於Masm32\Lib目錄下。

也可設置環境變量Lib的值:在dos提示符下鍵入Set Lib=d:\masm7\lib,這樣“鏈接”就可簡單寫成:

link /subsystem:Windows 3.obj,試想壹下,在程序調試過程中,修改源程序是常用的事啦,每次編譯鏈接都要帶/libpath:...那該有多煩人呢。當然,我們也可在源程序中直接給出引入庫的位置,這樣,鏈接時就方便啦,如下:

includelib d:\masm7\lib\kernel32.lib

includelib d:\masm7\lib\user32.lib

--------------------------------------------------

執行:在dos提示符下鍵入3,回車,出現壹個消息框,哈哈,真正的Win32程序!

--------------------------------------------------

深入分析:

看壹下源程序,有這麽兩行:call messageboxa\call exitprocess。大家壹看都知道,這是子程序調用,但是我們並沒寫這樣的子程序,事實上,這些是API函數。作為函數,我們在調用時可能需要傳送給函數壹些參數,程序怎麽知道傳送的參數有哪些,類型是什麽呢?就是通過函數原型定義,如下所示:

ExitProcess PROTO :Dword

MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:Dword

可以看出,ExitProcess有壹個參數,MessageBoxA有四個參數,這些參數都是Dword類型。

在Win32中,參數的傳遞都是通過堆棧來完成的。象MessageBoxA這個函數有四個參數,究竟是左邊的先壓入堆棧還是右邊的先入棧呢?.model flat,stdcall給出了答案。stdcall 指定參數是從右到左壓入堆棧的,且調整堆棧是在子程序返回時完成的。在源程序中不需要用“add sp,值”來保持堆棧平衡。對MessageBox,在API手冊中是這樣定義的:

int MessageBox(

HWND hWnd, // handle of owner window

LPCTSTR lpText, // address of text in message box

LPCTSTR lpCaption, // address of title of message box

UINT uType &n

您正在看的匯編語言是:hello,world!win32匯編小程序。

bsp; // style of message box

)

;所以會有我們的程序段:

push MB_OK

lea eax,szCaption

push eax

lea eax,szText

push eax

push NULL

call messageboxa

看看上面的程序,不難想到,假如在寫程序時,少往堆棧裏壓入壹個數據,那將是壹個致命的錯誤。能不能將這種檢查參數個數是否匹配的工作交給計算機來完成呢?這是可以的,INVOKE指令可以幫助我們完成這樣的工作。假如妳的參數個數不正確,連接器將給出錯誤提示。所以,極力建議妳使用invoke代替call來調用子程序,當然,這不是絕對的。使用invoke上面的指令就可簡寫成下面的樣子,看起來簡煉多啦,查錯也方便啦!

invoke messageboxa, NULL,addr szText,addr szCaption,MB_OK

另外,像NULL,MB_OK都是壹些常量,這樣的常量有很多,還有很多的結構,如果在我們的程序中壹開始都寫這麽多的東西,可能壹下子就把妳嚇怕啦,也容易出錯,更不便於看程序的主要部分。hutch整理的Windows.inc包含了WIN32編程所需要的常量和結構體的定義,我們可簡單的用壹個include指令將這些常量和結構的定義插入到我們的文件中:

include d:\masm32\include\Windows.inc

但是Windows.inc中並不包含函數原型的聲明,還要從其他的頭文件中得到函數原型的聲明,比如:messageboxa的原型聲明在user32.inc文件中,exitprocess在kernel32.inc文件中。這些頭文件都放在 \masm32\include文件夾下。

還有,要用Windows.inc,必須使用option casemap:none,它的意思是告訴 MASM 要區分符號的大小寫,譬如:start和START是不壹樣的。否則,壹個小小的程序,可能會出成百上千的錯誤呀!

其他的,就不再細說啦,到此,上面的程序可重新修改如下:

-----------------------------------------------------------------

;最終的結果

.386 ;表示要用到386指令

.model flat,stdcall ;32位程序,要用flat啦!;stadcall,標準調用

option casemap:none ;區別大小寫

include Windows.inc ;包括常量及結構定義

include kernel32.inc ;函數原型聲明

include user32.inc

includelib kernel32.lib ;用到的引入庫

includelib user32.lib

.data;數據區,定義2個字符串

szText db "Hello, world!",0

szCaption db "Win32Asm",0

.code ;代碼開始執行處

start:

invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK

;調用MessageBoxAPI函數

invoke ExitProcess,NULL ;程序退出

end start;結束

------------------------------------

編譯鏈接:

ml /c /coff /I d:\masm7\include 3.asm ;註意開關符識別大小寫

link /subsystem:Windows /libpath:d:\masm7\lib 3.obj

/I d:\masm7\include 表示*.inc文件的位置,也可設置環境變量Set include=d:\masm7\include來簡化操作,也可在程序中明確指出*.inc的位置。

前面講的都是用兩條指令來完成編譯鏈接,實際上用壹條指令也可完成,如下:

ml /coff /I d:\masm7\include 3.asm /link /subsystem:Windows /libpath:lib

若*.inc及引入庫在源程序中都明確指出其位置,則可簡化為:

ml /coff 3.asm /link /subsystem:

  • 上一篇:家鄉特產網絡營銷策劃
  • 下一篇:怎麽樣完成壹個活動體系的策劃
  • copyright 2024編程學習大全網