How to Convert ARM Assembly and Machine Code

16 min read

Introduction

This is a memo from my ARM assembly studies. It explains how to convert between ARM assembly and machine code, and how the instruction encoding works. Please note that some details may be incorrect.

Machine Language

ARM uses 32-bit instructions. Instructions are classified into data processing instructions, memory instructions, branch instructions, and other instructions.

Basic form

*Top: bit positions. Bottom row: contents.

31:28 27:26 25:20 19:0
cond op funct -

Field descriptions

  • cond: Condition code cond=1110: Always execute
  • op: Operation code Check this first to determine the instruction type.
    • op=00: data processing instruction
    • op=01: memory instruction
    • op=10: branch instruction
  • funct: function The format changes depending on whether the instruction is for data processing, memory access, or branching.
  • -: The format changes depending on the instruction.

Data Processing Instructions

Instructions executed when op=00

Basic form

*Top: bit positions. Bottom row: contents.

31:28 27:26 25 24:21 20 19:16 15:12 11:0
cond op I cmd S Rn Rd Src2

Field descriptions

  • I: Selects an immediate value or a register. This changes the format of Src2.
    • I=1:immediate value
    • I=0: register or shifted register
  • cmd: data processing instructions This determines the data processing operation.
  • S: Update condition flags
    • S=1: Update
    • S=0: Do not update
  • Rd: Register 1
  • Rn: Register 2
  • Src2: Source 2

cmd values

cmd format description behavior
0000 AND Rd,Rn,Src2 Bitwise AND Rd ← Rn & Src2
0001 EOR Rd,Rn,Src2 Bitwise XOR Rd ← Rn ^ Src2
0010 SUB Rd,Rn,Src2 Subtraction Rd ← Rn - Src2
0011 RSB Rd,Rn,Src2 Reverse subtraction Rd ← Src2 - Rn
0100 ADD Rd,Rn,Src2 Addition Rd ← Rn + Src2
0101 ADC Rd,Rn,Src2 Carry addition Rd ← Rn + Src2 + C
0110 SBC Rd,Rn,Src2 Subtraction with carry Rd ← Rn - Src2 - C
0111 RSC Rd,Rn,Src2 Reverse subtraction with carry Rd ← Src2 - Rn - C
1000 TST Rn,Src2 Test Set flag based on Rn & Src2
1001 TEQ Rn,Src2 Test for equality Set flag based on Rn^Src2
1010 CMP Rn,Src2 Compare Set flag based on Rn -Src2
1011 CMN Rn,Src2 Negative comparison Set flag based on Rn + Src2
1100 ORR Rd,Rn,Src2 Bitwise OR Rd ← Rn | Src2
1101 Shift See table below
1110 BIC Rd,Rn,Src2 Clear each bit Rd ← Rn & ~Src2
1111 MVN Rd,Src2 Bitwise negation Rd ← ~Src2
  • Format example In this case, R1=Rd, R2=Rn, #12=Src2.
ADD R1,R2,#12

Shift details

When I=1, the instruction is a move instruction. When I=0, it is a shift or rotate instruction. When I=0, the instruction is determined from sh. *Exception 1: If I=0, sh=00, and shmat5=00000, it becomes a move instruction (MOV). *Exception 2: If I=0, sh=11, and shmat5=00000, it becomes an extended rotate-right instruction (RRX).

Shift breakdown when I=1

Format Description Behavior
MOV Rd,Src2 Move Rd ← Src2

Shift details when I=0

sh Format Description Behavior
00 LSL Rd,Rm,Rs/shmat5 Logical left shift Rd ← Rm << Src2
01 LSR Rd,Rm,Rs/shmat5 Logical right shift Rd ← Rm >> Src2
10 ASR Rd,Rm,Rs/shmat5 Arithmetic right shift Rd ← Rm >> Src2
11 ROR Rd,Rm,Rs/shmat5 Right rotation Rd ← Rn ror Src2

