【问题标题】:inline assembly not showing output内联汇编不显示输出
【发布时间】:2017-01-12 06:37:46
【问题描述】:

我在cygwin 64位windows下编译这个程序,没有输出,编译正确

#include <unistd.h>

int main(void)
{
    const char hello[] = "Hello World!\n";
    const size_t hello_size = sizeof(hello);
    ssize_t ret;
    asm volatile
    (
        "movl $1, %%eax\n\t"
        "movl $1, %%edi\n\t"
        "movq %1, %%rsi\n\t"
        "movl %2, %%edx\n\t"
        "syscall"
        : "=a"(ret)
        : "g"(hello), "g"(hello_size)
        : "%rdi", "%rsi", "%rdx", "%rcx", "%r11"
    );
    return 0;
}

【问题讨论】:

  • 您使用的 syscall 适用于 64 位 Linux,而不适用于 Windows/Cygwin
  • @MichaelPetch 你应该把这个作为答案。

标签: windows gcc cygwin x86-64 inline-assembly


【解决方案1】:

Michael 的评论确实正确地定义了问题。但作为解释,它有点薄。所以...

虽然syscall 是用户模式应用程序(用户模式:如果您不编写设备驱动程序或更改操作系统的内核,那么您正在编写用户模式)要求 x64 操作系统为您做点什么,每个 x64 操作系统发出请求的格式略有不同。

例如,在您发布的代码中,您将值 1 移动到 eax 寄存器中。你为什么这样做?为什么是 1 而不是(比如说)23?答案是在 Linux 上,eax 用于保存一个数字,告诉您希望操作系统执行什么操作。 1 表示输出字符串。然后你必须把特定的值放在其他特定的寄存器中,以说明你想打印什么以及你想在哪里打印。

但是你需要设置哪些值以及它们需要去哪里是由编写 Linux 的人定义的。 Windows 可以(并且确实)以完全不同的方式做事:不同的值、不同的寄存器等。

所以这段代码不起作用的原因是它是专门为 Linux 设计的,而您正试图在 Windows 上运行它。虽然 cygwin 可以让事情看起来更像 linux(例如制作一个处理 rm 命令的命令提示符),但它无法改变当您通过 syscall 直接调用操作系统时发生的情况。您仍在运行 Windows,而这将由谁来处理系统调用。 cygwin 对此无能为力。

那么,考虑到这一切,如何让这段代码在 Windows 下工作?简短的回答是你不能。 Microsoft 没有公布系统调用编号以及哪些值进入哪些寄存器。

如果您想在 Windows 下打印某些东西,您需要调用一个系统 dll 来为您完成所有这些工作。您可以调用 ntdll.dll 或其他一些 dll(如 msvcrt.dll),最终调用 ntdll.dll。

How to write hello world in assembler under Windows? 有一些很好的例子

PS 如果您找到最初编写该 asm 的人,请告诉他,虽然它可以在 Linux 上运行,但它非常效率低下。

【讨论】:

  • 我故意保持我的评论很薄;-),我不会写一个基本上最终成为非答案的答案,或者至少不是 OP 想要听到的。哈哈。不知道为什么 OP 不能只使用 C 库进行打印。
  • 看起来 OPs 代码在 SO in this answer 上首次亮相,尽管类似的代码 sn-p 也出现在博客上。脚注是答案实际上有一个链接到这个other SO answer中的更好的实现和解释@
  • 我不确定 OP 的目标是什么。虽然有些人喜欢对“裸机”进行编程,但在这种情况下,他看起来只是在复制他在其他地方看到的东西。人们对 cygwin 能做什么和不能做什么感到困惑。解释为什么它可以在 linux 中工作,但不能在 linux“模拟器”中工作,这似乎是我弥补坏消息的起码。
  • 只是一个挑剔的人,但你很少直接从 ntdll.dll 调用函数。那是本机 API,不是为用户模式应用程序设计的。您通常会调用 Win32 API 提供的包装函数,主要来自 kernel32 和/或 user32 DLL(尽管还有许多其他 DLL)。如您的回答中所述,CRT(msvcrt.dll 和其他特定版本)也很常用。
  • @CodyGray 我并不反对 ntdll,但它与 Windows 中的“裸机”差不多。 OP 对他的实际目标含糊不清,但我想不出另一个使用 inline asm 进行系统调用的好理由。您是正确的,使用 msvcrt.dll 和公司提供了很多好处,并且应该是首选课程(特别是因为 OP 已经在 C 中编程)。但一般来说,避免内联汇编也应该是首选课程。
猜你喜欢
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2016-01-24
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
相关资源
最近更新 更多