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
。
因此,如果您的入口点是_start
或main
,则应将其更改为_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 ExitProcess
和call 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 机器上模拟 Linuxint 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 程序? [关闭]