210 likes | 325 Vues
Learn how to work with characters and strings in MIPS assembly language, including ASCII encoding, byte operations, string copying, and stack implementation.
E N D
Character and String Operations • Characters are encoded as 0’s and 1’s using ASCII most commonly • American Standard Code for Information Interchange • Each character is represented using 8 bits (or a byte) • MIPS provides instructions to move bytes • Load byte (lb) loads a byte to the rightmost 8 bits of a register • Store byte (sb) write the rightmost 8 bits of a register to memory week04-3.ppt
SPIM syscalls • li $v0,1 # print an integer in $a0 • li $a0,100 • syscall • li $v0,5 # read an integer into $v0 • syscall • li $v0,4 # print an ASCIIZ string at $a0 • la $a0,msg_hello • syscall • li $v0,10 #exit • syscall
String Copy Procedure week04-3.ppt
.data msg_hello: .asciiz "Hello! This is CDA3100!\n" msg_empty: .space 400 .text .globl main main: li $v0,4 la $a0,msg_hello syscall li $v0,4 la $a0,msg_empty syscall la $a0,msg_empty #dst la $a1,msg_hello #src jal strcpy li $v0,4 la $a0,msg_empty syscall li $v0,10 #exit syscall strcpy: ori $t0, $a0, 0 ori $t1, $a1, 0 strcpyloop: lb $t3, 0($t1) sb $t3, 0($t0) beq $t3, $0, strcpydone addi $t0, $t0, 1 addi $t1, $t1, 1 j strcpyloop strcpydone: jr $ra
Stack • Key things to keep in mind: • Stack is a software concept – last in first out, that’s it. • In MIPS, you implement the stack by yourself by keeping $sp always pointing to the top element on the stack • Stack can be used in functions to save register values, and is the standard approach to save register values. But • You can also use stack for other purposes • This is not the only way to save register values.
.data msg: .asciiz "hello world" endl: .asciiz "\n" .text .globl main main: addi $sp,$sp,-1 sb $0,($sp) la $t1, msg L0: lb $t0,($t1) beq $t0,$0, L1 sub $sp,$sp,1 sb $t0,($sp) add $t1,1 j L0 L1: la $t1,msg L2: lb $t0,($sp) add $sp,$sp,1 sb $t0,($t1) beq $t0, $0, L3 add $t1,1 j L2 L3: la $a0,msg li $v0,4 syscall la $a0,endl li $v0,4 syscall li $v0,10 #exit syscall
Implementing a Recursive Function • Suppose we want to implement this in MIPS: • It is a recursive function – a function that calls itself. • It will keep on calling itself, with different parameters, until a terminating condition is met.
The Recursive Function • What happens if we call fact(4)? • First time call fact, compare 4 with 1, no less than 1, call fact again – fact(3). • Second time call fact, compare 3 with 1, no less than 1, call fact again – fact(2). • Third time call fact, compare 2 with 1, no less than 1, call fact again – fact(1). • Fourth time call fact, compare 1 with 1, no less than 1, call fact again – fact(0). • Fifth time call fact, compare 1 with 1, less than 1, return 1. • Return to the time when fact(0) was called (when calling fact(1)). Multiply 1 with 1, return 1. • Return to the time when fact(1) was called (when calling fact(2)). Multiply 2 with 1, return 2. • Return to the time when fact(2) was called (when calling fact(3)). Multiply 3 with 2, return 6. • Return to the time when fact(3) was called (when calling fact(4)). Multiply 4 with 6, return 24.
The Recursive Function • In MIPS, we say calling a function as going to the function. So we go to the function over and over again, until the terminating condition is met. • Here, the function is called “fact,” so we will have a line of code inside the fact function: jal fact
The Recursive Function • The parameter should be passed in $a0. In the C function, every time we call fact, we call with n-1. So, in the MIPS function, before we do “jal fact”, we should have “addi $a0, $a0,-1.” addi $a0, $a0, -1 jal fact
The Recursive Function • After calling fact, we multiply the return result with n, so addi $a0, $a0, -1 jal fact mul $v0, $v0, $a0
The Recursive Function • After multiplying, we return, so addi $a0, $a0, -1 jal fact mul $v0, $v0, $a0 jr $ra
The Recursive Function • So, one if else branch is done. The other branch is slti $t0, $a0, 1 beq $t0, $0, L1 ori $v0, $0, 1 jr $ra where L1 is where we should go to if n >= 1.
The Recursive Function fact: slti $t0, $a0, 1 beq $t0, $zero, L1 ori $v0, $0, 1 jr $ra L1: addi $a0, $a0, -1 jal fact mul $v0, $v0, $a0 jr $ra Any problems?
The Recursive Function fact: addi $sp, $sp, -4 sw $ra, 0($sp) slti $t0, $a0, 1 beq $t0, $zero, L1 ori $v0, $0, 1 lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra L1: addi $a0, $a0, -1 jal fact mul $v0, $v0, $a0 lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra • The problem is that the function will call itself, as we have expected, but it will not return correctly! • You need to save $ra, because you made another function call inside the function. You should always do so. • Is this enough?
The Recursive Function • So now you can return to the main function, but the return result is 0, why? • Because you did not return to the correct time. • Time, here, means what was the parameter you called fact with. • So, should also save $a0!
The Recursive Function week04-3.ppt
The Stack During Recursion week04-3.ppt
.data .text .globl main main: li $a0, 4 jal fact done: li $v0,10 syscall fact: addi $sp, $sp, -8 sw $ra, 4($sp) sw $a0, 0($sp) slti $t0, $a0, 1 beq $t0, $zero, L1 ori $v0, $0, 1 addi $sp, $sp, 8 jr $ra L1: addi $a0, $a0, -1 jal fact lw $ra, 4($sp) lw $a0, 0($sp) mul $v0, $v0, $a0 addi $sp, $sp, 8 jr $ra
Two other MIPS pointers • $fp: When you call a C function, the function may declare an array of size 100 like int A[100]. It is on the stack. You would want to access it, but the stack pointer may keep changing, so you need a fixed reference. $fp is the “frame pointer,” which should always point to the first word that is used by this function. • $gp: the “global pointer.” A reference to access the static data.