Skip to main content

Binary arm-thumb-1 cheat sheet

Documentation ARM
Author
Raphael Outhier
Kernel engineer

Warning
#

This is a work in progress which I publish mostly for my own reference and there may be errors and typos.

Please refer to the source of truth if you want to use thumb-1 and pardon my english.

Context
#

These days when I have time I’m playing ScratchOS and I’m currently at the nibble stage where I can only write code via GPIOs and have the firmware execute it.

To move forward I need to write a few simple programs to start taking over from here.

The challenge is that I can’t use a computer to translate text assembly to hex assembly, and that requires me to get a better grip of the thumb assembly encoding.

This page is intended as a reference for future me or anyone playing masochist-mode-bringup.

Source of truth
#

All the encodings listed here can be found in the ARM Thumb 1 spec.

Instructions.
#

PC-relative branch.
#

Branch syntax :

11100xxxxxxxxxxx
e0-7….….

branch behavior : takes PC of instruction, adds 4, sign extends 2 * X to 32 bits, adds it, and sets PC to the result.

branch forward :

111000xxxxxxxxxx
e0-3….….

branch backward :

111001xxxxxxxxxx
e4-7….….

deadloop : branch with offset of -4 -> X = -2 = (~0b10 + 1 = 0b111 1111 1101 + 1 = 0b111 1111 1110)

1110011111111110
e7fe

PC-relative load :
#

Generic case :

01001dddoooooooo
48-f….….

Operands :

  • d : dest register.
  • o : offset

Behavior :

  • take v = (PC of instruction + 4) & ~(3);
  • take o and multiply it by 4.
  • load at v + o, write result in dest reg.

Particular cases :

Load at N words after PC (N > 0) after PC into r0 :

01001000oooooooo
480N - 1

Load four bytes after PC into r0 :

0100100000000000
4800

Load eight bytes after PC into r0 :

0100100000000001
4801

And so on.

Operations on high registers.
#

Encoding :

010001ooSDsssddd
44-7….….

Operands :

  • o : op : 00 = add, 01 = cmp, 10 = mov, 11 = bx.
  • S : high flag for source.
  • D : high flag for dest.
  • sss : source register
  • ddd : dest register

high register move syntax

01000110SDsssddd
46….….

special registers ;

  • sp = r13, 1 101
  • lr = r14, 1 110
  • pc = r15, 1 111

mov r0, pc = mov 0000 1111 :

0100011001000111
464f

mov sp, r0 = mov 1101 0000 :

0010011010101000
46a8

bx <s>

0100011100sss000
470-3[08]

bx r0

0100011100000000
4700

Move/compare/add/subtract immediate syntax :
#

001oodddiiiiiiii
[23]….….….

Operands :

  • o : operation : 00 mov 01 cmp 10 add 11 sub
  • d : dest low reg.
  • i : offset.

addition syntax :

00110dddiiiiiiii
30-7….….

which makes a nice lil 3 [reg] offset mnemonic.

Add offset to r0 : 3 0 offset.

push pop
#

1011m01rllllllll
b….….….

Operands :

  • m : 0 store 1 load
  • r : 0 don’t store LR / load PC, 1 store LR / load PC
  • l : register mask. bit : 0 not pushed / popped, 1 pushed/popped.

push (regular) :

10111010llllllll
ba….….

pop (regular)

10110010llllllll
b2….….

pop {r0, r1}

1011001000000011
b203

load-store (immediate offset) syntax :
#

011smooooobbbddd
[67]….….….

Operands :

  • s : 0 word, 1 byte
  • l : 0 store, 1 load
  • o : base offset
  • b : base register
  • d : data register (source or dest).

word store with no offset :

0110000000bbbddd
600-3….

word load with no offset :

0110100000bbbddd
680-3….

str r1, [r0] :

0110000000000001
6001

generally, store any register at address of r0 :

0110000000000ddd
600Rd

generally, load any register at address contained in r0 :

0110100000000ddd
680Rd