0% found this document useful (0 votes)
26 views9 pages

Mips Data Notes

Uploaded by

st.andrews.eve
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views9 pages

Mips Data Notes

Uploaded by

st.andrews.eve
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

The Memory Subsystem Accessing Memory on the MIPS

• memory subsystem typically provides capability to load or store bytes • addresses are 32 bit (but there are 64-bit MIPS CPUs)
• each byte has unique address, think of: • only load/store instructions access memory on the MIPS
• memory as implementing a gigantic array of bytes • 1 byte (8-bit) loaded/stored with lb/sb
• and the address is the array index
• 2 bytes (16-bit) called a half-word, loaded/stored with lh/sh
• addresses are 32 bit on the MIPS CPU we are using
• 4 bytes (32-bits) called a word, loaded/stored with lw/sw
• most general purpose computers now use 64-bit addresses (and there are
• memory address used for load/store instructions is sum of a specified register
64-bit MIPS)
and a 16-bit constant (often 0) which is part of the instruction
• typically small group of (1,2,4,8,..) bytes can be loaded/stored in single
• for sb & sh operations low (least significant) bits of source register are used.
operations
• lb/lh assume byte/halfword contains a 8-bit/16-bit signed integer
• general purpose computers typically have complex caching systems to
improve memory performance (not covered in this course) • high 24/16-bits of destination register set to 1 if 8-bit/16-bit integer negative

• operating systems on general purpose computers - typically provide virtual • unsigned equivalents lbu & lhu assume integer is unsigned
memory (covered later in this course) • high 24/16-bits of destination register always set to 0
1 2

MIPS Load/Store Instructions Code example: storing and loading a value (no labels)

assembly meaning bit pattern # simple example of load & storing a byte
lb rt , I(rs ) rt = mem[rs +I] 100000ssssstttttIIIIIIIIIIIIIIII # we normally use directives and labels
lh rt , I(rs ) rt = mem[rs +I] | 100001ssssstttttIIIIIIIIIIIIIIII main:
mem[rs +I+1] << 8 li $t0, 42
lw rt , I(rs ) rt = mem[rs +I] | 100011ssssstttttIIIIIIIIIIIIIIII li $t1, 0x10000000
mem[rs +I+1] << 8 | sb $t0, 0($t1) # store 42 in byte at address 0x10000000
mem[rs +I+2] << 16 | lb $a0, 0($t1) # load $a0 from same address
mem[rs +I+3] << 24 li $v0, 1 # print $a0
sb rt , I(rs ) mem[rs +I] = rt & 0xff 101000ssssstttttIIIIIIIIIIIIIIII syscall
sh rt , I(rs ) mem[rs +I] = rt & 0xff 101001ssssstttttIIIIIIIIIIIIIIII li $a0, '\n' # print '\n'
mem[rs +I+1] = rt >> 8 & 0xff li $v0, 11
sw rt , I(rs ) mem[rs +I] = rt & 0xff 101011ssssstttttIIIIIIIIIIIIIIII syscall
mem[rs +I+1] = rt >> 8 & 0xff li $v0, 0 # return 0
mem[rs +I+2] = rt >> 16 & 0xff jr $ra
mem[rs +I+3] = rt >> 24 & 0xff source code for load_store_no_label.s

3 4
Assembler Directives Code example: storing and loading a value

# simple example of load & storing a byte


SPIM has directive to initialize memory and associate labels with addresses. main:
li $t0, 42
.text # following instructions placed in text
la $t1, x
.data # following objects placed in data
sb $t0, 0($t1) # store 42 in byte at address labelled x
.globl # make symbol available globally
lb $a0, 0($t1) # load $a0 from same address
a: .space 18 # int8_t a[18];
li $v0, 1 # print $a0
.align 2 # align next object on 4-byte addr
syscall
i: .word 2 # int32_t i = 2;
li $a0, '\n' # print '\n'
v: .word 1,3,5 # int32_t v[3] = {1,3,5};
li $v0, 11
h: .half 2,4,6 # int16_t h[3] = {2,4,6};
syscall
b: .byte 7:5 # int8_t b[5] = {7,7,7,7,7};
li $v0, 0 # return 0
f: .float 3.14 # float f = 3.14;
jr $ra
s: .asciiz "abc" # char s[4] {'a','b','c','\0'};
.data
t: .ascii "abc" # char s[3] {'a','b','c'};
x: .space 1 # set aside 1 byte and associate label x with its
source code for load_store.s

