在 ARM 中使用 return 值执行系统调用的内联汇编

In-line assembly to perform syscall with return value in ARM

我找到了许多使用 asm 运行 Hello World 系统调用的示例,但 none 讨论了使用 return 值调用系统调用。我的代码是

int my_syscall(int sn)
{
    int output_variable = 0;
    int input_variable = sn;
    __asm__ volatile(
    "mov r7,%1\n\t"
    "svc 0\n\t"
    "mov %0,r0\n\t"
    :"=r"(output_variable)
    :"r"(input_variable)
    );
    return output_variable;
}

运行 ARM 上的这个 linux(BeagleBone Black) 给我一个分段错误。

修复:修复是在使用 arm-linux-gnueabihf-gcc(可能也适用于其他风格)进行编译时使用“-fomit-frame-pointer”指令。

$arm-linux-gnueabihf-gcc {YOUR FILE NAME}.c -fomit-frame-pointer -o {YOUR OUTPUT FILE NAME}

谢谢大家的评论。因此,为了记录,问题中的上述代码逻辑有效。据我了解,问题是编译器出于某种原因使用 r7 作为帧指针。您可以继续添加参数作为输入,并使用内联汇编创建更通用的系统调用实现。考虑人们在评论中所说的更好的实施。

伪代码

returntype my_syscall(int syscallnumber,type arg1,type arg2,..)
{
    int output_variable = 0;
    __asm__ volatile
    (
        "mov r7,[sysnum]\n\t"
        "mov r0,[var1]\n\t"
        "mov r1,[var2]\n\t"
                             //continue similarly for more input arguments etc 
        "svc 0\n\t"
        "mov %0,r0\n\t"      //Return value of syscall will be available in r0 for ARM EABI
        :"=r"(output_variable)
        :[sysnum]"r"(syscallnumber),[var1]"r"(arg1),[var2]"r"(arg2) //and so on for other arguments
        :"memory" //clobber others based on usage
    );
    return output_variable;
}

背景故事(对于任何感兴趣的人):当我实现一个简单的 "Hello World" 字符串写入(更改包括不同的系统调用编号和参数)时,相同的代码(问题中存在的代码)略有不同就起作用了.但是当我调用我的自定义系统调用时它不起作用 returned 一个需要的值(或者,您可以使用参数而不是 return 指令将系统调用设计为 return 值以避免这种情况整个问题。我没有这样做,因为那样我将不得不重新编译整个内核,但我离题了)。我用内置的 syscall() 函数测试了我的系统调用,它运行良好。但是 syscall() 函数的 MY 实现无法调用 MY 自定义系统调用。 我尝试了寄存器变量,我尝试了不同的指令并破坏了 r0、内存等(在我在这里问这个问题之前),但似乎没有任何效果。然后我尝试破坏 r7,编译器说你不能那样做。所以那时候我发现 r7 寄存器也被用于其他用途。当我用谷歌搜索错误时,我发现了上面的 fix。 具有讽刺意味的是,在修复之后它没有破坏 r7 或其他任何东西。哈哈