内联汇编不显示输出

inline assembly not showing output

我正在用 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 , %%eax\n\t"
        "movl , %%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;
}

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

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

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

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

所以此代码不起作用的原因是它是专门为 Linux 设计的,而您正试图在 Windows 上 运行 它。虽然 cygwin 可以使事情看起来更多 linux-like(例如制作处理 rm 命令的命令提示符),但它无法改变通过系统调用直接调用操作系统时发生的情况。您仍然是 运行ning 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 上工作,但 非常可怕效率低下。