首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用GNU C内联汇编编写Linux Int80h系统调用包装器

用GNU C内联汇编编写Linux Int80h系统调用包装器
EN

Stack Overflow用户
提问于 2011-02-27 13:05:39
回答 1查看 16K关注 0票数 9

我正在尝试使用内联汇编...我读了这个页面http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx,但是我不能理解传递给我的函数的参数。

我正在写一个C写的例子..这是我的函数头:

代码语言:javascript
复制
write2(char *str, int len){
}

这是我的汇编代码:

代码语言:javascript
复制
global write2
write2:
    push ebp
    mov ebp, esp
    mov eax, 4      ;sys_write
    mov ebx, 1      ;stdout
    mov ecx, [ebp+8]    ;string pointer
    mov edx, [ebp+12]   ;string size
    int 0x80        ;syscall
    leave
    ret

我该怎么做才能把这段代码传递给C函数...我正在做这样的事情:

代码语言:javascript
复制
write2(char *str, int len){
    asm ( "movl 4, %%eax;"
          "movl 1, %%ebx;"
          "mov %1, %%ecx;"
          //"mov %2, %%edx;"
          "int 0x80;"
           :
           : "a" (str), "b" (len)
    );
}

这是因为我没有输出变量,那么我该如何处理呢?另外,使用以下代码:

代码语言:javascript
复制
global main
main:
    mov ebx, 5866       ;PID
    mov ecx, 9      ;SIGKILL
    mov eax, 37     ;sys_kill
    int 0x80        ;interruption
    ret 

如何才能将代码内联到代码中。这样我就可以向用户询问pid了。像这样..。这是我的预编码

代码语言:javascript
复制
void killp(int pid){
    asm ( "mov %1, %%ebx;"
          "mov 9, %%ecx;"
          "mov 37, %%eax;"
           :
           : "a" (pid)         /* optional */
    );
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-02-27 14:37:15

好吧,你没特别说,但是在你的帖子里,你似乎在使用gcc及其带约束的内联asm语法(其他C编译器有非常不同的内联语法)。也就是说,您可能需要使用AT&T汇编语言语法,而不是Intel,因为这就是gcc使用的语法。

如上所述,让我们来看看你的write2函数。首先,您不想创建堆栈帧,因为gcc将创建一个堆栈帧,所以如果您在asm代码中创建一个堆栈帧,您将最终得到两个帧,并且事情可能会变得非常混乱。其次,由于gcc正在布局堆栈帧,因此您不能使用"ebp + offset“访问var,因为您不知道它是如何布局的。

这就是约束的用途--您可以说明您希望gcc将值放在什么位置(任何寄存器、内存、特定寄存器),以及在asm代码中使用"%X“。最后,如果您在asm代码中使用显式寄存器,则需要在第三部分中列出它们(在输入约束之后),以便gcc知道您正在使用它们。否则,它可能会将一些重要的值放在其中一个寄存器中,而您将重写该值。

您还需要告诉编译器,内联asm将或可能读取或写入输入操作数指向的内存;这并不是暗示。

因此,您的write2函数如下所示:

代码语言:javascript
复制
void write2(char *str, int len) {
    __asm__ volatile (
        "movl $4, %%eax;"      // SYS_write
        "movl $1, %%ebx;"      // file descriptor = stdout_fd
        "movl %0, %%ecx;"
        "movl %1, %%edx;"
        "int $0x80"
        :: "g" (str), "g" (len)       // input values we MOV from
        : "eax", "ebx", "ecx", "edx", // registers we destroy
          "memory"                    // memory has to be in sync so we can read it
     );
}

注意AT&T语法-- src,dest而不是dest,src和%放在寄存器名称之前。

现在这将会工作,但它的效率很低,因为它将包含许多额外的mov。通常,您不应该在asm代码中使用mov指令或显式寄存器,因为最好使用约束来说明您想要的东西的位置,并让编译器确保它们在那里。这样,优化器可能会去掉大部分mov,特别是在它内联函数的情况下(如果您指定-O3,它就会这么做)。方便的是,i386机器模型具有针对特定寄存器的约束,因此您可以这样做:

代码语言:javascript
复制
void write2(char *str, int len) {
    __asm__ volatile (
        "movl $4, %%eax;"
        "movl $1, %%ebx;"
        "int $0x80"
        :: "c" (str), /* c constraint tells the compiler to put str in ecx */
           "d" (len)  /* d constraint tells the compiler to put len in edx */
        : "eax", "ebx", "memory");
}

甚至更好

代码语言:javascript
复制
// UNSAFE: destroys EAX (with return value) without telling the compiler
void write2(char *str, int len) {
    __asm__ volatile ("int $0x80"
        :: "a" (4), "b" (1), "c" (str), "d" (len)
        : "memory");
}

还要注意volatile的使用,它需要告诉编译器,即使没有使用它的输出(其中没有输出),也不能将其作为失效来消除。(没有输出操作数的asm已经是隐式的volatile,但是当真正的目的不是计算某些东西时,显式地设置它并没有什么坏处;它是为了产生像系统调用这样的副作用。)

编辑

最后要注意的是,此函数正在执行一个write系统调用,它确实返回eax中的一个值--写入的字节数或错误代码。所以你可以通过一个输出约束来实现:

代码语言:javascript
复制
int write2(const char *str, int len) {
    __asm__ volatile ("int $0x80" 
     : "=a" (len)
     : "a" (4), "b" (1), "c" (str), "d" (len),
       "m"( *(const char (*)[])str )       // "dummy" input instead of memory clobber
     );
    return len;
}

所有系统调用都以EAX格式返回。从-4095-1 (含)的值为负errno代码,其他值为非错误。(这适用于全局的所有Linux系统调用)。

如果您正在编写一个通用的系统调用包装器,那么您可能需要一个"memory"封装器,因为不同的系统调用具有不同的指针操作数,并且可能是输入或输出。如果省略了https://godbolt.org/z/GOXBue,请参阅this answer获取有关虚拟内存输入/输出的更多详细信息。

使用这个输出操作数,您需要显式的volatile --每次在源代码中“运行”asm语句时,只需要一个write系统调用。否则,允许编译器假定它的存在只是为了计算它的返回值,并且可以消除对相同输入的重复调用,而不是编写多行代码。(或者,如果没有检查返回值,则将其完全删除。)

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5131568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档