Skip to content

Instantly share code, notes, and snippets.

@Todd-Davies
Last active July 21, 2018 09:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Todd-Davies/458b6ea463af2f182773 to your computer and use it in GitHub Desktop.
Save Todd-Davies/458b6ea463af2f182773 to your computer and use it in GitHub Desktop.
ARM Addressing modes
; Addressing modes
; ================
; Here we write a program to add up the numbers in a table.
; We do it in four different ways to illustrate different methods of addressing
; in ARM Assembly.
; To compile/run, open Komodo with the command:
; start_komodo 15111
; Then open, compile and run this file as normal.
; Expected output:
; Base + offset: 10
; Register indirect: 10
; Pre-indexed: 10
; Base + offset with offset in register: 10
; Post indexed: 10
; Branch to the start so we don't try and execute the data we define below
B start
; Define all the data we need
msgPre DEFB "Base + offset: ", 0
ALIGN
msgRegIn DEFB "Register indirect: ", 0
ALIGN
msgAuto DEFB "Pre-indexed: ", 0
ALIGN
msgReg DEFB "Base + offset with offset in register: ", 0
ALIGN
msgPost DEFB "Post indexed: ", 0
ALIGN
newline DEFB "\n", 0
ALIGN
; This is the data we're working on. N.b. 1 + 2 + 3 + 4 = 10
table DEFB 1, 2, 3, 4;
tableEnd ;
; N.b. we can compute how many bytes there
; are in the table like so:
; #(tableEnd - table)
start
; ----------------------------------------
; Naive way - Base + offset addressing
; The first load (LDRB R2, [R1]) uses register indirect addressing, but the
; other three use pre-indexed register indirect addressing (LDR R2, [R1, #X]),
; where the value of R1 is not updated.
; ----------------------------------------
; Print the message
ADR R0, msgPre;
SVC 3;
; Clear R0 since we'll keep the sum in there
MOV R0, #0
ADR R1, table;
LDRB R2, [R1];
ADD R0, R0, R2;
LDRB R2, [R1, #1];
ADD R0, R0, R2;
LDRB R2, [R1, #2];
ADD R0, R0, R2;
LDRB R2, [R1, #3];
ADD R0, R0, R2;
; Print the result
SVC 4;
ADR R0, newline;
SVC 3;
; ----------------------------------------
; Naive way 2 - Base + register indirect addressing
; Use register indirect addressing and increment the register after every load
; ----------------------------------------
; Print the message
ADR R0, msgRegIn;
SVC 3;
; Clear R0 since we'll keep the sum in there
MOV R0, #0
ADR R1, table;
LDRB R2, [R1];
ADD R1, R1, #1;
ADD R0, R0, R2;
LDRB R2, [R1];
ADD R1, R1, #1;
ADD R0, R0, R2;
LDRB R2, [R1];
ADD R1, R1, #1;
ADD R0, R0, R2;
LDRB R2, [R1];
ADD R0, R0, R2;
; Print the result
SVC 4;
ADR R0, newline;
SVC 3;
; ----------------------------------------
; Naive way 3 - preindexed addressing
; The value of R1 is incremented by each (LDRB R2, [R1, #1]!) instruction
; before it executes. This is basically the same as the last one, but requires
; fewer instructions.
; ----------------------------------------
; Print the result
ADR R0, msgAuto;
SVC 3;
; Clear R0 since we'll keep the sum in there
MOV R0, #0
ADR R1, table;
LDRB R2, [R1];
ADD R0, R0, R2;
LDRB R2, [R1, #1]!;
ADD R0, R0, R2;
LDRB R2, [R1, #1]!;
ADD R0, R0, R2;
LDRB R2, [R1, #1]!;
ADD R0, R0, R2;
; Print the result
SVC 4;
ADR R0, newline;
SVC 3;
; ----------------------------------------
; External count register (Base + offset addressing, with offset in a register)
; Here, we keep a pointer to the start of the table (R1), then we increment an
; offset (R3) by one every time.
; ----------------------------------------
; Print the result
ADR R0, msgReg;
SVC 3;
; Clear R0 since we'll keep the sum in there
MOV R0, #0
MOV R3, #0 ; Keep a count
ADR R1, table ; Load a pointer to the table into R1
loop LDRB R2, [R1, R3]; Load the value of memory at address R1 + R3
ADD R3, R3, #1 ; Increment R3
ADD R0, R0, R2 ; Add R2 to the sum
CMP R3, #(tableEnd - table); Have we reached the end of the table?
BLT loop ; If we have not, then loop around.
; Print the result
SVC 4;
ADR R0, newline;
SVC 3;
; ----------------------------------------
; Increment pointer (post indexed addressing)
; We use one less register here (and one less ADD), since we increment R1 every
; time. Since we're using post indexed addressing, R1 is updated *after* each
; 'LDRB R2, [R1], #1' instruction
; ----------------------------------------
; Print the result
ADR R0, msgPost;
SVC 3;
; Clear R0 since we'll keep the sum in there
MOV R0, #0
ADR R1, table ; Load the address of the table
loop2 LDRB R2, [R1], #1 ; Load the byte at the address pointed to by R1.
; Then increment R1
ADD R0, R0, R2 ; Add R2 to the sum
CMP R1, #tableEnd; See if we've reached the end of the table
BLT loop2 ; Loop if we've not
; Print the result
SVC 4;
ADR R0, newline;
SVC 3;
; Stop
SVC 2;
@cirosantilli
Copy link

cirosantilli commented Jul 21, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment