如何在Windows下编译hello world?
我想在Windows下编写一些基本的东西,我正在使用NASM,但是我什么都不能工作。如何在Windows下编译hello world?
如何编写和编译的Hello World无C函数在Windows的帮助?
; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is a Win32 console program that writes "Hello, World" on one line and
; then exits. It needs to be linked with a C library.
; ----------------------------------------------------------------------------
global _main
extern _printf
section .text
_main:
push message
call _printf
add esp, 4
ret
message:
db 'Hello, World', 10, 0
然后运行
nasm -fwin32 helloworld.asm
gcc helloworld.obj
a
还有The Clueless Newbies Guide to Hello World in Nasm没有使用C++类库。然后代码将如下所示。
org 100h
mov dx,msg
mov ah,9
int 21h
mov ah,4Ch
int 21h
msg db 'Hello, World!',0Dh,0Ah,'$'
祝你好运。
这个问题明确提到“不使用C库” – 2009-06-21 10:24:40
没有可靠的方法来做到这一点,而没有在某个时候调用C函数。除非通过“C函数”来表示“标准C函数”。 – 2009-06-21 12:36:40
这个例子显示了如何直接转到Windows API和C标准库中没有链接。
global _main
extern [email protected]
extern [email protected]
extern [email protected]
section .text
_main:
; DWORD bytes;
mov ebp, esp
sub esp, 4
; hStdOut = GetstdHandle(STD_OUTPUT_HANDLE)
push -11
call [email protected]
mov ebx, eax
; WriteFile(hstdOut, message, length(message), &bytes, 0);
push 0
lea eax, [ebp-4]
push eax
push (message_end - message)
push message
push ebx
call [email protected]
; ExitProcess(0)
push 0
call [email protected]
; never here
hlt
message:
db 'Hello, World', 10
message_end:
进行编译,你需要NASM和LINK.EXE(从Visual Studio标准版)
nasm -fwin32 hello.asm link /subsystem:console /nodefaultlib /entry:main hello.obj
除非你打电话一些功能,这是不是在所有琐碎。 (而且,严肃地说,在调用printf和调用win32 api函数之间没有真正的复杂性。)
即使DOS int 21h实际上只是一个函数调用,即使它是一个不同的API。
如果你想这样做没有你需要跟直接视频硬件的帮助,可能写“世界,你好”的字母的位图转换为一个帧缓冲。即使这样,显卡也在将这些内存值转换成VGA/DVI信号。
需要注意的是,真的,没有这东西一路下跌到硬件在ASM比C.任何一个更有趣的“Hello World”程序归结为一个函数调用。 ASM的一个好处就是你可以使用任何你想要的ABI都相当简单;你只需要知道ABI是什么。
这些都是使用Windows API调用Win32和Win64的例子。他们是为了MASM而不是NASM,但是看看他们。您可以在this文章中找到更多详细信息。
;---ASM Hello World Win32 MessageBox
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
title db 'Win32', 0
msg db 'Hello World', 0
.code
Main:
push 0 ; uType = MB_OK
push offset title ; LPCSTR lpCaption
push offset msg ; LPCSTR lpText
push 0 ; hWnd = HWND_DESKTOP
call MessageBoxA
push eax ; uExitCode = MessageBox(...)
call ExitProcess
End Main
;---ASM Hello World Win64 MessageBox
extrn MessageBoxA: PROC
extrn ExitProcess: PROC
.data
title db 'Win64', 0
msg db 'Hello World!', 0
.code
main proc
sub rsp, 28h
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, msg ; LPCSTR lpText
lea r8, title ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA
add rsp, 28h
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
main endp
End
为了组装和这些使用MASM,使用该32位的可执行链接:
ml.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main
或此对64位的可执行:
ml64.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main
如果你想使用NASM和Visual Studio的链接器(link.exe)与anderstornvig的Hello World例子,你将不得不手动链接包含printf()函数的C Runtime Libary。
nasm -fwin32 helloworld.asm
link.exe helloworld.obj libcmt.lib
希望这可以帮助别人。
Flat Assembler不需要额外的链接器。这使得汇编编程变得非常简单。它也适用于Linux。
这是从FASM例子hello.asm
:
include 'win32ax.inc'
.code
start:
invoke MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK
invoke ExitProcess,0
.end start
FASM创建一个可执行文件:
>fasm hello.asm flat assembler version 1.70.03 (1048575 kilobytes memory) 4 passes, 1536 bytes.
这是IDA程序:
你可以看到三个cal ls:,MessageBox
和ExitProcess
。
为了得到一个.exe与NASM'compiler和Visual Studio的链接此代码工作正常:
global WinMain
extern ExitProcess ; external functions in system libraries
extern MessageBoxA
section .data
title: db 'Win64', 0
msg: db 'Hello world!', 0
section .text
WinMain:
sub rsp, 28h
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx,[msg] ; LPCSTR lpText
lea r8,[title] ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA
add rsp, 28h
mov ecx,eax
call ExitProcess
hlt ; never here
如果此代码保存在如“test64.asm”,然后编译:
nasm -f win64 test64.asm
生产 “test64.obj” 然后从命令提示符链接:
path_to_link\link.exe test64.obj /subsystem:windows /entry:WinMain /libpath:path_to_libs /nodefaultlib kernel32.lib user32.lib /largeaddressaware:no
其中path_to_link可能是C:\ Program Files文件(x86)\ Microsoft Visual Studio 10.0 \ VC \ bin或您的计算机中的任何地方是link.exe程序, path_to_libs可能是C:\ Program Files(x86)\ Windows Kits \ 8.1 \ Lib \ winv6。 3 \ um \ x64或任何地方你的库(在这种情况下,kernel32.lib和user32.lib都在同一个地方,否则为你需要的每个路径使用一个选项)和/largeaddressaware:没有选项是必要的以避免链接器抱怨地址长(在这种情况下为user32.lib)。 另外,因为它是在这里完成的,所以如果从命令提示符调用Visual的链接器,则有必要先设置环境(运行一次vcvarsall.bat和/或参见MS C++ 2010 and mspdb100.dll)。
最好的例子是fasm,因为fasm不使用链接器,它通过另一个不透明的复杂层隐藏了Windows编程的复杂性。 如果你满足于一个写入gui窗口的程序,那么在fasm的示例目录中有一个例子。
如果你想要一个控制台程序,它允许标准输入和标准输出的重定向,这也是可能的。 有一个(helas高度不平凡的)示例程序可用,它不使用gui,并且严格地与控制台一起工作,这就是fasm本身。这可以根据要素进行细化。 (我已经编写了第四个编译器,这是另一个非gui的例子,但它也是非平凡的)。
这样的程序有以下命令来生成正确的可执行头,通常由链接器完成。
FORMAT PE CONSOLE
称为“的.idata” A部分包含一个表,启动时的运行时间地址的功能,这几个名字中会有帮助的窗口。它还包含对Windows操作系统KERNEL.DLL的引用。
section '.idata' import data readable writeable
...
您的程序在'.text'部分。如果您声明该部分可读写和可执行文件,则它是您需要的唯一部分。
section '.text' code executable readable writable
您可以调用您在.idata部分声明的所有设施。对于控制台程序,您需要_GetStdHandle为标准输入和标准输出(使用符号名称,如STD_INPUT_HANDLE,它可以在包含文件win32a.inc中找到)找到他的文件描述符。 一旦你有文件描述符,你可以做WriteFile和ReadFile。 在kernel32文档中描述了所有函数。您可能知道这一点,或者您不会尝试汇编编程。
总结:有一张带有asci名字的表格,与windows操作系统相连。 在启动过程中,它将转换为可调用地址表,您可以在程序中使用该表。
还可以查看Steve Gibson的[Small Is Beautiful](http://www.grc.com/smgassembly.htm)Windows程序集入门工具包。 – Jeremy 2010-04-16 14:51:39
不使用c库是一个有点奇怪的约束。必须在MS-Windows操作系统中调用一些库。可能是kernel32.dll。微软是用c还是Pascal写的,似乎没有关系。这是否意味着只能调用OS提供的函数,而在Unix类型的系统中又称为系统调用? – 2017-02-16 11:16:43
对于C库,我假设他或她的意思是不使用像GCC或MSVC那样的C运行库。当然,他或她将不得不使用一些标准的Windows DLL,比如kernel32.dll。 – 2017-05-13 19:23:55