简体   繁体   English

内联程序集不显示输出

[英]inline assembly not showing output

i am compiling this program in cygwin 64 bit windows, no output, compiles correctly 我正在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;
}

Michael's comment does correctly define the problem. 迈克尔的评论确实正确地定义了问题。 But as an explanation, it is a little thin. 但作为解释,它有点薄。 So... 所以...

While syscall is the way for a user-mode application (user-mode: if you are not writing a device driver or changing the operating system's kernel, you are writing user-mode) to ask an x64 operating system to do something for you, every x64 OS has slightly different format for making the request. 尽管syscall是用户模式应用程序的方式(用户模式:如果您不编写设备驱动程序或更改操作系统的内核,而您正在编写用户模式)则要求x64操作系统为您做点事情,每个x64 OS发出请求的格式都略有不同。

For example, in the code you posted, you move the value 1 into the eax register. 例如,在您发布的代码中,将值1移动到eax寄存器中。 Why do you do that? 你为什么要这么做? Why 1 instead of (say) 23? 为什么用1代替(例如)23? The answer is that on Linux, eax is used to hold a number that tells what operation you want the OS to do. 答案是在Linux上,eax用于保存一个数字,该数字告诉您希望操作系统执行什么操作。 1 means output string. 1表示输出字符串。 Then you have to put specific values in other specific registers to say what you want to print and where you want to print it. 然后,您必须在其他特定的寄存器中输入特定的值,以说出要打印的内容和要打印的位置。

But which values you need to set and where they need to go is defined by the people who wrote Linux. 但是编写Linux的人定义了您需要设置哪些值以及将它们放到哪里。 Windows can (and does) do things entirely differently: different values, different registers, etc. Windows可以(并且确实)做完全不同的事情:不同的值,不同的寄存器等。

So the reason this code doesn't work is that it was designed specifically for Linux and you are trying to run it on Windows. 因此,此代码不起作用的原因是它是专为Linux设计的,并且您正尝试在Windows上运行它。 And while cygwin can make things look more linux-like (for example making a command prompt that handles rm commands), it can't change what happens when you directly invoke the operating system via syscall. 尽管cygwin可以使事情看起来更像linux(例如,使命令提示符处理rm命令),但是当您通过syscall直接调用操作系统时,它将无法改变。 You are still running Windows, and that's who is going to handle the syscall. 您仍在运行Windows,这将负责处理syscall。 There's nothing cygwin can do about that. cygwin对此无能为力。

So, with all this in mind, how do you make this code work under Windows? 因此,考虑到所有这些,如何使此代码在Windows下工作? The short answer is that you can't. 简短的答案是您不能这样做。 Microsoft doesn't publish the syscall numbers and what values go in which registers. Microsoft不会发布系统调用号以及在哪些寄存器中包含什么值。

If you want to print something under Windows, you are going to need to call a system dll which does all that for you. 如果要在Windows下打印某些内容,则需要调用一个系统dll,它可以为您完成所有这些工作。 You can either call ntdll.dll, or some other dll (like msvcrt.dll) which in turn ends up calling ntdll.dll. 您可以调用ntdll.dll,也可以调用其他一些dll(例如msvcrt.dll),而后者又最终会调用ntdll.dll。

There's some good examples at How to write hello world in assembler under Windows? 在Windows下如何在汇编器中编写hello world中有一些很好的示例

PS If you find the guy who originally wrote that asm, tell him that while it works on Linux, it is horribly inefficient. PS:如果您找到最初编写该asm的人,请告诉他,尽管它在Linux上运行,但效率非常低。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM