初学者内联汇编分段错误

Posted

技术标签:

【中文标题】初学者内联汇编分段错误【英文标题】:Beginner Inline Assembly Segmentation fault 【发布时间】:2013-11-18 05:05:20 【问题描述】:

我是第一次编写内联汇编,但我不知道为什么在尝试运行它时会出现 Seg 错误。

#include <stdio.h>
int very_fast_function(int i)
    asm volatile("movl %%eax,%%ebx;"
        "sall $6,%%ebx;"
        "addl $1,%%ebx;"
        "cmpl $1024,%%ebx;"
        "jle Return;"
        "addl $1,%%eax;"
        "jmp End;"
        "Return: movl $0,%%eax;"
        "End: ret;": "=eax" (i) : "eax" (i) : "eax", "ebx" );
    return i;
    /*if ( (i*64 +1) > 1024) return ++i;
    else return 0;*/


int main(int argc, char *argv[])

    int i;
    i=40;
    printf("The function value of  i is %d\n", very_fast_function(i));
    return 0;

就像我说的那样,这是我的第一次,所以如果它非常明显,我道歉。

【问题讨论】:

看看setg指令。如果你在开始时清空 eax,在 cmpl 之后你可以执行 setg %al 并完成它。 【参考方案1】:

您不得直接使用ret。原因:在进入每个函数的时候有压栈或者保存帧指针的初始化,也有相应的finalization。如果直接使用ret,你只是让堆栈不恢复。

只要去掉ret就不会出现分段错误。

但是我认为结果并不像预期的那样。原因是您的输入/输出约束不符合预期。请注意,您编写的"=eax" (i) 没有指定使用%%eax 作为i 的输出,而这意味着在输出变量i 上应用约束e ax

出于您的目的,您可以简单地使用r 来指定一个寄存器。查看我刚刚测试过的编辑代码:

asm volatile("movl %1,%%ebx;"
    "sall $6,%%ebx;"
    "addl $1,%%ebx;"
    "cmpl $1024,%%ebx;"
    "jle Return;"
    "addl $1,%0;"
    "jmp End;"
    "Return: movl $0,%0;"
    "End: ;": "=r" (i) : "r" (i) : "ebx" );

这里要明确使用%%eax,请使用"=a" 而不是"=r"

更多信息,请阅读http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

【讨论】:

太棒了,非常感谢您的帮助!修复一切! @user2926342 总是很高兴能提供帮助:D【参考方案2】:

ret 不应在内联汇编块中使用 - 除了简单的 ret 将处理之外,您所使用的函数还需要一些清理。

请记住,内联汇编直接插入到它所嵌入的函数中。它本身并不是一个函数。

【讨论】:

以上是关于初学者内联汇编分段错误的主要内容,如果未能解决你的问题,请参考以下文章

gnu 内联汇编错误

内联汇编,错误

内联汇编代码错误

GCC 内联汇编错误:表达式后出现垃圾 `(%ebp)+4'

简单 g++ 内联汇编程序中的错误

编译linux内核2.4.0时内联汇编错误