用于PowerPC中执行系统调用的通用C / C ++函数

时间:2019-01-10 13:15:48

标签: c++ c++17 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变量作为syscallinstead of hard-coding one编译代码会导致以下编译错误(因此,这已经无法按预期进行):

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中,通常是r3r4,...,这也很麻烦,因为我不想显式地指定它并根据调用约定保留寄存器分配改为编译器。也许后者是不可能的,所以我不得不像下面的伪代码那样写它:

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)

这怎么办?

1 个答案:

答案 0 :(得分:1)

假设您更改后的代码如下:

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(“移动寄存器”)而不是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的{​​{1}}执行r0指令。

但是,它还不是很完整。由于您的系统调用可能返回了某些内容,因此您还需要在嵌入式asm的输出约束中对其进行描述。返回值的存储方式取决于您正在使用的系统的ABI。

根据您的系统调用ABI,value指令可能会更改其他寄存器和/或内存。您还需要在asm语句的内容破坏者列表中列出这些内容。

然后,我们有了输入参数。实际的实现取决于您程序的函数调用ABI和主管代码的系统调用A。

如果它们非常相似,您可能会发现将sc实施为实际的ASM而不是C-with-inline-ASM要容易得多。这样,您无需将参数从C拆包到内联ASM。否则,您将需要创建类似的代码以将execute_system_call数组的元素放入特定的寄存器中。

作为健全性检查,您的平台是否不提供syscall功能?听起来正是您在这里寻找的东西。