c - C 中的内联汇编。错误的翻译

标签 c gcc assembly inline-assembly i386

我在C:中有这个函数

int write(int fd, char *buffer, int size)
{
    int ret;

    __asm__("mov $4, %%eax;"
            "mov %0, %%ebx;"
            "mov %1, %%ecx;"
            "mov %2, %%edx;"
            "int $0x80"
            : "=r"(ret)
            : "g"(fd), "g"(buffer), "g"(size)
            : "eax", "ebx", "ecx", "edx");

    if (ret < 0) {
        return -1;
    } else {
        return 0;
    }
}

这在 ASM 中翻译成这段代码:

push   %ebp
mov    %esp,%ebp
push   %esi
push   %ebx
mov    $0x4,%eax
mov    %esi,%ebx
mov    0x8(%ebp),%ecx
mov    0xc(%ebp),%edx
int    $0x80
mov    %esi,%eax
sar    $0x1f,%eax
pop    %ebx
pop    %esi
pop    %ebp
ret

由于fd、*buffer和size是函数参数,它们分别位于0x8(%ebp)、0xc(%ebp)和0x10(%ebp)中。为什么GCC会识别fd在%esi中的位置,而其他两个变量在堆栈中移动?我怎样才能运行这个函数(正确获取寄存器中的变量)?

最佳答案

这可能是您的架构上的调用约定。如果您想将其他参数约束到寄存器,您应该直接使用寄存器约束:例如。 “a”代表eax寄存器。

而且开头的 $4 在我看来也是错误的。

一些事情

     __asm__(
        "int $0x80"
        : "=b"(ret)
        : "c"(fd), "d"(buffer), "a"(size)
        );

如果这些确实是您的系统调用使用的寄存器,则应该这样做。

但是,总的来说,我认为你不应该自己这样做。您的操作系统肯定有类似 syscall 之类的东西,可以为您提供该功能。

关于c - C 中的内联汇编。错误的翻译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25951065/

相关文章:

c - C中函数 "localtime"的异常行为

C89,混合变量声明和代码

c++ - 设置声明值时调用函数

c++ - 在 C++/C 中通过引用传递

c++ - 注册为模板参数

assembly - defuse.ca 在线 GAS 汇编器接受 movb 和 movw 的 AT&T 语法,但不接受 movl?

assembly - 从程序集调用 C 函数——应用程序在 "call printf"处卡住,我不知道为什么

c++ - 用于创建业余操作系统的最受尊敬的语言和免费编译器?

c - 删除C中的节点

c - 如何创建一个使用输入 GTK 更改文本的窗口