如何在C代码中将汇编指令文本转换为其二进制字节表示?
Great question! Hardcoding raw opcode bytes is a total maintenance disaster—comments inevitably get out of sync with values, and debugging becomes way harder than it needs to be. You don’t need to roll your own preprocessor; there are built-in ways to let the compiler/assembler handle converting assembly instructions to their binary equivalents for you. Here are your best options:
Option 1: Use GCC/Clang Assembly Extensions to Extract Opcode
You can leverage inline assembly to generate the instruction, then capture its opcode bytes into a variable without executing the instruction itself. Here’s a working example for PowerPC (since your code uses cmpwi, a PowerPC instruction):
#include <stdint.h> uint32_t get_cmpwi_r3_20_opcode() { uint32_t opcode; asm volatile ( // Push the instruction into a temporary read-only section ".pushsection .rodata\n" "1:\n" // Label for the start of our instruction "cmpwi r3, 0x20\n" // The assembly instruction we want "2:\n" // Label for the end ".popsection\n" // Load the address of the start label, then read the opcode from that address "ldr %0, =1b\n" "ldr %0, [%0]\n" : "=r"(opcode) // Output: store opcode into this variable : // No inputs : "memory" // Tell compiler memory may be modified ); return opcode; } // Usage in your code: int main() { volatile uint32_t *target_addr = (volatile uint32_t *)0x80001234; *target_addr = get_cmpwi_r3_20_opcode(); return 0; }
This works by temporarily placing the cmpwi instruction into a read-only data section, then loading the value at that section’s address into your variable. The compiler handles assembling the instruction into its correct opcode, so you only need to update the assembly line in the inline block if you want to change the instruction.
Option 2: Separate Assembly File with Opcode Symbols
For cleaner code (especially if you need multiple opcodes), create a standalone assembly file that defines each instruction as a global symbol, then reference those symbols in your C code.
Step 1: Create opcodes.s
.section .rodata .global cmpwi_r3_20_opcode cmpwi_r3_20_opcode: cmpwi r3, 0x20 ; The instruction we want to get the opcode for
Step 2: Reference in C Code
#include <stdint.h> // Declare the external symbol from the assembly file extern const uint32_t cmpwi_r3_20_opcode; int main() { volatile uint32_t *target_addr = (volatile uint32_t *)0x80001234; *target_addr = cmpwi_r3_20_opcode; return 0; }
When you compile and link this, the assembler will convert the cmpwi instruction to its binary opcode, and your C code can directly reference it as a constant. This is great for scalability—add more instructions to the assembly file as needed, no messy inline blocks.
Key Notes
- Byte Order: PowerPC uses big-endian byte ordering, which matches how opcodes are stored in memory, so you won’t need to swap bytes here. Double-check this if you’re targeting a different architecture.
- Volatile: Always use
volatilefor the target memory pointer to prevent the compiler from optimizing away the write operation. - Permissions: Modifying another process’s memory will require appropriate system permissions (e.g., using
ptraceon Linux, or memory mapping APIs depending on your OS).
You don’t need to build a custom preprocessor for this—these methods leverage the existing toolchain to keep your code maintainable and in sync.
内容的提问来源于stack exchange,提问作者Florian Bach

