410 likes | 521 Views
Intro to Computer Org. MIPS Assembly – Program Implementation. Composition of Programs. As we referenced before, all computer programs are represented as binary data. This data must first be loaded into memory, then jumped to by an operating system in order to execute. Composition of Programs.
E N D
Intro to Computer Org. MIPS Assembly – Program Implementation
Composition of Programs • As we referenced before, all computer programs are represented as binary data. • This data must first be loaded into memory, then jumped to by an operating system in order to execute.
Composition of Programs • We know that programs are composed of multiple segments. • Static data (compile-time constants) • Instructions (the part that runs) • Others we’ll see shortly • Dynamic data (requested at run-time) • A stack (useful for temporary data, facilitates use of functions)
Composition of Programs • Not all components of a program can be properly represented by assembly instructions. • To represent these other elements, assembly languages provide directives that allow for further specifications.
Assembler Directives • Some directives are used to specify the memory layout of the program. • .text • Code segment • .data • Data segment
Assembler Directives • Instructions and static data are placed toward the beginning of memory. • Dynamic data and the stack are free to grow during execution and are placed on opposite sides of the remaining memory.
Code Segment • .text must be the last segment-defining directive before a program’s instructions.
Data Segment • .data must be the last segment-defining directive before a program’s static data. • Consists of all data that must be globally accessible or memory-bound data that is known during compilation. • Global variables • Large constants, like strings or fixed-size arrays.
Data Segment • There are many directives designed for use within the .data segment to declare any statically-used memory the compiler/programmer may need.
Data Segment • .byte<byte1>, …, <byteN> • Allocates memory for N bytes in a row, initializing them to the given values. • .half<half1>, …, <halfN> • The same, for half-word values. • .word<word1>, …, <wordN> • The same, for word-length values.
Data Segment • Use a label on the same line as one of these directives in order to treat that line’s value(s) as an array of length N. • Remember to adjust for the data’s byte size on any loads or stores.
Data Segment • a: .word 5 • a is an array of words with length 1. • Can also think of it as a pointer to a word. • The lone entry in the array has value 5. • b: .word 1, 2, 3, 4, 5 • b is an array of words with length 5. • The entries, in order, are 1, 2, 3, 4, and 5.
Data Segment • .asciiz<string> – Declares a string and null-terminates it. • Each character takes up a single byte of space. • Is equivalent to: • .byte<char1>, …, <charN>, 0 • In C, C++, and Java, strings are null-terminated, meaning there is an extra byte equaling 0 at the end.
Data Segment • prompt: .asciiz “Hello World!” • Defines a string called prompt with the value “Hello World!”. • This can be used directly with the syscalls we will learn about shortly.
Data Segment • .spacen - Allocates n bytes of memory for future use. • Useful if you wish to make a data structure of a particular size, or just to define a large array of any numerical type. • Instead of .word 0, 0, …, 0 for 100 0’s, .space 400 will allocate that for you.
Data Segment • .alignn – Sets the next element of data on a 2n memory address boundary. • This is important because loads and stores must be aligned on an appropriate boundary. • If the next element of data is a word, use n =2, for example. (Half-word => n = 1.) • Errors easily result from ignoring this.
Data Segment - Example • Write a program to find the sum of four integers specified in an array called ints. • Run it with ints = [34, -7, 18, 23]. • Try a few other values.
.data ints: .word 34, -7, 18, 23 .text .globl main main: la $t0, ints li $t1, 4 li $v0, 0 sum: lw $t3, 0($t0) add $v0, $v0, $t3 #Go to the next element addi $t0, $t0, 4 #Decrement count of ints addi $t1, $t1, -1 bne $t1, $0, sum #result is in $v0 jr $ra Data Segment - Example
System Calls • Since we’re using PCSpim to run our MIPS code, we have access to a few special facilities known as system calls, or syscalls, for short. • Each one takes care of some basic, yet somewhat complex task, on behalf of the programmer.
System Calls • Each system call is performed by setting $v0 to the appropriate code, then using the instruction syscall in order to perform the operation. • Ex: li $v0, 10 syscall #The exit syscall.
System Calls • Some syscalls take arguments – the first argument will be in $a0, and the second argument will be in $a1. • Ex: li $v0, 1 li $a0, 37 syscall #Prints 37.
System Calls • Some syscalls return values, placing that value in $v0. • Ex: li $v0, 5 syscall #Gets int from the user, #puts it in $v0.
System Calls • syscall 1 – Prints the integer found in $a0. • syscall 4 – Prints the string found at the address in $a0. • Combined with the earlier label prompt, we can use this to say “Hello World!”.
System Calls • syscall 5 – Reads in an integer from the console, places the value in $v0. • syscall 8 – Reads a string of at most $a1 bytes into a buffer at the address in $a0. • Warning – this includes the null-termination character!
System Calls • syscall 10 – the equivalent of System.exit() in Java. • Automatically terminates the program.
System Calls • syscall 9 – Allocates $a0 bytes dynamically (i.e., at run time), giving the address of said bytes in $v0. • This is the equivalent of the following line in Java-like form. byte[] $v0 = new byte[$a0];
System Calls • syscall 9 – Allocates $a0 bytes dynamically (i.e., at run time), giving the address of said bytes in $v0. • It can also be seen as the run-time equivalent of the .space directive. • Called sbrk on the some reference.
System Calls • Dynamic data and the stack are free to grow during execution and are placed on opposite sides of the remaining memory. • We’ll learn about the purpose of the stack in a few lectures.
System Calls – Example 1 • Write a program to find the sum of four integers specified by the user. • Store them in an array first, and perform the summation after getting all of the integers. (For practice.) • Run it with ints = [34, -7, 18, 23]. • Try a few other values.
.data ints: .space 16 prompt: .asciiz “Enter an int: ” result: .asciiz “Sum: “ .text .globl main main: la $t0, ints li $t1, 4 input: la $a0, prompt li $v0, 4 syscall #Give prompt li $v0, 5 syscall #Get int sw $v0, 0($t0) addi $t0, $t0, 4 addi $t1, $t1, -1 bne $t1, $0, input System Calls – Example 1
input: la $a0, prompt li $v0, 4 syscall #Give prompt li $v0, 5 syscall #Get int sw $v0, 0($t0) addi $t0, $t0, 4 addi $t1, $t1, -1 bne $t1, $0, input inputDone: la $t0, ints li $t1, 4 li $t2, 0 sum: lw $t3, 0($t0) add $t2, $t2, $t3 addi $t0, $t0, 4 addi $t1, $t1, -1 bne $t1, $0, sum System Calls – Example 1
inputDone: la $t0, ints li $t1, 4 li $t2, 0 sum: lw $t3, 0($t0) add $t2, $t2, $t3 addi $t0, $t0, 4 addi $t1, $t1, -1 bne $t1, $0, sum sumDone: li $v0, 4 la $a0, result syscall #Give text li $v0, 1 move $a0, $t2 syscall #Print result jr $ra System Calls – Example 1
System Calls – Example 2 • Write a program that takes two strings (from memory) and concatenates them together. • Use lbu and sb to operate on byte-sized data. • (load byte unsigned / store byte) • Note that we aren’t given the length of the strings. • Try it on “Hello ” + “World!”.
System Calls – Example 2 • Write a program that takes two strings (from memory) and concatenates them together. • Find lengths of each string. • Allocate space for the new string. • Copy each string until the null-termination character. • Write null-termination character.
.data str1: .asciiz “Hello ” str2: .asciiz “World!” .text .globl main main: li $t0, -1 li $t1, -1 la $t2, str1 la $t3, str2 getLen1: lb $t4, 0($t2) addi $t0, $t0, 1 addi $t2, $t2, -1 bne $t4, $0, getLen1 System Calls – Example 2
main: li $t0, -1 li $t1, -1 la $t2, str1 la $t3, str2 getLen1: lb $t4, 0($t2) addi $t0, $t0, 1 addi $t2, $t2, 1 bne $t4, $0, getLen1 getLen2: lb $t4, 0($t3) addi $t1, $t1, 1 addi $t3, $t3, 1 bne $t4, $0, getLen2 #$t0 = length(str1) #$t1 = length(str2) add $a0, $t0, $t1 addi $a0, $a0, 1 System Calls – Example 2
getLen2: lb $t4, 0($t3) addi $t1, $t1, 1 addi $t2, $t2, 1 bne $t4, $0, getLen1 #$t0 = length(str1) #$t1 = length(str2) add $a0, $t0, $t1 addi $a0, $a0, 1 #$a0 = needed bytes for #str1 + str2. li $v0, 9 #$a0 is loaded. syscall move $t5, $v0 move $t6, $v0 #$t5 & $t6 now hold the #final string’s address. la $t2, str1 la $t3, str2 System Calls – Example 2
#$a0 = needed bytes for #str1 + str2. li $v0, 9 #$a0 is loaded. syscall move $t5, $v0 move $t6, $v0 #$t5 & $t6 now hold the #final string’s address. la $t2, str1 la $t3, str2 cpyStr1: lb $t4, 0($t2) #Skip to next loop #if it’s ‘/0’. beq $t4, $0, cpyStr2 sb $t4, 0($t5) addi $t2, $t2, 1 addi $t5, $t5, 1 j cpyStr1 System Calls – Example 2
cpyStr1: lb $t4, 0($t2) #Skip to next loop #if it’s ‘/0’. beq $t4, $0, cpyStr2 sb $t4, 0($t5) addi $t2, $t2, 1 addi $t5, $t5, 1 j cpyStr1 cpyStr2: lb $t4, 0($t3) #Skip to next loop #if it’s ‘/0’. beq $t4, $0, cpyDone sb $t4, 0($t5) addi $t3, $t3, 1 addi $t5, $t5, 1 j cpyStr2 System Calls – Example 2
cpyStr2: lb $t4, 0($t3) #Skip to next loop #if it’s ‘/0’. beq $t4, $0, cpyDone sb $t4, 0($t5) addi $t3, $t3, 1 addi $t5, $t5, 1 j cpyStr2 cpyDone: #Now we null-terminate #and display the result. sb $0, 0($t5) #Original final string #address is in $t6. move $a0, $t6 li $v0, 4 syscall jr $ra System Calls – Example 2