In this lab, you will work with strings.
Read and display the given string as part of this exercise. Use the string "RISC-V Assembly Programming".
Code is provided for "string_copy.S", as shown below. Copy this to a local file. Note that the first instructions use an ecall named "sbrk" to reserve space, then store the address of the reserved space at "copy".
# This is written for VSCode/Venus
# Copy a string.
# -MCW
.text
main:
# Reserve 100 bytes
li a0, 9 # sbrk
li a1,100
ecall
# a0 has pointer to reserved memory
la t0, copy
sw a0, 0(t0) # store the address into "copy"
# We could move it to s3 and skip this,
# but it is a good idea.
# Note: we use s2,s3,s4 to make sure the values do not change
# when we do a call/ecall
la s2, mystring # s2 points to "mystring"
la s3, copy # s3 points to "copy"
la s4, mystring_end # s4 points to memory after string
loop:
lb s0, 0(s2) # Access byte from string
sb s0, 0(s3) # Copy byte to "copy"
addi s2, s2, 1 # Increment s2
addi s3, s3, 1 # Increment s3
# Now print the array value out
mv a1, s0
li a0, 1 # print an integer
ecall
# print space
li a0, 11 # print a character
li a1, 32 # space (the character to print)
ecall
bne s2, s4, loop # Compare s2 with s4
# (address of memory after string)
# Jump to loop if not equal
# We are done, so print the copy
li a0, 4 # print a string
la a1, copy # load address of "copy" string
ecall
# print NL
li a0, 11 # print a character
li a1, 10 # NL (the character to print)
ecall
# exit the program
li a0, 17
li a1, 0 # 0 for everything is OK
ecall
.data # Data section, initialized variables
mystring: .string "RISC-V Assembly Programming"
mystring_end:
#.bss # VSCode/Venus does not support .bss
copy: .word 0
Use VSCode/Venus to simulate the above code.
It should print the copied string.
Verify that it works.
Questions for Part 1
bne
instruction do in the loop? copy: .word 0
instead of
copy: .word 100
if we want "copy" to point to 100 bytes?
Here is what the code to do the count looks like. Pay attention to the comments to know how to use it.
find_len:
# Caller will have code like this:
#la a0, mystring # a0 points to "mystring"
#call find_len
# Put the length of the string into a1
# Set count (in register a1) to zero
mv a1, x0
find_len_loop:
lb t0, 0(a0) # Access byte from string
addi a0, a0, 1 # Increment a0 (pointer to next byte)
addi a1, a1, 1 # Increment a1 (count)
# Check: is the byte a zero?
bne t0, x0, find_len_loop
ret
Verify that the output is correct.
Questions
li t0, ' '
to
load a space into register t0 (or whatever register makes sense).
Modify the code from one of the previous parts to count the spaces.
The following algorithm should help. Lines with "#" are comments where the line under it accomplishes the task. Lines with "##" indicate places where you are meant to add code.
# Load the character to look for in t0
li t0, ' '
# Load the address of the string into t1
la t1, mystring
count_spaces:
## Is the character a space? If not, skip around the increment
## Increment the count
skip_inc:
## Did we find a character 0?
## If not, branch to count_spaces
## Now, write out the count and exit the program.
Questions
blt
instead of the
branch command that you use at the "If not, skip around the increment"
part.
Would that work? Explain.
beq
and bne
do.
For this exercise use the string "RISC-v Assembly Programming" and "RISC-V Assembly Programming", and write a subroutine to compare the two. Print either "equal" or "not equal" depending on the result. Show the outputs, and try a few variations for the strings.
Questions:
In this lab, we have learned: