内联程序集不显示输出 [英] inline assembly not showing output

查看:86
本文介绍了内联程序集不显示输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在cygwin 64位窗口中编译该程序,没有输出,可以正确编译

i am compiling this program in cygwin 64 bit windows, no output, compiles correctly

#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的注释正确地定义了问题.但作为解释,它有点薄.所以...

Michael's comment does correctly define the problem. But as an explanation, it is a little thin. So...

syscall是用户模式应用程序的方式(用户模式:如果您不编写设备驱动程序或不更改操作系统的内核,则是在编写用户模式),要求x64操作系统执行以下操作:为您做些事情,每个x64操作系统发出请求的格式都略有不同.

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.

例如,在您发布的代码中,将值1移动到eax寄存器中.你为什么要这么做?为什么用1代替(比如说)23?答案是在Linux上,eax用于保存一个数字,该数字告诉您希望操作系统执行什么操作. 1表示输出字符串.然后,您必须在其他特定的寄存器中输入特定的值,以说出要打印的内容和要打印的位置.

For example, in the code you posted, you move the value 1 into the eax register. Why do you do that? Why 1 instead of (say) 23? The answer is that on Linux, eax is used to hold a number that tells what operation you want the OS to do. 1 means output string. 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.

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

But which values you need to set and where they need to go is defined by the people who wrote Linux. Windows can (and does) do things entirely differently: different values, different registers, etc.

所以此代码不起作用的原因是它是专为Linux设计的,并且您正在尝试在Windows上运行它.尽管cygwin可以使事情看起来更像linux(例如,使命令提示符处理rm命令),但是当您通过syscall直接调用操作系统时,它将无法改变.您仍在运行Windows,这将负责处理syscall. cygwin对此无能为力.

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. 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. You are still running Windows, and that's who is going to handle the syscall. There's nothing cygwin can do about that.

因此,请牢记所有这些,如何使此代码在Windows下工作?简短的答案是您不能这样做. Microsoft不会发布系统调用号以及在哪个寄存器中输入什么值.

So, with all this in mind, how do you make this code work under Windows? The short answer is that you can't. Microsoft doesn't publish the syscall numbers and what values go in which registers.

如果要在Windows下打印某些内容,则需要调用一个系统dll,它可以为您完成所有这些工作.您可以调用ntdll.dll,也可以调用其他一些dll(例如msvcrt.dll),而这些dll最终会调用ntdll.dll.

If you want to print something under Windows, you are going to need to call a system dll which does all that for you. You can either call ntdll.dll, or some other dll (like msvcrt.dll) which in turn ends up calling ntdll.dll.

如何在Windows下的汇编器中编写hello world的例子很好.

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

PS If you find the guy who originally wrote that asm, tell him that while it works on Linux, it is horribly inefficient.

这篇关于内联程序集不显示输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