用于在 PowerPC 中执行系统调用的通用 C/C++ 函数
Generic C/C++ function for execution system calls in PowerPC
我想编写一个 C/C++
函数来执行一个 syscall
,它将 syscall
值作为参数以及可选的附加参数。
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"li 0, %0\n\t"
"sc\n\t"
:
: "i"(0x1337) // TODO: Use variable
);
}
使用 C
变量作为 syscall
值 编译代码会导致以下编译错误(因此这已经无法按预期工作):
assembly.cpp: In function 'void execute_system_call(short int, const int*, int)':
assembly.cpp:62:3: warning: asm operand 0 probably doesn't match constraints
);
^
assembly.cpp:62:3: error: impossible constraint in 'asm'
make[1]: *** [assembly.o] Error 1
make: *** [build] Error 2
此外,我还需要将参数传递到各自的寄存器中。在 PowerPC
中,这通常是 r3
、r4
、...这看起来也很麻烦,因为我不想明确指定它并根据调用约定保留寄存器分配改为编译器。也许后者是不可能的,所以我不得不把它写得更像下面的伪代码:
lis 3, $arguments[0]@h # Load higher 16-bit
ori 3, 3, $arguments[0]@l # Load lower 16-bit
lis 4, $arguments[1]@h
ori 4, 4, $arguments[1]@l
lis 5, $arguments[2]@h
ori 5, 5, $arguments[2]@l
...
li 0, $value
sc
请注意,如果假定 argument_count
始终为8
并且不必是可变的,因此方法签名也可以是
void execute_system_call(short value, const int *arguments)
如何做到这一点?
假设您修改后的代码如下所示:
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"li 0, %0\n\t"
"sc\n\t"
:
: "i"(value)
);
}
- 然后你要求 gcc 将 value
变量作为立即变量传递(因为你仍在使用 "i"
作为约束)。由于 value
是一个变量,而不是立即数,因此这将不起作用,这就是您在那里看到的错误的原因。
相反,您需要使用 "r" 输入约束来引用寄存器值:
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"li 0, %0\n\t"
"sc\n\t"
:
: "r"(value)
);
}
- 但这次,约束是正确的,但程序集不是 - li
需要一个寄存器和一个立即数,但我们需要两个寄存器。
所以,我们可能想要 mr
("move register") 而不是 li
:
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"mr 0, %0\n\t"
"sc\n\t"
:
: "r"(value)
);
}
这应该执行 sc
指令,其中 r0
包含 value
。
然而,它还没有完全完成。由于您的系统调用可能 returns 一些东西,您还需要在内联 asm 的输出约束中描述它。 return 值的存储方式将取决于您正在使用的系统的 ABI。
另外,根据您的系统调用 ABI,sc
指令可能会改变其他寄存器,and/or 内存。您还需要在 asm 语句的 clobber constriants 中列出那些。
然后,我们有了输入参数。这个的实际实现将取决于你程序的函数调用 ABI,以及主管代码的系统调用 ABI。
如果这些非常相似,您可能会发现将 execute_system_call
实现为实际的 ASM 而不是 C-with-inline-ASM 更容易。这样,您不必将参数从 C 解包到内联 ASM。否则,您将需要创建类似的代码来将 arguments
数组的元素放入特定的寄存器中。
作为完整性检查,您的平台不提供 syscall
功能吗?这听起来正是您在这里寻找的东西。
我想编写一个 C/C++
函数来执行一个 syscall
,它将 syscall
值作为参数以及可选的附加参数。
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"li 0, %0\n\t"
"sc\n\t"
:
: "i"(0x1337) // TODO: Use variable
);
}
使用 C
变量作为 syscall
值
assembly.cpp: In function 'void execute_system_call(short int, const int*, int)':
assembly.cpp:62:3: warning: asm operand 0 probably doesn't match constraints
);
^
assembly.cpp:62:3: error: impossible constraint in 'asm'
make[1]: *** [assembly.o] Error 1
make: *** [build] Error 2
此外,我还需要将参数传递到各自的寄存器中。在 PowerPC
中,这通常是 r3
、r4
、...这看起来也很麻烦,因为我不想明确指定它并根据调用约定保留寄存器分配改为编译器。也许后者是不可能的,所以我不得不把它写得更像下面的伪代码:
lis 3, $arguments[0]@h # Load higher 16-bit
ori 3, 3, $arguments[0]@l # Load lower 16-bit
lis 4, $arguments[1]@h
ori 4, 4, $arguments[1]@l
lis 5, $arguments[2]@h
ori 5, 5, $arguments[2]@l
...
li 0, $value
sc
请注意,如果假定 argument_count
始终为8
并且不必是可变的,因此方法签名也可以是
void execute_system_call(short value, const int *arguments)
如何做到这一点?
假设您修改后的代码如下所示:
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"li 0, %0\n\t"
"sc\n\t"
:
: "i"(value)
);
}
- 然后你要求 gcc 将 value
变量作为立即变量传递(因为你仍在使用 "i"
作为约束)。由于 value
是一个变量,而不是立即数,因此这将不起作用,这就是您在那里看到的错误的原因。
相反,您需要使用 "r" 输入约束来引用寄存器值:
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"li 0, %0\n\t"
"sc\n\t"
:
: "r"(value)
);
}
- 但这次,约束是正确的,但程序集不是 - li
需要一个寄存器和一个立即数,但我们需要两个寄存器。
所以,我们可能想要 mr
("move register") 而不是 li
:
void execute_system_call(short value, const int *arguments, int argument_count) {
// TODO: Use arguments
asm volatile (
"mr 0, %0\n\t"
"sc\n\t"
:
: "r"(value)
);
}
这应该执行 sc
指令,其中 r0
包含 value
。
然而,它还没有完全完成。由于您的系统调用可能 returns 一些东西,您还需要在内联 asm 的输出约束中描述它。 return 值的存储方式将取决于您正在使用的系统的 ABI。
另外,根据您的系统调用 ABI,sc
指令可能会改变其他寄存器,and/or 内存。您还需要在 asm 语句的 clobber constriants 中列出那些。
然后,我们有了输入参数。这个的实际实现将取决于你程序的函数调用 ABI,以及主管代码的系统调用 ABI。
如果这些非常相似,您可能会发现将 execute_system_call
实现为实际的 ASM 而不是 C-with-inline-ASM 更容易。这样,您不必将参数从 C 解包到内联 ASM。否则,您将需要创建类似的代码来将 arguments
数组的元素放入特定的寄存器中。
作为完整性检查,您的平台不提供 syscall
功能吗?这听起来正是您在这里寻找的东西。