| 常數 | 值 | 對應裝置 | DOS 代碼 |
STD_INPUT_HANDLE | -10 | 標準輸入 (鍵盤/管道/檔案) | 0000H (stdin) |
STD_OUTPUT_HANDLE | -11 | 標準輸出 (螢幕/管道/檔案) | 0001H (stdout) |
STD_ERROR_HANDLE | -12 | 標準錯誤輸出 | 0002H (stderr) |
API 定義
HANDLE GetStdHandle(DWORD nStdHandle); ; 返回裝置代碼
BOOL WriteFile(
HANDLE hFile, ; GetStdHandle 返回值
LPCVOID lpBuffer, ; 要寫入的資料指標
DWORD nNumberOfBytesToWrite, ; 位元組數
LPDWORD lpNumberOfBytesWritten, ; 實際寫入位元組數接收變數指標
LPOVERLAPPED lpOverlapped ; 非同步 I/O 結構,同步用 NULL
);
完整範例:輸出 "How are you !"
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
.data
mess db 'How are you !',0
.data?
StdOut dd ? ; 標準輸出代碼
CharOut dd ? ; 實際寫入位元組數
.code
start:
; 1. 取得標準輸出代碼
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov StdOut, eax
; 2. 計算字串長度 (不含結束符)
lea eax, mess
invoke lstrlen, eax
; eax = 長度
; 3. 寫入主控台
lea ecx, CharOut
invoke WriteFile, StdOut, addr mess, eax, ecx, NULL
invoke ExitProcess, NULL
end start
關鍵編譯選項:/subsystem:console
**必須**指定子系統為 Console,否則雖能編譯連結,執行時無主控台視窗,GetStdHandle 返回 INVALID_HANDLE_VALUE 或寫入無效果。
; MASM32 命令列編譯
ml /coff /I include 4.asm /link /subsystem:console /libpath:lib
; 或在原始碼加入連結器指示 (MASM 6.15+)
; option dllimport: ... 但最簡單是用批次檔/IDE 設定
編譯輸出參考:
D:\MASM7>ml /coff /I include 4.asm /link /subsystem:console /libpath:lib
Microsoft (R) Macro Assembler Version 6.14.8444
...
Microsoft (R) Incremental Linker Version 5.12.8078
/subsystem:console /libpath:lib
"4.obj"
"/OUT:4.exe"
D:\MASM7>4
How are you !
D:\MASM7>
MASM32 封裝巨集:StdOut - 一行搞定
masm32.inc/masm32.lib 提供高層封裝:
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include masm32.inc
includelib kernel32.lib
includelib masm32.lib
.data
mess db 'How are you !',0
.code
start:
invoke StdOut, addr mess ; 內部自動 GetStdHandle + lstrlen + WriteFile
invoke ExitProcess, NULL
end start
StdOut 實作原理 (masm32 原始碼):
StdOut proc lpszString:DWORD
invoke GetStdHandle, STD_OUTPUT_HANDLE
invoke lstrlen, lpszString
invoke WriteFile, eax, lpszString, eax, NULL, NULL
ret
StdOut endp
進階:讀取標準輸入 (StdIn)
invoke GetStdHandle, STD_INPUT_HANDLE
mov hStdIn, eax
invoke ReadFile, hStdIn, addr InputBuffer, 256, addr BytesRead, NULL
; 處理 InputBuffer...
主控台專屬 API 補充
| API | 功能 |
AllocConsole | 為 GUI 程式動態建立主控台視窗 |
FreeConsole | 與主控台分離 |
SetConsoleTitle | 設定視窗標題 |
SetConsoleTextAttribute | 設定文字顏色/屬性 |
GetConsoleScreenBufferInfo | 取得緩衝區大小、游標位置、屬性 |
SetConsoleCursorPosition | 移動游標 |
ReadConsoleInput | 低層輸入事件讀取 (鍵盤/滑鼠/視窗事件) |
除錯技巧:主控台視窗自動關閉問題
直接雙擊 .exe 執行,程式跑完視窗瞬間關閉看不見結果。
- 在 CMD 視窗中執行。
- 程式碼結束前加
invoke StdOut, addr promptPause + invoke ReadFile... 等待按鍵。
- 連結器選項
/subsystem:console 配合 IDE「執行後暫停」功能。
- 上一篇文章: DLL 資源存取完全指南:LoadLibrary 取得模組代碼,輕鬆讀取位圖、圖示、選單、字串與對話框
- 下一篇文章: DOS EXE 檔案格式深度剖析:.model small、記憶體佈局與 DEBUG 實戰追蹤
Copyright ©
程式碼之家 All Rights Reserved