【发布时间】:2013-03-27 00:07:08
【问题描述】:
我正在尝试用 C 和 ARM 编写一些自我修改的代码。我之前向similar question 询问过关于 MIPS 的问题,现在我正在尝试将项目移植到 ARM。
我的系统 := 树莓派上的 Raspbian、ARMv6、GCC
有几件事我不确定:
- ARM 是否需要 D 缓存回写/I 缓存无效(缓存刷新)?如果是这样,我们该怎么做?
我也尝试了一个例子
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int inc(int x){ //increments x
uint16_t *ret = malloc(2 * sizeof(uint16_t));
*(ret + 0) = 0x3001; //add r0 1 := r0 += 1
*(ret + 1) = 0x4770; //bx lr := jump back to inc()
int(*f)(int) = (int (*)(int)) ret;
return (*f)(x);
}
int main(){
printf("%d",inc(6)); //expect '7' to be printed
exit(0);}
但我不断收到分段错误。我正在使用 aapcs 调用约定,据我所知,这是所有 ARM 的默认设置
如果有人指出我正确的方向,我将不胜感激
额外问题(意思是,它实际上不必回答,但知道会很酷)-我“来自 MIPS 背景”,ARM 程序员在没有 0 寄存器的情况下怎么办? (例如,硬编码为值 0 的寄存器)
【问题讨论】:
-
这不是 arm 或 mips 问题,而是 linux 和保护问题。使用 mmap 分配内存空间并启用它以执行等,然后对其进行修改,然后您可以分支到它而不会出现保护错误。有很多SO问题已经回答了“Linux上的自我修改代码”问题,对于mips,arm,x86,ppc等问题的答案相同。
-
至于你的额外问题:在我知道的所有处理器中(大约 10 个),ARM 拥有最扩展的方式将常量输入到处理器的数据路径中,所以为什么只使用 0。所以我的反问是:为什么 MIPS 会浪费一个寄存器的指令编码空间来将 0 放入数据路径?当然是一个反问。
-
您至少需要
int tmp = 0; /* Drain WB */ __asm volatile(" mcr p15, 0, %0, c7, c10, 4\n" : "=r" (tmp));确保在跳转之前将写入提交到 RAM。 -
@C.E.Sally 对于奖金奖金,
MOV Rd,#1将适用于任何 8 位值。好的部分是,如果您需要设置额外的位,您可以在将原始 8 位旋转到寄存器中的任意位置时将它们“或”。使用MVN,您可以设置 8 个零位。 -
此外,您还需要分配可执行内存。通过 malloc 分配的内存可能不能保证可执行,因为它应该是数据而不是代码。尝试使用 mmap 分配内存并设置可执行标志。这是我为 x86 写的答案(但也应该在 ARM 下工作)stackoverflow.com/a/14826557/268025 编辑:殴打 - 刚刚看到 dwelch 的评论。
标签: c assembly arm jit raspberry-pi