盡管是學習 Win32 匯編, 也應該先從控制台程序起步; 因為一個基本的 Windows 窗口都需要不少代碼.
為了查看測試結果, 首先需要知道輸出呈現的辦法, 目前我嘗試出了 3 種辦法:
1、使用 MASM 提供的 StdOut 函數;
2、使用系統 API:
3、使用微軟 C 標准庫 msvcrt.dll 中的 printf 函數.
使用 MASM 的 StdOut 函數:
; Test3_1.asm
; 測試代碼前應先建立一個控制台工程: 文件 -> 新建工程 -> Console App ...
.386
.model flat, stdcall
include masm32.inc
include kernel32.inc
includelib masm32.lib
includelib kernel32.lib
.data
szText db "Hello World!", 0
.code
start:
invoke StdOut, addr szText
ret ;ret 是用於子程序返回的指令, 這裡用它代替 ExitProcess 只是為了簡單(但不知是否合適)
end start
使用系統 API 函數:
; Test3_2.asm
.386
.model flat, stdcall
include Windows.inc
include kernel32.inc
includelib kernel32.lib
.data
szText db 'Hello World!', 0
;定義兩個 DWord 類型的變量, 分別是用於輸出句柄和字符串長度
.data?
hOut dd ?
len dd ?
.code
start:
; 獲取控制台輸出設備的句柄, 其返回值會放在 eax 寄存器
invoke GetStdHandle, STD_OUTPUT_HANDLE
; 把獲取到的句柄給變量 hOut
mov hOut, eax
; 通過 lstrlen 函數獲取字符串長度, 返回值在 eax
invoke lstrlen, addr szText
; 把獲取到的字符串長度給變量 len
mov len, eax
; 輸出到控制台, 參數分別是: 句柄、字符串地址、字符串長度; 後面是兩個指針暫用不到
invoke WriteFile, hOut, addr szText, len, NULL, NULL
ret
end start
; 另外前面用到的 StdOut 也基本就是這樣實現的, 源碼在: masm32\m32lib\stdout.asm
使用微軟 C 標准庫中的 printf 函數; msvscrt.inc 把它聲明做 crt_printf
; Test3_3.asm
.386
.model flat, stdcall
include msvcrt.inc
includelib msvcrt.lib
.data
szText db 'Hello World!', 0
.code
start:
invoke crt_printf, addr szText
ret
end start
三種方法相比之下, 應推薦使用 C 函數 crt_printf; 因為它可以方便輸出更多數據類型, 如:
; Test3_4.asm
.386
.model flat, stdcall
include msvcrt.inc
includelib msvcrt.lib
.data
szFmt db 'EAX=%d; ECX=%d; EDX=%d', 0
.code
start:
mov eax, 11
mov ecx, 22
mov edx, 33
invoke crt_printf, addr szFmt, eax, ecx, edx
ret
end start