在 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 或其他任何东西。哈哈
我找到了许多使用 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 或其他任何东西。哈哈