Charm is a toy assembler that aims to generate ARMv7-A assembly code. It implements a very tiny subset of the ARMv7-A instruction set and can either genera 6FE4 te a flat binary or a static ELF executable.
Charm is implemented entirely in a single C file, without any dependencies other than the standard C library.
The following commands will assemble the hello.S
into a static ELF
executable that can run on an ARM Linux machine:
./charm samples/hello.S hello
./hello
Hello, world!
Tip
If you're not on an ARM machine, you can use qemu-arm
to run the generated executable.
Charm will use _start
as the entry point of the program.
If the output file ends with .bin
or .obj
, the output will be
a flat binary.
Compiling charm requires a recent C compiler (it uses some C23 features).
make
Running the test suite requires the GNU tools in arm-none-eabi-gcc
because as
and objdump
' are used for validation.
As the first line of this README says, Charm is a toy assembler and
therefore has many limitations compared to established assemblers
like GNU's as
.
Here's a non-exhaustive list, you can either look at this to see if charm is suitable for you use case or you can treat this as a potential list of improvements you could contribute.
Very few instructions are implemented: Charm implements around 20 instructions, and some of them are not even fully implemented.
Not all invalid instructions are rejected: Charm doesn't implement all verification checks for all instructions, and therefore it might allow you to assemble code that can generate unpredictable results.
As an example, mul pc, pc, pc
is marked as UNPREDICTABLE by the
ARMv7-A architecture, but charm will happily assemble that for you.
No support for auto-generating literal pools: Charm doesn't implement any support for literal pools, so you'll have to write them by hand.