背景
一直有一个需求,想要保存指令执行到特定位置的寄存器环境到一个结构体中,无疑内联汇编是一个不错的选择,但是由于对arm/thumb汇编了解的比较少,所以这个需求一直没能实现。近期又简单调试了一下,发现以前出现错误一直是由于自己写的指令有问题导致的(.........)。
环境配置
参考 https://developer.android.com/ndk/guides/standalone_toolchain.html?hl=zh-cn
截取一下内容:
NDK 提供 make-standalone-toolchain.sh shell 脚本以允许您从命令行执行定制的工具链安装。与简单方法中所述的程序相比,此方法为您提供更多灵活性。
脚本位于 $NDK/build/tools/ 目录中,其中 $NDK 是 NDK 的安装根目录。下面展示了使用此脚本的示例:
```
$NDK/build/tools/make-standalone-toolchain.sh --arch=arm --platform=android-21 --install-dir=/tmp/my-android-toolchain
在编译时,我们可以通过执行arm-linux-androideabi-gcc -mthumb thumb.c
来将我们的程序编译为thumb
指令.(就是加上了-mthumb
选项)
内联汇编
其实就是涉及到了几个指令, push
, pop
, ldr
, str
, add
.
这里就说一条指令: ldr rt, label
ldr rt, =proc
就是将proc变量的地址加载到rt中去.
#include <stdio.h>
#include <stdlib.h>
#define REG_MAX 8
typedef struct vm_context_t
{
uint32_t regs[REG_MAX];
uint8_t *PC;
uint32_t *SP;
uint8_t *LR;
char flag_z;
char flag_n;
char flag_c;
char flag_v;
} vm_context;
vm_context proc;
#define VM_COPY_REGS \
__asm__ __volatile__ \
( \
"push {r0, r1, r2, r3, r4, r5, r6, r7}\n\t" \
"ldr r1, =proc\n\t" \
"ldr r2, [sp]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0x4]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0x8]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0xc]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0x10]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0x14]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0x18]\n\t" \
"str r2, [r1]\n\t" \
\
"add r1, r1, #0x4\n\t" \
"ldr r2, [sp, #0x1c]\n\t" \
"str r2, [r1]\n\t" \
\
"pop {r0, r1, r2, r3, r4, r5, r6, r7}\n\t" \
)
int main(void)
{
VM_COPY_REGS;
printf("r0 = %x, r1 = %x, r2 = %x, r3 = %x\n"
"r4 = %x, r5 = %x, r6 = %x, r7 = %x\n", proc.regs[0], proc.regs[1], proc.regs[2], proc.regs[3], proc.regs[4], proc.regs[5], proc.regs[6], proc.regs[7]);
return 0;
}
执行效果(每次执行结果不同):
contextASM$ arm-linux-androideabi-gcc -mthumb thumb.c
contextASM$ adb push a.out /data/local/tmp/
a.out: 1 file pushed. 1.2 MB/s (6468 bytes in 0.005s)
contextASM$ adb shell
shell@hammerhead:/ $ cd /data/local/tmp/
shell@hammerhead:/data/local/tmp $ ./a.out
r0 = 1, r1 = bee49ab4, r2 = bee49abc, r3 = 9fe8
r4 = bee49ab4, r5 = bee49abc, r6 = 1, r7 = bee49a68
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!