Instructions for which condition flags are updated

Instructions with S=1:

  • ADDS
  • SUBS
  • ASRS,LSLS,LSRS,RORS
  • ANDS,ORRS,EORS,BICS
  • MOVS,MVNS
  • MULS, SMULLS, UMULLS
  • CMP,CMN
  • TEQ,TST

Contents of Src2

This is broadly divided into data processing instructions such as ADD and SUB, and shift instructions.

For data processing instructions

There are two patterns.

I=1: When handling immediate values

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:8 7:0
rot imm8
  • rot: Number of rotations
  • imm8: 8-bit value

When handling immediate values, you can basically only encode 8-bit values directly. However, by using the barrel shifter, you can represent values up to 32 bits with some restrictions.

  • Calculation method Rotate the imm8 value right by rot x 2. Example: imm8=1111 1111 rot=1110 rot=1110 is 14 in decimal. Therefore, rotate right by 14 x 2 = 28 bits. Before 32-bit rotation 0000 0000 0000 0000 0000 0000 1111 1111 After 32-bit rotation 0000 0000 0000 0000 0000 1111 1111 0000

The value after rotation is 4080 in decimal. This value cannot be represented as a plain 8-bit value, but it can be encoded by using the barrel shifter. If the value can be expressed within 8 bits, specify rot=0000.

Example: ADD R0,R1,#42

cond op I cmd S Rn Rd rot imm8
1110 00 1 0100 0 0001 0000 0000 0010 1010

cmd=ADD, Rd=R0, Rn=R1, rot/imm8=#42. Dividing this machine code into 4-bit groups gives:

1110 0010 1000 0001 0000 0000 0010 1010

Converting it to hexadecimal gives:

0xE281002A

I=0: When handling registers

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:7 6:5 4 3:0
shmat5 sh 0 Rm
  • shmat5: 5-bit shift amount *Shmat5=00000 when using data processing instructions and registers.
  • sh: Shift command *When handling data processing instructions and registers, sh=00.
  • 0: 0 is stored
  • Rm: Register This corresponds to the third register.

Example: SUB R8,R9,R10

cond op I cmd S Rn Rd shmat5 sh 0 Rm
1110 00 0 0010 0 0110 0101 00000 00 0 1010

cmd=SUB, Rd=R9, Rn=R8, Rm=R10. Dividing this machine code into 4-bit groups gives:

1110 0000 0100 0110 0101 0000 0000 1010

Converting it to hexadecimal gives:

0xE049800A

For shift commands

There are three patterns.

I=1: For move instructions

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:8 7:0
rot imm8
  • rot: Number of rotations
  • imm8: 8-bit value

As mentioned above, if I=1 in a shift command, it becomes a move instruction (MOV). Example: MOV R0,#7

cond op I cmd S Rn Rd rot imm8
1110 00 1 1101 0 0000 0000 0000 0000 0111

cmd=shift command, Rd=R0, rot/imm8=#7. Dividing this machine code into 4-bit groups gives:

1110 0011 1010 0000 0000 0000 0000 0111

Converting it to hexadecimal gives:

0xE3A00007

I=0: When the shift amount is an immediate value

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:7 6:5 4 3:0
shmat5 sh 0 Rm
  • shmat5: 5-bit shift amount *The immediate value is included here.
  • sh: Shift command
  • 0: 0 is stored
  • Rm: Register *For shift instructions, Rn is not used and the second register is Rm.

Example: LSL R0,R9,#7

cond op I cmd S Rn Rd shmat5 sh 0 Rm
1110 00 0 1101 0 0000 0000 00111 00 0 1001

cmd=shift command, Rd=R0, Rm=R9, shmat5=#7, sh=LSL. Dividing this machine code into 4-bit groups gives:

1110 0001 1010 0000 0000 0011 1000 1001

Converting it to hexadecimal gives:

0xE1A00309

