Assembly Language and Control Flow Flashcards
Assembly Operands: Memory
Memory can be thought of as a single one-dimensional array each cell stores a byte size value
Data is stored in memory as: __
Each register is 32-bits which is the size of a “word”
Data is stored in memory as: variables, arrays, structures
Assembly language is focused on high performance. Thus, given differences between registers and memory , programmers should …..:
Programmers should minimize the number of instructions
Registers are fast (1 ns)
Memory is slow (100 ns)
loading and storing has its costs and benefits
ARM is LOAD/STORE architecture
- does not support memory to emory data processing operations
- must move data values into registers before using them
loading data values from memory into registers done in hardware in parallel
process data in registers using a number of data processing instructions. which are not slowed down by memory access
store results from registers out to memory (done in background)
Memory is a “single” one-dimensional array where each cell stores a byte (size) of data
Accessed/Referred to by a 32-bit address
| 0x0a |. | 0x0b | | 0x0c |. | 0x0d |
0x 4000 0x 4001 0x 4002 0x 4003
ARM arithmetic instructions only operate on registers , never directly on memory
Data transfer instructions transfer data between register and memory
- LOAD from memory to register
- STORE from register to memory
ARM has 3 sets of instructions with interact with main memory
- single register data transfer (LDR/STR)
- Block data transfer (LDM/STM) * not for CSE30
- Single Data Swap (SWP) * not for CSE 30
Load
LDR and STR store one word (32-bits)
LDRB / STRB store a byte
LDRH / STRH store halfword or 16bits
LDRSB stores signed byte load
LDRSH stores signed halfword load
Memory systems must support all access sizes
Syntax is :
LDR. [<address>]
STR [address>]
</address>
Data Transfer: Memory to REgister
To transfer a word of Data, we need to specify two things:
Register:
R0 - R15
Memory Address: (more difficult)
-How do we specify memory address of data to operate on?
Remember we load value/data FROM memory
Addressing Modes
There are many ways in ARM to specify the address these are called addressing modes
.
Given CMP R4, R2 which condition code bits would need to be set to indicate that R4== R2
Z
Given the following code, elect the appropriate instruction to go in blank :
i = 10; j = 1; while (i > 0){ j = j + i; i--; }
mov R2, #10 ; i/R2 = 10 mov R3, #1 ; j/R3 = 1 lp: cmp R2, #0 ; while (i > 0){ \_\_\_\_\_ ; . add R3, R3, R2 ; j/R3 = j/R3 + i/R2; sub R2, R2, #1 ; i/R2 = i/R2 - 1; b lp ; } done:
ble done
The ARM instruction CMP:
Sets bits in the CPSR
Which of the following is true the following instruction
ldr r0, [r1, r2]
r0 is loaded with the contents of memory location r1 + r2
Assume we have an array ARR of ints whose base address (lowest address is 0x1a0000). Assume R1 == 0x1a0000
Given the C statement: j = ARR[12], which assembler instruction is best used to load j (assume j is represented by R3. Assume sizeof(int) == 4 bytes.
ldr r3, r1, #0x30
Given the following piece of code that scans an array of 8-bit values for “-1”. choose the appropriate instruction to fill in the blank:
loop: _________ // while (arr[i] != -1) {
cmp r3, #-1 // .
beq done // .
add r1, r1, #1 // i = i + 1
b loop // }
done:
ldrsb r3, [r1]
Y = &X
STR R1 , [R2]
Y = *X
LDR R2, [R1]
X = arr[4]
LDR R2 , [R1, #16]
Pointers Vs. Values
Effective Addres is CALCULATED
Effective Address =
Offset can be specified in different was
Load INstruction LDR - the memory address of the data that we want to retiree from memory
Store Instruction (STR) - the memory address where we want to write the value which is currently in a register
[R0] - specifies the memory address pointed to by the value in R0
Data Transfer: Memory to Register
Load Instruction Syntax
Load Instruction Syntax: 1 2, [3] • where 1) operation name 2) register that will receive value 3) register containing pointer to memory
X is in register r1 and Y is in r2
LDR r2, [r1]
ARM Instruction Name:
• LDR (meaning Load Register, so 32 bits or one word are loaded at a time)
Y = *X
LDR r2,[r1]
This instruction will take the address in r1, and then load a 4 byte value from the memory pointed to by it into register r2
r1 is called the base register
r1 = 0x200 (base register) 0x200 = 0xaa 0x201 0xbb 0x202 = 0xcc 0x203 - 0xdd
R2 will become 0xddccbbaa
STR r2,[r1]
This instruction will take the address in r1, and then store a 4 byte value from the register r2 to the memory pointed to by r1.
r1 is called the base register
r1 = 0x200 (base register) 0x200 = 0xaa 0x201 0xbb 0x202 = 0xcc 0x203 - 0xdd
R2 will become 0xddccbbaa
Big Endian and Little Endian
.
A stack follows the last in first out (LIFO) principle (operations: push, pop). The stack data structure is implemented based on either an array or a linked-list.
.
Callee SAve Rule: Before a callee disturbs any of the preserved registers (R4-R11 and LR) , it must save the registers. Before it returns it must restore these registers
According to the callee save rule, factorial is a nonleaf function and must save LR. According to the caller save rule, factorial will need n after calling itself, so it must save R0. Hence, it pushes both registers onto the stack at the start. It then checks whether n ≤ 1. If so, it puts the return value of 1 in R0, restores the stack pointer, and returns to the caller. It does not have to reload LR and R0 in this case, because they were never modified. If n > 1, the function recursively calls factorial(n – 1). It then restores the value of n and the link register (LR) from the stack, performs the multiplication, and returns this result. Notice that the function cleverly restores n into R1, so as not to overwrite the returned value. The multiply instruction (MUL R0, R1, R0) multiplies n (R1) and the returned value (R0) and puts the result in R0.
A recursive function is a nonleaf function that calls itself. Recursive functions behave as both caller and callee and must save both preserved and nonpreserved registers.
Recall that factorial(n)=n × (n – 1) × (n – 2) × ⋯ × 2 × 1. The factorial function can be rewritten recursively as factorial(n) = n × factorial(n – 1), as shown in Code Example 6.27. The factorial of 1 is simply 1.
View H&H regarding stack pointer changing locations throughout a facotrial function pg 327.
pg 327.IT starts at a location and moves “down” , getting smaller, then moves back “up” getting bigger in its memory address value
A nonleaf function overwrites LR when it calls another function using BL. Thus, a nonleaf function must always save LR on its stack and restore it before returning.
.
View H&H regarding stack pointer changing locations throughout a factorial function pg 327.
pg 327.IT starts at a location and moves “down” , getting smaller, then moves back “up” getting bigger in its memory address value
SP is the stack pointer, FP is the frame pointer. In each of our functions, we want to make sure that FP points to the start of our stack frame. If we have only stored FP and LR on the stack, we can simply do ADD FP, SP, #4 after pushing FP and LR to the stack to ensure FP points to the start of our stack frame.
%esp is commonly refered to as the stack pointer
%ebp is commonly referred to as the frame pointer