1 Review: ARM Instruction Set There are three main types of instructions Data transfer Data processing Flow control 2 Review: ARM Instruction Set There are three main types of instructions Data transfer Data processing Flow control 3 Review: Data transfer instructions Move data between registers and memory ARM processors are RISC (otherwise known as load/store) processors so all data in memory MUST be loaded into a register before it can be used. 4 Review LDR Load instructions copy data from memory to a register Syntax Curly brackets mean optional (we will ignore these for now) LDR{size} {cond} Rd, [address] opcode LDR Rd, [Rn] destination register Memory address // Load data into Rd using the address in Rn LDR Rd, [Rn, #offset] // Load data into Rd using the address in Rn + an offset LDR Rd, [Rn, Rm] // Load data into Rd using the address in Rn + an offset from Rm LDR Rd, [Rn, Rm, LSL #n] // Load data into Rd using the address calculated as Rn + data in Rm*2^n 5 Review: Load pseudo instruction (LDR) LDR Rd, =C // Load a 32 bit constant C into Rd – C can be decimal (default) or hexadecimal (0x prefix) or binary (0b prefix) 6 Review STR Store instructions copy data from registers to memory Syntax Optional STR{size}{cond} Rt, [address] opcode STR Rt, [Rn] Memory address source register // Store the data in Rt to memory using the address held in Rn STR Rt, [Rn, #offset] // Store the data in Rt to the address Rn + #offset STR Rt, [Rn, Rm] // Store the data in Rt to the address Rn + Rm STR Rt, [Rn, Rm, LSL #n] // Store the data in Rt to the address Rn + data in Rm*2^n 7 Review: Reading and Writing to GPIO GPIO ports are memory mapped input-output ports Storing to a GPIO’s memory address results in voltages appearing on the GPIO pins Loading from a GPIO’s address reads the voltages on GPIO pins into binary data E.g: Read status of GPIOA pins and copy it to GPIOB .equ GPIOA_IDR, 0x40010808 .equ GPIOB_ODR, 0x40010C0C LDR R0, =GPIOA_IDR LDR R1, [R0] LDR R0, =GPIOB_ODR STR R1, [R0] // GPIOA input data reg // GPIOB output data reg // GPIOA input data register location // Load GPIOA’s input bits to R1 // GPIOB output data register address // Store data from GPIOA to GPIOB 8 Review: Bitfields Using bitfields we can extract just some bits, ignoring the rest A bitfield is an arbitrary number of bits (<32) inside a word which require manipulation without affecting the rest of the bits start bit in source register width of bits to copy from source register UBFX{cond} Rd, Rn, #lsb, #width source register opcode destination register 9 Review: ARM Instruction Set Data transfer Data processing Flow control 10 Review: Arithmetic and logical instructions Syntax: Optional OP{S}{cond} Rd, Rn, operand2 2nd operand opcode ADD SUB ADC SBC destination register Add Subtract Add with carry Subtract with carry 1st operand register AND ORR EOR BIC ORN Logical AND Logical OR Logical XOR Logical AND NOT Logical OR NOT 11 Review: Arithmetic and Logical Instructions Operand 2 can be a register e.g. ADD R0, R1, R2 // R0 = R1+R2 Operand 2 can also be an 8 bit immediate (8 bit constant) a decimal immediate e.g. ADD R3, R3, #1 SUB R8, R7, #0x18 // R3 = R3 + 1 // R8 = R7 - 24 a hexadecimal immediate 12 Review: Bit shifting instructions Syntax: Optional OP{S}{cond} Rd, Rn, #n Shift length opcode destination register OP{S}{cond} Rd, Rn, Rm 1st operand register Register which holds the shift length OP can be: ASR (Arithmetic shift right), LSL (Logical shift left), LSR (Logical shift right), ROR (Rotate right) etc 13 Review: ARM Instruction Set Data transfer Data processing Flow control 14 Review: Status Bits The status bits / flags are labelled N, Z, C and V: – N=1 if the operation result is negative. • In practice, N is set to the two's complement sign bit of the result (bit 31). – Z =1 if the result of an operation is zero – C=1 if unsigned operation overflows the 32-bit result register. I.e. if an add resulted in a carry – V=1 if a signed operation resulted in an overflow • I.e. if the sign of the answer does not match the sign of the operands 15 Review: Status bits For the 32 bit ARM instruction set and thumb-2 instruction set, there are two ways to set the status bits –Using the optional S flag in a data processing instruction e.g : SUBS R2, R1, R3 // Status bits N,Z,C,V are updated based on the result of R1-R3 –Using a comparison instruction e.g. CMP R2, #0 16 Review: Branch Instructions The four branch mnemonics are: B{cond} label // Branch to label BL{cond} label // Branch to label, PC copied to LR BX{cond} Rm // Branch to address in Rm BLX{cond} Rm // Branch to address in Rm, PC copied to LR The B instruction can contain a conditional execution suffix anywhere in a program In thumb-2 if any other branch instruction is conditional it must be inside an IT block (we will see this later) 17 Review: Branch Instructions Non conditional branch: B here . . . //Branch to the instruction in memory address specified by ‘here’ here: STR r1, [R2] Note: you just write ‘here:’ (or whatever more descriptive label you use in place of ‘here’) somewhere in your program. The assembler will figure out which memory address that instruction corresponds to. 18 Review: Conditional Branch Instructions Branch instructions can use the full list of conditions we saw previously but the main ones you will use are EQ equal to NE not equal to GT greater than LT less than Example 2: CMP R1, #0 BEQ label //Branch to the instruction at ‘label’ if contents of R1 are equal to 0. Otherwise move on to the next instruction in the code 19 Structure of ARM Assembly Code Broad syntax – 3 columns {label} <instruction> {//comments} • {label} and {comments} are optional – Labels are used by branch instructions • <instruction> syntax details vary between instructions GNU assembler directives – .equ – .byte – ...etc Numbers are by default decimal. Use 0x prefix for hexadecimal constants 20 ARM Instruction Set Data transfer Data processing Flow control status bits (flags) flow control instructions loops 21 Branch equal / not equal Because branch if equal (or not equal) to zero are commonly used in programming there is a dedicated branch instruction for this purpose in the thumb-2 instruction set for a branch ahead. – CBZ Rn, label //Compare, branch if zero – CBNZ Rn, label //Compare, branch if not zero CBZ is equivalent to: CMP Rn, #0 BEQ label //Branch if equal to Likewise, CBNZ is equivalent to: CMP Rn, #0 BNE label //Branch if not equal to 22 If-then blocks Thumb-2 adds IT instructions for flow control The CMP instruction compares two numbers and the IT instructions checks a specified condition and carries out an action if that condition is true. Equivalent to an ‘if then’ statement in higher level languages. Here is where that optional {cond} comes in It must be used for instructions that are part of an IT block. CMP R1, #2 // Compare R1 with 2 IT NE // if then block, ‘not equal’ condition ADDNE R0, R0, R3, LSR #8 // Executed if R1 was not equal to 2 23 If-Then Blocks Note that the condition code suffix must be written after every instruction in the IT block – This is so that Thumb-2 assembly can be compiled as ARM assembly without modification if needed later NOT correct CMP R1, #2 IT NE ADD R0, R0, R3, LSR #8 // Compare R1 with 2 // IT block, NE condition // Executed if R1 was != 2 24 If-Then Blocks If then Example 2: CMP R1, #2 IT GT SUBGT R0, R0, R3 // Compare R1 with 2 // IT block, ‘greater than’ condition // Executed if R1 > 2 25 If-then blocks In thumb-2 assembly branch (B) instructions can be conditional at any time but every other instruction with conditional execution must be inside an If-Then (IT) block. The IT instructions allows each instruction’s condition to be true or false. Instructions can execute if a condition is met (ifthen) or if the condition is not met (if-else) The IT instruction can have up to 4 condition switches The condition switch is: – T (Then) which executes the instruction if the condition is met – E (Else) which executes the instruction if the condition is not met 26 Conditional execution As an aside: In the 32 bit ARM instruction set there is no IT instruction, instead almost every 32-bit ARM instruction (not just branch) can be executed conditionally. The following will be valid code in processors using the 32-bit ARM instruction. (But not in our processor and not in ELEC1710 assessment tasks which all assume the thumb-2 instruction set.) CMP Rn, Rd ADDNE R0, R0, R3 SUBEQ R0, R0, R2, // Executed if Rn was != Rd // Executed if Rn was == 2 Note: ADDNE did not set the flags (no S condition) so the SUBEQ instruction is based on the flags set by the CMP instruction. Note 2: When an IT block is compiled as 32bit ARM code the IT line is just ignored by the compiler (this is why the condition codes must match). 27 If-Then Blocks Note that the condition code suffix must be written after every instruction in the IT block – This is so that Thumb-2 assembly can be compiled as ARM assembly without modification later if required. If then else example: CMP R1, #2 ITE NE ADDNE R0, R0, R3, LSR #8 ADDEQ R0, R0, R2, LSR #8 // Compare R1 with 2 // IT block, NE condition // Executed if R1 was != 2 // Executed if R1 was == 2 The then conditions must match the condition code, and any else conditions must be the opposite condition. 28 If-Then Blocks More generally: the IT instruction has the following syntax: – IT{x{y{z}}} condition – Where x,y and z specify the condition switch (T for ‘then’ E for ‘else’) for the 2nd, 3rd and 4th instructions in the IT block. If then then example: CMP R1, #2 ITT NE ADDNE R0, R0, R3, LSR #8 ADDNE R0, R0, R2, LSR #8 // Compare R1 with 2 // IT block, NE condition // Executed if R1 was != 2 // Executed if R1 was != 2 29 If-Then Blocks If branch instructions are inside an IT block they must always be the last instruction. Example 2: ITTE EQ ADDEQ R1, R2, R3 //Executed if EQ condition is met ANDEQ R1, #0xFF //Executed if EQ condition is met BXNE R4 //Executed if EQ condition is NOT met Unlike a B instruction, a BX instruction must be inside an IT block to be conditional 30 ITE Example In the table given, list the contents of all appropriate registers after execution of the ARM assembly instructions below. 1. 2. 3. 4. 5. 6. 7. ldr r0, = table ldrb r1, [r0] ldrb r2, [r0, #1] cmp r1, r2 ite eq addeq r3, r1, r2 addne r4, r1, #1 Line R0 1 0x08000234 2 R1 R2 R3 R4 130 3 10 4 5 6 7 1. .align 4 2. table: // The address of the table is 0x08000234 3. 4. .byte 130 5. .byte 10 6. .byte 84 7. .byte 1 8. .byte 2 131 31 Comparison Instructions Understanding how the flags are set and tested can be complicated. Requires a very good understanding of arithmetic from week 4. CMP Rn, Rd BEQ label Is somewhat straightforward. The result of Rn-Rd will be zero if Rn = Rd. From the table on slide 15, BEQ checks the zero flag which is one if and only if Rn = Rd. 32 Comparison Instructions CMP Rn, Rd BGT label Is less straightforward. GT checks (Z==0) && (N==V) Depending on the values in Rn and Rd you need to work through what the values will be for each flag E.g. Rn and Rd both positive: If Rn>Rd the condition is true since Rn-Rd will be positive N=0, no overflow will occur V=0, but they are not equal so the result won’t be zero Z=0. (However, If Rn<Rd, N=1, V=0 and so condition 33 is not true) ARM Instruction Set Data transfer Data processing Flow control status bits (flags) flow control instructions loops 34 Flow control: While loop Keep doing some activity while some condition remains true. There is no fixed number of times you loop (usually because it is unknown when the loop starts how long this will take.) C code instruction: while (i < 6){ …… } Python instruction: while i < 6: …… Matlab instruction: while (i < 6) …… end Java instruction: while (i < 5){ …… } 35 Flow control: While loop Example: Wait until the input on bit 0 of port GPIOA is low. (or in other words: while GPIOA bit 0 is high keep looping) 1. load data from GPIOA_IDR into register R1 2. mask out bit zero (i.e. all other entries of R1 are set to zero) 3. if R1 is zero we can continue on. If R1 is not zero return to Step 1 36 Flow control: While loop Wait until the input on bit 0 of port GPIOA is low. .equ GPIOA_IDR, 0x40010808 // GPIOA IDR for STM32F103 LDR R0, =GPIOA_IDR // GPIOA input data register address wait: LDR R1, [R0] // Load GPIOA’s input bits to R1 AND R1, R1, #0x01 // AND to mask out all bits except bit 0 // Compare port A bit 0 with 0 // keep looping if bit 0 of // Port A is not 0 CMP R1, #0 BNE wait 37 Flow control: For loop Repeat a certain task a fixed number of times (which will be known before the loop starts) E.g. Count up from 1 to n C code / Java instruction: for(i = 1; i < n+1; i++){ ….. } Python instruction: for i in range(1, n+1): ……….. Matlab instruction: for i = 1: n …… end 38 Flow control: For loop E.g. Count down from 524288 (0x80000) to 37 (0x24). C code instruction: Python instruction: Matlab instruction: for(i = 524288; i > 36; i--) for i in range(524288, 36, -1): for i = 524288: -1: 37 Assembly: 1. Load 0x00080000 into register R3 (R3 will hold i) 2. R3 = R3-1 3. Compare R3 to 0x24 4. If > 0x24 return to step 2, otherwise continue on 39 Flow control: For loop // This code executes a FOR loop which counts down from 524288 // (0x80000) to 37 (0x24). LDR R3, =0x00080000 loop1: SUB R3, R3, #1 CMP R3, #0x24 BGT loop1 // Set-up R3 to hold loop counter ‘i’ // Subtract 1 from the loop counter ‘i’ // Compare the loop counter ‘i’ to 37 (0x24). // If i is still > 0x24 then branch to the start of // the loop 40 Flow control: If statement If (and only if) a certain condition is true carry out a set of instructions. C code / Java instruction: if(x == 5){ ….. } Python instruction: if x == 5 : ….. Matlab instruction: if x == 5 ….. end 41 Flow control: If statement // An If statement which executes instructions if the variable in R1 // is equal to 5 CMP R1, #5 // Compare r1 and the decimal constant 5 BNE isnoteq // If R1 is not equal to 5 we jump over the // instructions for the ‘then’ part // Code executed if R1 is equal to 5 (as many lines as you need) isnoteq: // Code outside of the If 42 Flow control: If Then Else statement // An If-then-else statement which executes different instructions if // the variable in R1 is equal to 5 or not CMP R1, #5 // Compare r1 and the decimal constant 5 BEQ iseq // If R1 is equal to 5 we jump to the ‘then’ part BNE isnoteq // If R1 is not equal to 5 we jump to the ‘else’ part iseq: // Code executed if R1 is equal to 5 (as many lines as you need) B endIF isnoteq: // Code executed if R1 not equal to 5 (as many lines as needed) endIF: // Code outside of the If 43 A note on efficient use of space If program memory space is tight you will want as many of your thumb-2 instructions to be 16 bit as possible. The general rules for generating the 16 bit form of the instructions are: Use registers in the range R0-R7 Set the condition flags, unless the instruction is conditional, wherever possible Use small immediate constants where possible 44 Example 1 E.g: Write a program to add data from the GPIOA and GPIOC pins and write the result to GPIOB. The first three lines have been written for you. .equ GPIOA_IDR, 0x40010808 .equ GPIOC_IDR, 0x40011008 .equ GPIOB_ODR, 0x40010C0C // GPIOA input data reg // GPIOC input data reg // GPIOB output data reg Step 1: Plan out the flow of the program (pseudo code / flow charts / whatever works for you) • • • • Load data from GPIOA_IDR into a register - lets make it R1 Load data from GPIOC_IDR into a different register - lets make it R2 Add the data together and store the result in a register - lets make it R3 Output the data from R3 to GPIOB_ODR 45 Example 1 E.g: Write a program to add data from the GPIOA and GPIOC pins and write the result to GPIOB. The first three lines have been written for you. .equ GPIOA_IDR, 0x40010808 .equ GPIOC_IDR, 0x40011008 .equ GPIOB_ODR, 0x40010C0C // GPIOA input data reg // GPIOC input data reg // GPIOB output data reg Step 2: Replace each part with the required ARM instructions • Load data from GPIOA_IDR into R1 • Put the memory address of GPIOA_IDR into a register (say R0) • Load data from that memory address into R1 LDR R0, =GPIOA_IDR LDR R1, [R0] // GPIOA input data register location // Load GPIOA’s input bits to R1 46 Example 1 E.g: Write a program to add data from the GPIOA and GPIOC pins and write the result to GPIOB. The first three lines have been written for you. .equ GPIOA_IDR, 0x40010808 .equ GPIOC_IDR, 0x40011008 .equ GPIOB_ODR, 0x40010C0C // GPIOA input data reg // GPIOC input data reg // GPIOB output data reg LDR R0, =GPIOA_IDR LDR R1, [R0] // GPIOA input data register location // Load GPIOA’s input bits to R1 LDR R0, =GPIOC_IDR LDR R2, [R0] // GPIOC input data register location // Load GPIOC’s input bits to R2 ADD R3, R1, R2; // R3 = R1 + R2 LDR R0, =GPIOB_ODR STR R3, [R0] // GPIOB output data register address // Store sum to GPIOB 47 Example 2 In the table given, list the contents of all appropriate registers after execution of the ARM assembly instructions below. Indicate a “?” where the value is unknown (ie: not yet modified by an instruction) and “||” when a value is unchanged. You may use hex or decimal notation or a mixture of the two. 1. ldr r0, = 0x08000234 // The address of the table is 0x08000234 2. ldrb r1, [r0] 3. ldrb r2, [r0, #1] 4. add r3, r1, r2 5. add r4, r2, #10 6. add r5, r1, r2, LSL #1 7. .align 4 8. table: Line R0 R1 R2 R3 R4 9. .byte 130 1 10. .byte 10 2 11. .byte 84 3 12. .byte 1 4 13. .byte 2 R5 5 6 48 Example 2 1. ldr r0, = 0x08000234 2. ldrb r1, [r0] 3. ldrb r2, [r0, #1] 4. add r3, r1, r2 5. add r4, r2, #10 6. add r5, r1, r2, LSL #1 7. .align 4 8. table: // The address of the table is 0x08000234 9. .byte 130 10. .byte 10 11. .byte 84 R2 =10 = [0…0 1010] LSL #1 gives [0…0 0001 0100] = 20 12. .byte 1 OR 13. .byte 2 LSL = x2 and 2*R2 = 2*10 = 20 Line R0 1 R1 R2 R3 R4 R5 0x08000234 ? ? ? ? ? 2 “ ? ? ? ? 3 “ 130 ” ? ? ? 4 “ ” 10 ” ? ? 5 “ ” ” 140 ” ? 6 “ ” ” ” 20 ” 150 49 The only way to become proficient with assembly language programming is to do it. Practice! Practice! Practice! Questions? CRICOS Provider 00109J | www.newcastle.edu.au 50