0

全部,

我试图用内联汇编函数编写一个 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;
}
4

1 回答 1

3

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

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

asm ( <your code here> : "=a" (a) : "0" (a) )

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

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

于 2012-10-24T15:24:41.803 回答