5 6

Testing Endian-ness Setting A Register to An Address

C MIPS
• Note the la (load address) instruction is used to set a register to a labelled
uint8_t b; li $t0, 0x03040506 memory address.
uint32_t u; la $t1, u
la $t8, start
u = 0x03040506; sw $t0, 0($t1) # u = 0x03040506;
// load first byte of u lb $a0, 0($t1) # b = *(uint8_t *)&u;
• The memory address will be fixed before the program is run, so this differs
b = *(uint8_t *)&u; li $v0, 1 # printf("%d", a0);only syntatctically from the li instruction.
// prints 6 if little-endian syscall
// and 3 if big-endian li $a0, '\n' • For example, if vec is the label for memory address 0x10000100 then these
# printf("%c", '\n');
printf("%d\n", b); li $v0, 11 two instructions are equivalent:
source code for endian.c
syscall la $t7, vec
li $v0, 0 # return 0 li $t7, 0x10000100
jr $ra
.data • In both cases the constant is encoded as part of the instruction(s).
u: • Neither la or li access memory - they are very different to the lw
.space 4
source code for endian.s
instruction.

7 8
Specifying Addresses - some SPIM short cuts SPIM memory layout

• SPIM allows the constant which is part of load & store instructions can be
omitted in the common case it is 0.
sb $t0, 0($t1) # store $t0 in byte at address in $t1
sb $t0, ($t1) # same Region Address Notes
text 0x00400000 instructions only; read-only; cannot expand
• For convenience, SPIM allows addresses to be specified in a few other ways data 0x10000000 data objects; read/write; can be expanded
and will generate appropriate real MIPS instructions stack 0x7fffefff grows down from that address; read/write
sb $t0, x # store $t0 in byte at address labelled x k_text 0x80000000 kernel code; read-only
sb $t1, x+15 # store $t1 15 bytes past address labelled x only accessible in kernel mode
sb $t2, x($t3) # store $t2 $t3 bytes past address labelled x k_data 0x90000000 kernel data’
only accessible in kernel mode
• These are effectively pseudo-instructions.
• You can use these short cuts but won’t help you much
• Most assemblers have similar short cuts for convenience

9 10

Global/Static Variables add: local variables in registers

• global/static variables need appropriate number of bytes allocated in data C MIPS


segment using .space: int main(void) { main:
double val; val: .space 8 int x, y, z; # x in $t0
char str[20]; str: .space 20 x = 17; # y in $t1
int vec[20]; vec: .space 80 y = 25; # z in $t2
z = x + y; li $t0, 17
initialized to 0 by default, other directives allow initialization to other values: li $t1, 25
int val = 5; val: ..double 5 add $t2, $t1, $t0
int arr[4] = {9,8,7,6}; arr: .word 9, 8, 7, 6
char msg[7] = "Hello\n"; msg: .asciiz "Hello\n" // ...

11 12
add variables in memory (uninitialized) add variables in memory (initialized)

C MIPS (.text)
int x, y, z; main: C MIPS .text
int main(void) { li $t0, 17 # x = 17; int x=17, y=25, z; main:
x = 17; la $t1, x int main(void) { la $t0, x
y = 25; sw $t0, 0($t1) z = x + y; lw $t1, 0($t0)
z = x + y; li $t0, 25 # y = 25; } la $t0, y
} la $t1, y lw $t2, 0($t0)
sw $t0, 0($t1) add $t3, $t1, $t2 # z = x + y
la $t0, x la $t0, z
MIPS .data
MIPS (.data) lw $t1, 0($t0) sw $t3, 0($t0)
la $t0, y .data
.data la $t0, z
lw $t2, 0($t0) x: .word 17 source code for add_memory_initialized.s

x: .space 4 y: .word 25
add $t3, $t1, $t2 # z = x + y
y: .space 4 z: .space 4
la $t0, z
z: .space 4
sw $t3,
source code for add_memory.s
0($t0)

13 14

add variables in memory (array) store value in array element - example 1

C MIPS .text C MIPS

int x[] = {17,25,0}; main: int x[10]; main:


int main(void) { la $t0, x li $t0, 3
x[2] = x[0] + x[1]; lw $t1, 0($t0) int main(void) { # each array element
} lw $t2, 4($t0) // sizeof x[0] == 4 # is 4 bytes
add $t3, $t1, $t2 # z = x + y x[3] = 17; mul $t0, $t0, 4
sw $t3, 8($t0) } la $t1, x
source code for add_memory_array.s
add $t2, $t1, $t0
MIPS .data
li $t3, 17
.data sw $t3, 0($t2)
# int x[] = {17,25,0} .data
x: .word 17,25,0 x: .space 40

15 16
store value in array element - example 2 Printing Array: C to simplified C

C MIPS C Simplified C
#include <stdint.h> main: int main(void) { int main(void) {
li $t0, 13 int i = 0; int i = 0;
int16_t x[30]; # each array element while (i < 5) { loop:
# is 2 bytes printf("%d\n", numbers[i]); if (i >= 5) goto end;
int main(void) { mul $t0, $t0, 2 i++; printf("%d", numbers[i]);
// sizeof x[0] == 2 la $t1, x } printf("%c", '\n');
x[13] = 23; add $t2, $t1, $t0 return 0; i++;
} li $t3, 23 }
source code for print5.c
goto loop;
sh $t3, 0($t2) end:
.data return 0;
x: .space 60 }
source code for print5.simple.c