I=0: When the shift amount is a register

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:8 7 6:5 4 3:0
Rs 0 sh 1 Rm
  • Rs: Register This corresponds to the third register.
  • 0: 0 is stored
  • sh: Shift instruction
  • 1: 1 is stored
  • Rm: Register This corresponds to the second register.

Example: ASR R5,R1,R12

cond op I cmd S Rn Rd Rs 0 sh 1 Rm
1110 00 0 1101 0 0000 0101 1100 0 10 1 0001

cmd=shift command, Rd=R5, Rm=R1, Rs=R12, sh=ASR. Dividing this machine code into 4-bit groups gives:

1110 0001 1010 0000 0101 1100 0101 0001

Converting it to hexadecimal gives:

0xE1A05C51

Memory Instructions

Instructions executed when op=01

Basic form

*Top: bit positions. Bottom row: contents.

31:28 27:26 25 24 23 22 21 20 19:16 15:12 11:0
cond op I P U B W L Rn Rd Src2

Field descriptions

  • I: Selects an immediate value or a register. This changes the format of Src2.
    • I=0:Immediate offset
    • I=1: Register offset
  • U: Addition or subtraction
    • U=1: Add offset
    • U=0: Subtract offset
  • P W: Index mode Determine using the P and W values.
  • L B: Memory instruction Determine using the L and B values.
  • Rd: Register 1
  • Rn: Register 2
  • Src2: Source 2

P W: Index mode values

P W Index mode Example How to tell
0 0 Post-index LDR R0,[R1],R2 The parentheses are in the middle.
0 1 Not supported -
1 0 Offset LDR R0,[R1,R2] The two closing brackets are at the end.
1 1 Pre-index LDR R0,[R1,R2]! Exclamation mark

L B: Memory instruction values

L B Command
0 0 STR
0 1 STRB
1 0 LDR
1 1 LDRB

Contents of Src2

I=0: When handling immediate values

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:0
imm12
  • imm12: Stores a 12-bit value This handles immediate values.

Example: STR R11,[R5],#-26

cond op I P U B W L Rn Rd imm12
1110 01 0 0 0 0 0 0 0101 1011 0000 0001 1010

U=subtraction, P W=post index, L B=STR, imm12=#26 Dividing this machine code into 4-bit groups gives:

1110 0100 0000 0101 1011 0000 0001 1010

Converting it to hexadecimal gives:

0xE405B01A

I=1: When handling registers

Src2 is encoded as follows.

*Top: bit positions. Bottom row: contents.

11:7 6:5 4 3:0
shmat5 sh 0 Rm
  • shmat5: 5-bit shift amount
  • sh: Shift instruction
  • 0: 0 is stored
  • Rm: Register

Example: omitted

Branch Instructions

Instructions executed when op=10

Basic form

*Top: bit positions. Bottom row: contents.

31:28 27:26 25 24 23:0
cond op 1 L imm24
  • 1: 1 is stored
  • L: Branch instruction
  • imm24: Stores a 24-bit value This stores the branch destination address.

L: Branch instruction values

L Command
0 B
1 BL

Branch destination address calculation

  1. Find the branch instruction.
  2. Use the instruction two positions after the branch instruction as the reference.
  3. Calculate how far the branch destination address is from the reference.
  4. Store that address value in imm24. If the value is negative, express it using two’s complement.

Example:

1 TEST LDRB R5,[R0,R3] ← Branch destination address
2      STRB R5,[R1,R3]
3      ADD  R3,R3,#1
4      MOV  PC,LR
5 BL TEST ← Branch instruction
6      LDR  R3,[R1],#4
7 SUB R4,R3,#9  ← Reference

In this case, the branch destination address is “-6” from the reference. In other words, it is expressed in machine code as follows:

cond op 1 L imm24
1110 10 1 1 1111 1111 1111 1111 1111 1010

Dividing this machine code into 4-bit groups gives:

1110 1011 1111 1111 1111 1111 1111 1010

Converting it to hexadecimal gives:

0xEBFFFFFA

References