【问题标题】:Win32 Assembly - WriteFile() to console don't show outputWin32 程序集 - WriteFile() 到控制台不显示输出
【发布时间】:2016-10-12 16:37:56
【问题描述】:

我现在正在编写一些 Windows 本地程序集,使用 NASM 2.12.01 和 GCC 4.8.1 作为链接器。

但是,这个简单的 HelloWorld 程序编译和链接没有任何问题,但不会向控制台屏幕输出任何内容。

GetStdHandle 似乎没有将有效句柄返回到当前控制台,因此没有显示输出。

但问题可能是其他问题。

代码:

; Name:     hello.asm
; Assemble: nasm.exe -fwin32 hello.asm
; Link:     gcc -mwindows -o hello hello.obj -lkernel32 -lmsvcrt
; Run:      a.exe

BITS 32
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
extern __getch
extern _puts

SECTION .data
    str:    db `Hello world!\n`         ; C-like strings in NASM with backticks
    strlen  equ $-str
    pause:  db "Do you know where the ANY key is? :-)",0

SECTION .text
GLOBAL _main
_main:
; Stack frame for NumberOfBytesWritten
push ebp
sub esp, 4

; http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231.aspx
; HANDLE WINAPI GetStdHandle(
;   _In_  DWORD nStdHandle
; );
push -11
call _GetStdHandle@4

; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx
; BOOL WINAPI WriteFile(
;   _In_         HANDLE hFile,
;   _In_         LPCVOID lpBuffer,
;   _In_         DWORD nNumberOfBytesToWrite,
;   _Out_opt_    LPDWORD lpNumberOfBytesWritten,
;   _Inout_opt_  LPOVERLAPPED lpOverlapped
; );
push 0              ; lpOverlapped,
lea ebx, [ebp-4]    ; EBX: address of NumberOfBytesWritten
push ebx            ; lpNumberOfBytesWritten,
push strlen         ; nNumberOfBytesToWrite
push str            ; lpBuffer,
push eax            ; hFile (result from GetStdHandle
call _WriteFile@20

; msvcrt.dll (C library)
push pause
call _puts          ; http://msdn.microsoft.com/library/tf52y4t1.aspx
add esp, 4
call __getch        ; http://msdn.microsoft.com/library/078sfkak.aspx

; ExitProcess (0)
push 0
call _ExitProcess@4

【问题讨论】:

  • “但问题可能是其他问题。” - 如果只是为了停止猜测,为什么不实施错误处理?
  • @IInspectable 您将如何在 hello world ASM 程序中实现它?
  • 是否有 Windows 工具可以跟踪进程进行的所有系统调用?在 Linux/Unix 中,strace 非常适合调试这样的事情。 (见example output in this random blog post)。
  • 与您在任何其他 Windows 应用程序中执行此操作的方式相同。遵循书面合同并评估返回值。
  • @IInspectable:如果您只是在学习 asm,那么您更有可能在编写错误处理代码时通过破坏寄存器或不平衡堆栈来创建 更多 错误.我建议使用调试器或跟踪工具在单步执行时查看 API 调用返回值,而不是尝试在程序中编写代码来检查它们。您不能只在 asm 程序中插入调试打印而不可能引入新的错误。 (除非您有一个非常精细的宏来保存/恢复所有内容,包括标志)。

标签: winapi gcc assembly nasm kernel32


【解决方案1】:

为了生成控制台应用程序,您必须使用 GCC 的 -mconsole 选项。请参阅在线文档,section 3.18.55, x86 Windows Options。

您正在使用 -mwindows 创建一个 GUI 应用程序。 Windows 在启动 GUI 应用程序时不会创建控制台或设置标准句柄。

【讨论】:

  • 哇!这正是问题所在!根本不需要创建任何控制台句柄!
【解决方案2】:

您从未正确设置堆栈帧!

这不是正确的方法:

push ebp
sub esp, 4

你错过了什么吗?你的堆栈搞砸了!

序言应该是:

push ebp
  mov   ebp, esp
  sub   esp, 4 

对于尾声,只需将其反转即可。

【讨论】:

  • 不需要将基指针设置为任何特定值。这纯粹是一种方便,可以更轻松地访问本地人和参数。事实上,省略帧指针是任何高级语言编译器最常见​​的优化之一。很抱歉,但这并不能回答问题(我不知道谁对此投了赞成票,也不知道为什么)。
猜你喜欢
  • 2011-03-10
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多