ikj78i 發表於 2024-11-19 08:23:59

簡單的Windows主控臺程式

本帖最後由 ikj78i 於 2024-11-19 08:54 編輯

編寫視窗程式比較麻煩,主控臺程式比較簡單,底下就是一個很簡單的主控臺程式,叫HELLO。
HELLO會在「命令提示字元」顯示「請輸入姓名:」,等使用者輸入名字之後,例如使用者輸入
「張三」,HELLO會顯示「張三,你好。」.586
.model  flat,stdcall
option  casemap:none
include    c:\masm32\include\windows.inc
include    c:\masm32\include\kernel32.inc
include    c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
;*******************************************************************************
.DATA
hOut    DD      ?
hIn     DD      ?
dOut    DD      ?
dIn     DD      ?
szHello DB      ",你好。",0
szHint  DB      "請輸入姓名:",0
szName  DB      10 DUP (0)
        DB      SIZEOF szHello DUP (0)
;*******************************************************************************
.CODE
;-------------------------------------------------------------------------------
main    PROC
  ;取得「標準輸出裝置代碼」,並存於hOut變數內。主控臺程式的輸出與輸入必須獲得「標準
  ;輸出裝置代碼」與「標準輸入裝置代碼」。簡單的說,標準輸出裝置其實就是螢幕;標準輸
  ;入裝置代碼,其實就是鍵盤。取得它們的代碼之後,才能對螢幕、鍵盤進行輸出、輸入
        invoke  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hOut,eax
  ;取得「標準輸入裝置代碼」,並存於hOut變數內。
        invoke  GetStdHandle,STD_INPUT_HANDLE
        mov     hIn,eax
  ;在螢幕上顯示「請輸入姓名:」。對螢幕輸出文字需呼叫WriteConsole。
  ;第一個參數是標準輸出裝置代碼
  ;第二個參數是輸出文字的位址所在,並不是文字本身,用OFFSET可以取得變數的位址,所以
  ;   OFFSET szHint就是取得szHint字串變數的位址。
  ;第三個參數是要顯示的字串長度,用SIZEOF可以取得字串長度。
  ;第四個參數是位址,此位址將存放WriteConsole實際輸出多少位元組
  ;第五個參數是系統保留給將來擴充所需,應設為0
        invoke  WriteConsole,hOut,OFFSET szHint,SIZEOF szHint,OFFSET dOut,0
  ;讀取使用者用鍵盤輸入的文字。呼叫ReadConsole可讀取鍵盤輸入的文字,它的五個參數與
  ;WriteConsole很相似。要注意的是ReadConsole會對所讀取的文字之後自動加上兩個數值,
  ;13及10,這兩個數值代表換行
        invoke  ReadConsole,hIn,OFFSET szName,SIZEOF szName,OFFSET dIn,0
  ;取得13、10的位址。szName的位址加上實際輸入幾個位元組就是13、10之後的位址。假如
  ;szName在100的位址上,輸入John之後有4個位元組,再加上13,10,所以dIn=6:
  ;100 101 102 103 104 105 106
  ; J   o   h   n   13  10
        mov     edx,OFFSET szName-2     ;EDX=100-2=98
        add     edx,dIn                 ;EDX+dIn=104
        mov     BYTE PTR ,0        ;把換行符號變為0
  ;要連接兩個字串,一般呼叫lstrcat,它可以把兩個字串以零為結尾連接起來,呼叫方式如下:
  ;  invoke lstrcat,psz1,psz2
  ;psz1、psz2是字串位址,不是字串名稱。p代表指標也就是位址,s是字串,z代表零。lstrcat
  ;會把psz2所指位址上的字串複製到psz1位址上的字串之後,psz1上的字串結尾的0會被除去
  ;不可使用「invoke lstrcat,szName,szHello」,這樣會把szName、szHello的內容傳給lstrcat
  ;,但lstrcat要的不是字串內容而是位址。取得字串的位址,需用OFFSET。
        invoke  lstrcat,OFFSET szName,OFFSET szHello
  ;最後呼叫WriteConsole,印出lstrcat連接後的字串,字串長度應等於使用者輸入的名字長度加
  ;上szHello的長度。使用者輸入的名字長度已經在dIn內,但須扣除13、10兩個位元組。szHello
  ;的長度可用SIZEOF szHello求得,但須扣除結尾的0。所以下式須減去3  
        add     dIn,SIZEOF szHello-3
        invoke  WriteConsole,hOut,OFFSET szName,dIn,OFFSET dOut,0
  ;Windows應用程式要結束時,呼叫ExitProcess,0是傳回值,傳給Windows
        invoke  ExitProcess,0
main    ENDP
;*******************************************************************************
END     main
把上述程式存入E:\TEMP\HELLO.ASM,開啟「命令提示字元」,輸入下面指令:
path c:\masm32\bin;%path%
ml /coff hello.asm /link /subsystem:console
就能看到組譯成功,輸入hello就能執行hello.exe,結果如下圖(張三是使用者輸入的名字):



頁: [1]
查看完整版本: 簡單的Windows主控臺程式