17 18

Printing Array: MIPS Printing Array: MIPS (continued)


# print array of ints
# i in $t0
main:
li $t0, 0 # int i = 0;
loop:
end:
bge $t0, 5, end # if (i >= 5) goto end;
li $v0, 0 # return 0
la $t1, numbers # int j = numbers[i];
jr $ra
mul $t2, $t0, 4
.data
add $t3, $t2, $t1
numbers: # int numbers[10] = { 3, 9, 27, 81, 243};
lw $a0, 0($t3) # printf("%d", j);
.word 3, 9, 27, 81, 243
li $v0, 1 source code for print5.s
syscall
li $a0, '\n' # printf("%c", '\n');
li $v0, 11
syscall
addi $t0, $t0, 1 # i++
j loop # goto loop 19 20
Printing Array with Pointers: C to simplified C Printing Array with Pointers: MIPS

# p in $t0, q in $t1
C Simplified C
main:
int main(void) { int main(void) { la $t0, numbers # int *p = &numbers[0];
int *p = &numbers[0]; int *p = &numbers[0]; la $t0, numbers # int *q = &numbers[4];
int *q = &numbers[4]; int *q = &numbers[4]; addi $t1, $t0, 16 #
while (p <= q) { loop: loop:
printf("%d\n", *p); if (p > q) goto end; bgt $t0, $t1, end # if (p > q) goto end;
p++; int j = *p; lw $a0, 0($t0) # int j = *p;
} printf("%d", j); li $v0, 1
return 0; printf("%c", '\n'); syscall
}
source code for pointer5.c
p++; li $a0, '\n' # printf("%c", '\n');
goto loop; li $v0, 11
end: syscall
return 0; addi $t0, $t0, 4 # p++
}
source code for pointer5.simple.c j loop # goto loop
end:
source code for pointer5.s
21 22

Printing 1-d Arrays in MIPS - v1 Example C with unaligned accesses


C MIPS
int vec[5]={0,1,2,3,4}; # ...
// ... li $s0, 0
int i = 0 loop:
while (i < 5) { bge $s0, 5, end
printf("%d", vec[i]); la $t0, vec uint8_t bytes[32];
i++; mul $t1, $s0, 4 uint32_t *i = (int *)bytes[1];
} add $t2, $t1, $t0 // illegal store - not aligned on a 4-byte boundary
// .... lw $a0, ($t2) *i = 0x03040506;
li $v0, 1 printf("%d\n", bytes[1]);
• i in $s0
source code for unalign.c
syscall
addi $s0, $s0, 1
b loop
end:
# ...
.data
vec: .word 0,1,2,3,4 23 24
Example MIPS with unaligned accesses Example MIPS with unaligned accesses

