Hello World 在 Windows 程序集中使用 nasm

Posted

技术标签:

【中文标题】Hello World 在 Windows 程序集中使用 nasm【英文标题】:Hello world using nasm in windows assembly 【发布时间】:2012-09-16 11:55:20 【问题描述】:

我正在使用nasm 编译以下程序集。但是代码在 Windows 下的控制台中崩溃了。

C:\>nasm -f win32 test.asm -o test.o

C:\>ld test.o -o test.exe

section .data
  msg   db    'Hello world!', 0AH
  len   equ   $-msg

section .text
  global _WinMain@16

_WinMain@16:
  mov   edx, len
  mov   ecx, msg
  mov   ebx, 1
  mov   eax, 4
  int   80h

  mov   ebx, 0
  mov   eax, 1
  int   80h

据此post。 main函数在Windows下不可用,必须替换为WinMain

因此,如果您的入口点是_startmain,则应将其更改为_WinMain@16,并将程序末尾的ret 更改为ret 16

我的工作示例:

section .text       
 global _WinMain@16       

_WinMain@16:       
 mov eax, 0       
 ret 16 

【问题讨论】:

请编辑标题,以便对未来的访问者有用。否则它可能会因为过于本地化而被关闭。 @RaymondChen 是什么? 【参考方案1】:

最大的问题是你试图在 Windows 上使用 Linux 中断! int 80 不能在 Windows 上工作。

我们使用的是 Assembly,因此您的入口点可以是您想要的任何标签。 ld 寻找的标准入口点是 _start,如果你想使用另一个标签,你需要用 -e 选项告诉 ld 所以如果你想让你的开始标签是主要的,那么你需要

global main
ld -e main test.o -o test.exe

如果您打算在 Windows 上使用 NASM,我建议您使用 GoLink 作为您的链接器。 这是一个简单的 Windows 控制台应用程序:

STD_OUTPUT_HANDLE   equ -11
NULL                equ 0

global GobleyGook
extern ExitProcess, GetStdHandle, WriteConsoleA

section .data
msg                 db "Hello World!", 13, 10, 0
msg.len             equ $ - msg

section .bss
dummy               resd 1

section .text
GobleyGook:
    push    STD_OUTPUT_HANDLE
    call    GetStdHandle

    push    NULL
    push    dummy
    push    msg.len
    push    msg
    push    eax
    call    WriteConsoleA 

    push    NULL
    call    ExitProcess

制作文件:

hello: hello.obj
    GoLink.exe  /console /entry GobleyGook hello.obj kernel32.dll  

hello.obj: hello.asm
    nasm -f win32 hello.asm -o hello.obj

【讨论】:

@Gunner 谢谢。但是有一个问题 - 您推荐 GoLink 而不是其他链接器的原因是什么? @Boris 我猜是个人喜好。发现它比 Windows 上的其他链接器更容易使用。 消息字符串末尾的零字节不应存在。 WriteConsoleA 不需要它,它使用提供的字符串长度,实际上最终被写入控制台,当我尝试它时显​​示为空格。删除零字节解决了问题。 不是call ExitProcesscall WriteConsoleA ,Windows 有没有相当于简单地做syscall 对于 64 位 Windows 是否有类似的功能?如果我尝试做-f win64,我会在push eax 行得到error: instruction not supported in 64-bit mode【参考方案2】:

虽然,同样的程序可能会像魅力一样在 Linux 上的 WINE 中运行。 :)

WINE 不会阻止在 Windows PE 二进制文件中使用 Linux 系统调用;机器指令本机运行,WINE 仅提供 DLL 函数。

【讨论】:

@JayBlanchard 这是一个答案,因为它指向操作系统,程序将在其中正常工作,而问题中没有提到崩溃。 哦,你的意思是在 Linux 机器上,系统调用本地运行,WINE 与它们无关。起初我以为你的意思是 WINE 是双向的,它可以在 Windows 机器上模拟 Linux int 0x80 ABI! @PeterCordes WINE 仅在 Unix 机器上运行并模拟 Windows API。但只要程序不是在 VM 中运行,而是在 Linux 操作系统的内存中本地运行,它们就可以使用 int 0x80 系统调用。当然,这样的程序会在真正的 Windows 上崩溃。但程序只能在 Linux 上运行时检测操作系统并使用此类调用。 是的,我都知道。我想说你的回答误导了我一分钟。请注意,WINE 可以在一些非 Linux 操作系统(*BSD,包括 OS X)上运行,在这些操作系统中本地 Linux 系统调用不起作用。

以上是关于Hello World 在 Windows 程序集中使用 nasm的主要内容,如果未能解决你的问题,请参考以下文章

团体程序设计天梯赛-练习集L1-001 Hello World (5 分)

在 Windows 的 Eclipse C++ 中运行 Hello World 应用程序

如何在 Windows 中运行基本的“Hello World”GLSL 程序? [关闭]

Windows对应的"Hello,world"程序

windows学习记录----hello world与窗口创建

超详细SDK Hello World