使用WIN32函数在MASM中输出Hello World

11

目录

  1. 介绍
  2. 代码
  3. 组装和运行
  4. 杂项
  5. 问题

1. 介绍

这不是一个问题(尽管底部有一个),而是为StackOverflow上的人们提供的HelloWorld应用程序,以进行实验。

当我第一次尝试使用MASM编程时,我试图找到一个使用WIN32 API调用的工作HelloWorld应用程序(因此不链接到C库),但找不到一个(在MASM语法中)。所以现在我已经有了一些经验,并为其他想要学习汇编语言的人编写了一个应用程序。

2. 代码

.386 ; 386 Processor Instruction Set

.model flat,stdcall ; Flat memory model and stdcall method

option casemap:none ; Case Sensitive

;Libaries and Include files used in this project

; Windows.inc defines alias (such as NULL and STD_OUTPUT_HANDLE in this code
include \masm32\include\windows.inc 

; Functions that we use (GetStdHandle, WriteConsole, and ExitProcess)
; Listing of all available functions in kernel32.lib
include \masm32\include\kernel32.inc 
; Actuall byte code available of the functions
includelib \masm32\lib\kernel32.lib  

.data
; Labels that with the allocated data (in this case Hello World!...) that are aliases to memory.
output db "Hello World!", 0ah, 0h; This String Hello World! and then a the newline character \n (0ah) and then the null character 0h

.code 
start: 

; --------------------------------------------------------------------------------------------------------------------------------------
; Retrieves that handle to the output console
;
; ====Arguments===
;
; STD_OUTPUT_HANDLE - alias for -11 and indicates that we want the handle to 
;                     write to console output
;
invoke GetStdHandle, STD_OUTPUT_HANDLE
; --------------------------------------------------------------------------------------------------------------------------------------

; --------------------------------------------------------------------------------------------------------------------------------------
; Writes the text in output (.data section) to the console
;
; ====Arguments===
;
; eax - the handle to the console buffer
;
; addr output - pass by reference the text of output (Hello World!)
;
; sizeof output - the size of the string so that the WriteConsole knows when to 
;                 stop (doesn't support NULL terminated strings I guess);
;
; ebx - secondary "return" value that contains the number of bytes written (eax
;       is used for an error code)
;
; NULL - this is reserved and MSDN says just to pass NULL
;
; MSDN Link: http://msdn.microsoft.com/en-us/library/ms687401(v=VS.85).aspx
;
invoke WriteConsole, eax, addr output, sizeof output, ebx, NULL
; --------------------------------------------------------------------------------------------------------------------------------------

; --------------------------------------------------------------------------------------------------------------------------------------
; Exits the program with return code 0 (default one that usually is used to 
; indicate that the program did not error
;
; ====Arguments===
;
; 0 - the exit code
;
; MSDN Link: http://msdn.microsoft.com/en-us/library/ms682658(VS.85).aspx
;
invoke ExitProcess, 0
; --------------------------------------------------------------------------------------------------------------------------------------

end start 

3. 组装和运行

我假设您已经在C:\MASM32目录下安装了MASM32。

  • 如果您没有安装MASM,请访问http://masm32.com/install.htm并按照说明操作。

  • 如果MASM32安装在不同的目录中,请相应更改说明内容。

    1. 通过单击桌面快捷方式或者在C:\MASM32\中找到qeditor.exe并双击打开MASM32编辑器(QEditor)。

    2. 复制代码段中的代码(只复制灰色背景的文本)并粘贴到MASM32编辑器(QEditor)中,然后保存。

    3. 保存代码后,单击“Project”菜单,选择“Console Assemble and Link”(而不是“Assemble and Link”(见Miscellaneous))。

    4. 转到“开始”菜单,单击“运行”,然后输入cmd并按回车键,一个黑色的带有灰色文本的框应该出现。

    5. 使用资源管理器导航到你在步骤3中保存代码的位置。现在应该有一个与源文件(步骤3)同名但后缀为exe的文件。将exe文件从资源管理器窗口拖放到cmd框(步骤4的黑色框)中。

    6. 选择黑色框并按回车键,应该会出现文本“Hello World!”。

4. 其他

为什么我必须单击“Console Assemble and Run”,而不是在“Project”菜单中直接单击“Assemble and Run”?

您必须单击“Console Assemble and Run”是因为有两种类型的应用程序,一种是GUI,另一种是基于文本的控制台(DOS)应用程序。Hello Would应用程序是一种基于文本的应用程序,因此在组装时必须具备控制台应用程序的设置,而不是GUI。

请参见此链接下“备注”第三段中的更详细的说明。

5. 问题

好了,现在问题来了,这段代码中是否存在任何问题、错误或一般性问题,或者您有任何建议?

3个回答

7
这个程序很好。它确实是Win32的“Hello World”版本。但请记住它是一个控制台程序。在Win32中,你将主要处理Windows、对话框,与控制台的交互很少(如果你想专门处理控制台,那就另当别论)。
如果你想学习Win32汇编语言,我强烈建议你看Iczelion教程。
以下是他教程的“Hello World”示例:

http://win32assembly.online.fr/tut2.html


我正在查看它们,它们确实是一套不错的教程,但几乎所有编程教程都从控制台和命令行应用程序开始。 - Zimm3r
我同意,但在Win32编程的情况下,这是一个例外,因为你学习的不是语言而是Win32平台。 - Madhur Ahuja

3

这个示例代码更简单易懂。

.386
.model flat, stdcall
option casemap: none

include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib

.data
    szCaption   db  'Hello', 0
    szText      db  'Hello, World!', 0

.code
    start:
            invoke MessageBox, NULL, offset szText, offset szCaption, MB_OK
            invoke ExitProcess, NULL        
    end start

哦,这个代码 a) 相当老了 b) 没有做到它应该做的事情!c) 对于初学者来说没有任何解释! - Zimm3r
2
这并不是老旧的代码... 它可以编译... 并且使用Win32 API打印出一个Hello World消息框... 使用invoke比推送参数更快捷。 - justyy
嗯,这个问题已经超过一年了,它已经比较老了... 另外,这是为了展示如何在不使用invoke的情况下完成它,因为invoke会为你做很多事情。 - Zimm3r

0

StdOut 是一个控制台函数

你可以使用 MessageBox 函数...

.model small,pascal,nearstack
.386
?WINPROLOGUE=1
include win.inc
includelib libw.lib
extern __astart:proc

.data
text sbyte "Hello f*** World!",0
title sbyte "Win",0

.code
WinMain    PROC, hInstance:HANDLE, hPrevInstance:HANDLE, lpszCmdLine:LPSTR, nCmdShow,WORD
  LOCAL msg:MSG

 invoke MessageBox, NULL, addr text, addr title, 0
 invoke PostQuitMessage,0

 .while TRUE
     invoke GetMessage,addr msg,NULL,0,0
     .break .if (ax == 0)
     invoke TranslateMessage,addr msg
     invoke DispatchMessage,addr msg
 .endw
WinMain    ENDP
END        __astart

这是经典的hello world,就像在C语言中使用printf一样。 - Zimm3r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接