冰楓論壇

標題: 簡單的Windows主控臺程式 [打印本頁]

作者: ikj78i    時間: 7 小時前
標題: 簡單的Windows主控臺程式
本帖最後由 ikj78i 於 2024-11-19 08:54 編輯

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



hello.png (8.51 KB, 下載次數: 2)

組譯HELLO並執行

組譯HELLO並執行






歡迎光臨 冰楓論壇 (https://bingfong.com/) Powered by 冰楓