.data
li $t0, 1
# data will be aligned on a 4-byte boundary
sb $t0, v1 # will succeed because no alignment needed
# most likely on at least a 128-byte boundary
sh $t0, v1 # will fail because v1 is not 2-byte aligned
# but safer to just add a .align directive
sw $t0, v1 # will fail because v1 is not 4-byte aligned
.align 2
sh $t0, v2 # will succeeed because v2 is 2-byte aligned
.space 1
sw $t0, v2 # will fail because v2 is not 4-byte aligned
v1: .space 1
sh $t0, v3 # will succeeed because v3 is 2-byte aligned
v2: .space 4
sw $t0, v3 # will fail because v3 is not 4-byte aligned
v3: .space 2
sh $t0, v4 # will succeeed because v4 is 2-byte aligned
v4: .space 4
sw $t0, v4 # will succeeed because v4 is 4-byte aligned
.space 1
sw $t0, v5 # will succeeed because v5 is 4-byte aligned
.align 2 # ensure e is on a 4 (2**2) byte boundary
sw $t0, v6 # will succeeed because v6 is 4-byte aligned
v5: .space 4
li $v0, 0
.space 1
jr $ra # return
v6: .word 0 # word directive aligns on 4 byte boundary source code for unalign.s
source code for unalign.s

25 26

Data Structures and MIPS Printing 1-d Array in MIPS -v2

C data structures and their MIPS representations:


C MIPS
• char ... as byte in memory, or register int vec[5]={0,1,2,3,4}; li $s0, vec
• int ... as 4 bytes in memory, or register // ... la $t0, vec
int *p = &vec[0]; add $s1, $t0, 16
• double ... as 8 bytes in memory, or $f? register
int *end = &vec[4]; loop:
• arrays ... sequence of bytes in memory, elements accessed by index while (p <= end) { bgt $s0, $s1, end
(calculated on MIPS) int y = *p; lw $a0, 0($s0)
printf("%d", y); li $v0, 1
• structs ... sequence of bytes in memory, accessed by fields (constant offsets
p++; syscall
on MIPS)
} addi $s0, $s0, 4
A char, int or double // .... b loop
• can be stored in register if local variable and no pointer to it • p in $s0 end:
• end in $s1 .data
• otherwise stored on stack if local variable vec: .word 0,1,2,3,4
• stored in data segment if global variable
27 28
Computing sum of 2-d Array : C Computing sum of 2-d Array : MIPS

Assume we have a 2d-array:


int32_t matrix[6][5];

We can sum its value like this in C


int row, col, sum = 0;
// row-by-row
for (row = 0; row < 6; row++) {
// col-by-col within row
for (col = 0; col < 5; row++) {
sum += matrix[row][col];
}
}

MIPS directives for an equivalent 2d-array


mips .data matrix: .space 120 # 6 * 5 == 30 array elements
each 4 bytesmips .text
29 30
“‘
Computing sum of 2-d Array : MIPS Structs in MIPS

li $s0, 0 # sum = 0
li $s2, 0 # row = 0
loop1: bge $s2, 6, end1 # if (row >= 6) break
li $s4, 0 # col = 0
loop2: bge $s4, 5, end2 # if (col >= 5) break
la $t0, matrix
mul $t1, $s2, 20 # t1 = row*rowsize
mul $t2, $s4, 4 # t2 = col*intsize
add $t3, $t0, $t1 # offset = t0+t1
add $t4, $t3, $t2 # offset = t0+t1
lw $t5, 0($t4) # t0 = *(matrix+offset)
add $s0, $s0, $t5 # sum += t0
addi $s4, $s4, 1 # col++
j loop2
end2: addi $s2, $s2, 1 # row++
j loop1
end1: 31 32
Implementing Structs in MIPS Implementing Structs in MIPS

C struct definitions effectively define a new type.


// new type called "struct student" Accessing structure components is by offset, not name
struct student {...}; li $t0 5012345
// new type called student_t la $t1, stu1
typedef struct student student_t; sw $t0, 0($t1) # stu1.id = 5012345;
li $t0, 3778
Instances of structures can be created by allocating space: sw $t0, 44($t1) # stu1.program = 3778;
# sizeof(Student) == 56
stu1: # student_t stu1; la $s1, stu2 # stu = &stu2;
.space 56 li $t0, 3707
stu2: # student_t stu2; sw $t0, 44($s1) # stu->program = 3707;
.space 56 li $t0, 5034567
stu: sw $t0, 0($s1) # stu->id = 5034567;
.space 4 # student_t *stu;

33 34

You might also like