[英]Get byte representation of ASM instruction within C code
在 C 代码中,有没有办法将 ASM 指令的文本表示(如cmpwi r3, 0x20
)转换为其二进制表示( 0x2c030020
)?
我正在编写将在运行时嵌入到另一个应用程序中的代码。 该代码应该改变正在运行的程序的行为/代码。 这意味着,有一堆这样的代码行:
*((volatile int *)(0x80001234)) = 0x2c030020;
该代码将 ASM 指令cmpwi r3, 0x20
写入 0x80001234,覆盖该地址处的当前指令。 现在,在我的 C 代码中使用常量“0x2c030020”而不知道它的作用对维护代码不利。 因此,我通常会在上面的代码中添加注释,说明 ASM 指令: // 2c 03 00 20 = cmpwi r3, 0x20
但是,这些有时会不同步。 我可能会快速更改整数值而忘记更新评论,或者我可能只是在评论中打错了字,从而导致混乱。
有什么办法可以让我做这样的事情吗? (伪代码) *((volatile int *)(0x80001234)) = asm("cmpwi r3, 0x20");
这会导致 0x2c030020 被写入 80001234? 或者我是否需要一个带有自定义预处理器的 hacky 解决方案,在我的 C 源文件上运行,用它们的字节码替换 ASM 指令?
我知道有使用asm()
函数的内联汇编代码的 C 语法,但这会执行给定的 ASM 指令,而不是给我它们的二进制表示。
这听起来像是一件疯狂的事情,但我认为您有充分的理由这样做。 生活没有一点点疯狂就没有乐趣。
您可以使用的一种方法是在构建期间使用汇编器来生成编译时常量。
第一步是制作一个文件,其中包含您将使用的每条汇编指令,每行一个。
例如:
cmpwi 3,0x20
addi 3,3,0
blr
将该文件命名为 input.def。 然后,使用这个 shell 脚本:
#!/usr/bin/env bash
(cat << HEADER
.global main
.text
main:
HEADER
cat input.def) > asm.s
powerpc-linux-gnu-as asm.s -o asm.o
powerpc-linux-gnu-objdump -d asm.o | \
sed '1,/<main>/ d' | \
paste -d'\t' - input.def | \
awk -F'\t' '{
bytes=$2
asm=$4
disasm=$3
gsub(/ /, "", bytes);
gsub(/[, ]+/, "_", asm);
printf("#define ASM_%-20s 0x%s // disassembly: %s\n", asm, bytes, disasm)
}'
# Clean temporaries
rm asm.s asm.o
(我在这里使用 GNU 汇编程序和 objdump。如果您不使用这些工具,您可能需要更改这部分。objdump 在这里被用作一种美化的 hexdump 实用程序。)
这个shell脚本:
这是很多工作,但您可以在编译时完成所有工作。
这会生成一个名为 asm.h 的头文件:
#define ASM_cmpwi_3_0x20 0x2c030020 // disassembly: cmpwi r3,32
#define ASM_addi_3_3_0 0x38630000 // disassembly: addi r3,r3,0
#define ASM_blr 0x4e800020 // disassembly: blr
您可以像这样使用 asm.h 文件:
#include "asm.h"
*((volatile int *)(0x80001234)) = ASM_cmpwi_3_0x20;
如果需要新的 asm 常量,请编辑 input.def 并重新运行 shell 脚本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.