Learning Arm, Deep, Down and Dirty
Last week I seriously started to work on the ARM support for Insight. Of course, writing a support for a new architecture in Insight requires much more than just get its hand on a decoder that can translate opcodes into mnemonics. I have to dig deep into ARM semantics and translate each instruction into our intermediate language without missing any side-effect.
This is still work in progress (and I already have to start working for teaching next semester right now… so, it will slow down a bit). But, I think I did grab a bit of the ARM spirit in the meanwhile. Here are a few of my advises to start with ARM assembly.
Reduced Instruction Set Computer !?!?
If you think that RISC means really that the instruction set is simple, you will be disillusioned quickly. ARM has a very complex set of instructions. Not because it has a lot, but mostly because it is extremely difficult to know what are the core instructions which are in most of the versions of the instruction set. Somehow, x86 is much simpler because the core instruction set has been clearly defined and used for years. ARM instruction set seems to be extremely difficult to list and with a lot of diverging documentations.
So, the first problem is really to get a trustable documentation with clear and detailed explanations down to the precise semantics of each core instruction (and get a list of it). After a few Googling I have been quite lucky and found the following that I recommend you (better look at ARMv7 which is currently the most common architecture right now, even if ARMv8 is out):
-
Introducing ARM assembly language, by Carl Burch, 2011.
-
Introduction to ARM, by David Thomas, 2012.
-
ARM Official Infocenter, ARM Ltd, 2014.
-
ARM instruction evaluator, by Anthony Fox, Magnus Myreen and Mike Gordon, 2010.
The last link has been extremely precious to me because it gives the whole semantics of each instruction. These people have also participated to the verification of the seL4 microkernel from its ARM binary. Which is a quite big achievement.
ARM Syntax is complex !
My second though on ARM is that the syntax is incredibly complex. I am used to x86 assembly, which I believed to be extremely complex. ARM is just the same because it tries to get the maximum of each instruction. For example, the conditional code is something a bit surprising when coming from x86.
Indeed, imagine that the any ARM instruction can be conditionally
executed according to the value of the CPSR (Current Program Status
Register) and a conditional (guard) stored within the instruction
opcode. In term of mnemonics, it means that the same instruction, let
say mov
can be written moveq
(executed if the CPSR has the flag
equal set to 1), movne
(not equal), movlt
(less than), and so on.
Moreover, if the mnemonic has an ‘s
‘ prefix, then it means that the
instruction updates the CPSR (and doesn’t otherwise). So, every
instruction might appear in 18 different variants with different
meaning (not even counting the ‘s
‘ prefix).
And, this does not end here ! You can also embed any shift/rotate
instruction inside another instruction. For example, here is an and
instruction with a conditional (eq
) and an internal left shift of 3
on its value, note also the final s
on the mnemonic which indicates
that the CPSR will be updated at the end of the computation:
andeqs r9, r0, r0, ror #3
Quite a nightmare to parse and to know the exact semantics of it
(knowing that ror
is also a perfectly valid instruction to be
treated as other instructions in any other situations.
To be totally complete I found also a few other curiosity such as the
possibility for the push
and pop
and ldm
instructions to address
a list of registers at once such as {r0, r1, r3}
. Which means that
the instruction should be repeated as many time as there are registers
in the list.
At first, everybody told me that ARM syntax was nice and gentle. Now I know that I tried to make a parser for it, I know it is not true. I would rank it to about the same complexity of the x86 (just a bit lower maybe because of the simplicity of the opcodes).
Beware of the rule of the Thumb !
I also need to tell that once you got to understand the ARM assembler, you discover that there is a second mode (16-bits mode) to express a subset of the instruction set with the same syntax but slightly less customization capabilities (for example, you cannot access all the registers to write on, or not all the possible formats are available, …). This 16-bits mode requires to be a bit cautious like a different instruction set, because it is a different instruction set.
Finally got the grasp on it!
After a week looking at it and making experiments, I finally got the grasp on most of it. I think I understand the big picture (I am sure I still miss a lot of details). But, this is enough for me to start with on Insight.
I need to thank a lot the people from RE StackExchange for their answers to my annoying questions (1, 2, 3).
About the title of this post, Deep, Down & Dirty (2001) is an album from the Stereo MCs.