c - 编写 MIPS 机器指令并从 C 执行它们

标签 c assembly mips inline-assembly mips32

我正在尝试用 C 和 MIPS 编写一些自修改代码。

因为我想稍后修改代码,所以我尝试编写实际的机器指令(而不是内联汇编)并尝试执行这些指令。有人告诉我可以只 malloc 一些内存,在那里写指令,将 C 函数指针指向它然后跳转到它。(我包括下面的示例)

我已经用我的交叉编译器(sourcery codebench 工具链)尝试过这个,但它不起作用(是的,事后看来,我认为它看起来确实很幼稚)。我怎样才能正确地做到这一点?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


void inc(){
    int i = 41;
    uint32_t *addone = malloc(sizeof(*addone) * 2); //we malloc space for our asm function
    *(addone) = 0x20820001; // this is addi $v0 $a0 1, which adds one to our arg (gcc calling con)
    *(addone + 1) = 0x23e00000; //this is jr $ra

    int (*f)(int x) = addone; //our function pointer
    i = (*f)(i);
    printf("%d",i);    
}

int main(){
    inc();
exit(0);}

我在这里遵循 gcc 调用约定,其中参数传递给 $a0,函数的结果预计在 $v0 中。我实际上不知道返回地址是否会被放入 $ra (但我还不能测试它,因为我无法编译。 我在指令中使用 int 因为我正在编译 MIPS32(因此 32 位 int 应该足够了)

最佳答案

OP 编写的代码使用 Codesourcery mips-linux-gnu-gcc 编译时没有错误。

正如其他人在上面提到的,MIPS 上的自修改代码需要在编写代码后将指令缓存与数据缓存同步。 MIPS 架构的 MIPS32R2 版本添加了 SYNCI instruction这是一条用户模式指令,可以满足您的需求。所有现代 MIPS CPU 都实现 MIPS32R2,包括 SYNCI

内存保护是 MIPS 上的一个选项,但大多数 MIPS CPU 在构建时并未选择此功能,因此在大多数真正的 MIPS 硬件上可能不需要使用 mprotect 系统调用。

请注意,如果您使用 -O0 之外的任何优化,编译器可以并且确实优化了存储到 *addone 和函数调用,这会破坏您的代码。使用 volatile 关键字可防止编译器执行此操作。

以下代码生成正确的 MIPS 程序集,但我手头没有 MIPS 硬件来测试它:

int inc() {
    volatile int i = 41;
    // malloc 8 x sizeof(int) to allocate 32 bytes ie one cache line,
    // also ensuring that the address of function addone is aligned to
    // a cache line.
    volatile int *addone = malloc(sizeof(*addone) * 8);
    *(addone)     = 0x20820001; // this is addi $v0 $a0 1
    *(addone + 1) = 0x23e00000; //this is jr $ra
    // use a SYNCI instruction to flush the data written above from
    // the D cache and to flush any stale data from the I cache
    asm volatile("synci 0(%0)": : "r" (addone));
    volatile int (*f)(int x) = addone; //our function pointer
    int j = (*f)(i);
    return j;
}

int main(){
    int k = 0;
    k = inc();
    printf("%d",k);    
    exit(0);
}

关于c - 编写 MIPS 机器指令并从 C 执行它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13162464/

相关文章:

c - 使用 getsockname() 获取我自己的 IP 地址

c - C中ListNode中的指针

c - 有没有办法使用 gcc 将 C 转换为 MIPS?

c - Nios II 汇编代码转 C

C 到 MIPS 的转换

Android 实时构建 jar : arm64, armabi、mips、mips64、x86

c - 读取简单 CSV 文件时出现段错误 - C

c - 用向右移动 'k' 次的单词替换文本中的每个单词

assembly - 汇编中的宏与过程

c++ - 将文件链接到内核时出错