首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Windows 主控台程式開發:GetStdHandle 與 WriteFile 實現文字輸出,兼談 MASM32 StdOut 巨集

     編輯:組合語言

什麼是主控台程式?

類似 DOS 年代的文字模式程式:ping, ipconfig, ftp, cmd.exe 本身。無圖形介面,標準輸入/輸出/錯誤重導向 (>, <, |) 完整支援。適合批次處理、工具程式、伺服器後台服務。

核心 API:GetStdHandle + WriteFile

Windows 繼承 DOS「檔案代碼」概念,標準裝置預設代碼:

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 補充

常數值對應裝置DOS 代碼
STD_INPUT_HANDLE-10標準輸入 (鍵盤/管道/檔案)0000H (stdin)
STD_OUTPUT_HANDLE-11標準輸出 (螢幕/管道/檔案)0001H (stdout)
STD_ERROR_HANDLE-12標準錯誤輸出0002H (stderr)
API功能
AllocConsole為 GUI 程式動態建立主控台視窗
FreeConsole與主控台分離
SetConsoleTitle設定視窗標題
SetConsoleTextAttribute設定文字顏色/屬性
GetConsoleScreenBufferInfo取得緩衝區大小、游標位置、屬性
SetConsoleCursorPosition移動游標
ReadConsoleInput低層輸入事件讀取 (鍵盤/滑鼠/視窗事件)

除錯技巧:主控台視窗自動關閉問題

直接雙擊 .exe 執行,程式跑完視窗瞬間關閉看不見結果。

  • 在 CMD 視窗中執行。
  • 程式碼結束前加 invoke StdOut, addr promptPause + invoke ReadFile... 等待按鍵。
  • 連結器選項 /subsystem:console 配合 IDE「執行後暫停」功能。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved