c - 内联汇编段错误

标签 c assembly rot13

全部,

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

下面的代码对 'a' 有效,但是当 c 转到 'z' 时,它就不再有效了......

而且...它总是显示“segmentation fault”...请给我一些建议来解决

这个问题。

#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 指令在那里。内联汇编不会像普通函数一样被调用,因此您不需要它,它会破坏堆栈。

另一个问题是您将所有程序集硬编码为在 %eax 上运行,但您没有告诉编译器这一点。它认为它可以将输入保存在它想要的任何寄存器中,并从它想要的任何其他寄存器读取输出。可以通过始终使用 %0%1 而不是 %%eax 来使代码适应这种情况,但这可能更容易将输入和输出约束更改为

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

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

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

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

相关文章:

linux - 比较大文件

assembly - x86 指令 "movb $5, var(,1)"

java - Java程序中的字符串数组

c - 在 C 语言中,什么是 sscanf 的安全替代品?

android-studio - 在Android Studio上使用ARM64-v8a的汇编语言

python - ROT(n) 编码器和解码器,但解码器不工作

php - 如何在字符串上使用 PHP rot13?

C 中函数的冲突类型

c - 在 NetBeans 7 中启用 C 编译器警告

javascript - 为 C 编译器指定 header 位置(使用 emscripten 编译 R 代码)