【问题标题】:inline assembly segmentation fault内联汇编分段错误
【发布时间】:2012-10-24 15:21:41
【问题描述】:

全部,

我正在尝试用内联汇编函数编写一个 rot13...

下面的代码适用于'a',但是当c转到'z'时,它就不再起作用了......

而且...它总是显示“分段错误”...请给我一些建议来解决

这个问题。

#include <stdio.h>

#define add(a,b)\
asm volatile(\
    "add %%ebx,%%eax" \
    :"=a"(a) \
    :"a"(a),"b"(b) \
)

#define rot13(a)\
asm (\
"rot:\n\t"\
    "add $13,%%eax\n\t"\
    "cmpl $64,%%eax\n\t"\
    "jle L5f\n\t"\
    "cmpl $90, %%eax\n\t"\
    "jg L5f\n\t"\
    "cmpl $90,%%eax\n\t"\
    "jle L5f\n\t"\
    "subl $26,%%eax\n\t"\
"L5f:\n\t"\
    "cmpl $96,%%eax\n\t"\
    "jle L6f\n\t"\
    "cmpl $122,%%eax\n\t"\
    "jg L6f\n\t"\
    "cmpl $122,%%eax\n\t"\
    "jle L6f\n\t"\
    "subl $26,%%eax\n\t" \
"L6f:\n\t"\
    "leave\n\t"\
    :"=r"(a)\
    :"r"(a)\
)

int main()
{
    int a=13, b=12,c='z';
    rot13(c);
    printf("c-> rot13= %c\n",c);

    return 0;
}

【问题讨论】:

  • 为什么你的内联汇编中有一个 LEAVE 指令?这将修改堆栈指针,并从堆栈中弹出 4 个字节。它应该只出现在函数的末尾,并在需要时由编译器添加。
  • 非常感谢...还在学习如何处理内联汇编:)

标签: c assembly rot13


【解决方案1】:

我敢打赌你的分段错误是因为你有一个leave 指令在那里。内联汇编不会像普通函数一样被调用,所以你不需要它,它会破坏堆栈。

另一个问题是您将所有程序集硬编码为在%eax 上运行,但您没有告诉编译器。它认为它可以将输入粘贴到它想要的任何寄存器中,并从它想要的任何 other 寄存器中读取输出。可以通过始终使用%0%1 而不是%%eax 来调整代码,但是将输入和输出约束更改为

可能更容易
asm ( <your code here> : "=a" (a) : "0" (a) )

这意味着“这个内联汇编的输出必须在%eax,并且输入必须和输出在同一个寄存器中”。 (如果您再次在输入约束上加上“a”,它将不会正常工作。GCC 的寄存器分配器是 28 年的老手,你必须遵守它的规则。规则可以在GCC manual 的“Extended Asm”和“Constraints for Asm Operands”部分中找到;非常仔细地阅读它们,包括第二部分的所有小节,并记住,这实际上是内部“机器描述”语言的重新利用功能,并为此进行了优化。)

这仍然没有为我提供 rot13('z') 的正确答案,但我认为剩下的问题是你的 rot13 算法中的错误,而不是它与其余部分的接口程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 2019-08-06
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 2017-05-30
    相关资源
    最近更新 更多