2

我正在尝试使用 VS 2010 附带的 ML 和 LINK 在 Windows 上编译一个 hello world。

.MODEL FLAT
.STACK 4096
.data
msg db "Hello World!",0
.code
INCLUDELIB MSVCRT
EXTRN printf:NEAR
EXTRN exit:NEAR
PUBLIC _main
_main PROC
mov eax, offset msg
push eax
call printf
mov eax,0
push eax
call exit
_main ENDP
END _main

我不断收到链接器错误,说 printf 和 exit 是未解析的外部符号。我有一些问题。

  1. 与 ML 和 LINK 一起使用来编译和解决错误消息的命令行选项是什么。
  2. 是否有另一种方法可以使用汇编代码将文本输出显示到屏幕上,而不是调用诸如 printf 之类的 c 运行时函数?
4

1 回答 1

4
  1. 您需要为 C 函数使用带下划线的名称,因为这是编译器在汇编级别发出它们的方式。
  2. 您应该在调用 printf 和其他 CRT 函数后清理堆栈,因为它们使用 cdecl 调用约定(调用者堆栈清理)。严格来说,您也应该在 _exit 之后执行此操作,但这并不重要,因为它永远不会返回。
  3. 要使用 CRT 函数,您必须初始化 CRT。您可以在文件中检查它是如何完成的VC\crt\src\crt0.c

这是一个对我有用的最小文件(我使用静态库,因为我有 VS2008 并且不想摆弄清单以使其与 DLL 一起使用)。

.386
.MODEL FLAT
.STACK 4096
.data
  msg db "Hello World!",0
.code
INCLUDELIB LIBCMT
EXTRN _printf:NEAR
EXTRN _exit:NEAR
EXTRN __heap_init:NEAR
EXTRN __mtinit:NEAR
EXTRN __ioinit:NEAR
PUBLIC _main
_main PROC
  push 1
  call __heap_init
  add esp, 4
  push 1
  call __mtinit
  add esp, 4
  call __ioinit
  mov eax, offset msg
  push eax
  call _printf
  pop ecx
  mov eax,0
  push eax
  call _exit
_main ENDP
END _main

对于 MSVCRT,初始化是不同的,例如你需要调用 set_app_type

要不依赖 CRT,您必须使用 OS API。在 Win32 的情况下,它将是 Win32 函数,例如 WriteFile(文件句柄使用 GetStdHandle(STD_OUTPUT_HANDLE))。在此处查看一些示例。

于 2010-10-14T10:03:25.803 回答