Task 1. Assume you are dealing with a 32 bit microprocessor that accesses memory in words (i.e. 32 bits) at a time, while memory is addressed bytewise. You should store strings in memory in an aligned way. You should use as little memory as possibel without becoming unaligned.

  • Store the string "S" starting at an address above or equal to 2012 (decimal).
    ------                  
    2012 S
    2013
    2014
    2015
    ------
    		
  • Store the string "S" starting at an address above or equal to 2013 (decimal).
    ------                  
    2012 
    2013
    2014
    2015
    ------
    2016 S
    2017
    2018
    2019
    ------
    
    		
  • Store the strings "Sunshine", "Rain", "Joy", "Pain" starting at an address above or equal to 2012 (decimal).
    ------                  
    2012 S
    2013 u
    2014 n
    2015 s
    ------
    2016 h
    2017 i
    2018 n
    2019 e
    ------
    2020 R
    2021 a
    2022 i
    2023 n
    ------
    2024 J
    2025 o
    2026 y
    2027 
    ------
    2028 P
    2029 a
    2030 i
    2031 n
    ------
    
  • Store the strings "Sunshine", "Rain", "Joy", "Pain" starting at an address above or equal to 2013 (decimal).
    ------                  
    2012 
    2013 
    2014 
    2015 
    ------                  
    2016 S
    2017 u
    2018 n
    2019 s
    ----
    2020 h
    2021 i
    2022 n
    2023 e
    ----
    2024 R
    2025 a
    2026 i
    2027 n
    ----
    2028 J
    2029 o
    2030 y
    2031 
    ----
    2032 P
    2033 a
    2034 i
    2035 n
    ------
    

Task 4. Write the following programs in RISC-V assembler language. Recall that register $zero is hardwired to 0. For each subtask we give one possible solution -- there are many other ways to implement each subtask.

  • A program that counts the content of register $t1 down to 0 and then terminates.
        li t1 25
    loop:
        beq zero t1 exit
        addi t1 t1 -1
        b loop
    exit:
    
  • A program that counts the content of a memory cell down to 0 and then terminates.
        .data
    mem: .byte 25
        .text	
    loop:
        lw t1 mem
        beq zero t1 exit
        addi t1 t1 -1
        sw t1 mem t2
        b loop
    exit:
    
    There are many ways of doing this. The program above uses lw and sw in a slightly different way from the form given in the lectures. Note also that this program doesn't gracefully return control the the caller.
  • A program that copies 100 Bytes from one region of memory to another.
        .data
    mem1: .ascii
        "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
        # 100 bytes, formatted, so you can watch data being copied over.
    mem2: .space 100
        .text
    
    main:
        la t1 mem1
        la t2 mem2
        li t3, 25
    loop:
        beq t3, zero, exit
        lw a0, 0(t1)
        sw a0, 0(t2)
        addi t1, t1, 4
        addi t2, t2, 4
        addi t3, t3, -1
        b loop
    exit:
        li a7, 10
        ecall 
      
    Note that the pseudo-command ecall ensures smoothing handing back control.
  • A program that copies N words from the memory region starting at A to the memory region starting at B. Note that the source and target regions may overlap, or incrementing a register may lead to wrapping of the register back to 0. Is that a problem for your program?

    The solution to the previous problem is sufficient here, where we use mem1 as A, mem2 as B, and $t3 for N.

  • Write a program that computes (2+3)*4 and leaves the result on top of the stack (remember that the stack pointer should always point to the first free memory cell that's below the top of the stack, if the stack grows downwards).
        li t1 2
        li t2 3
        add t1 t1 t2
        li t2 4
        mul t1 t1 t2
        sw t1 0 ( sp )
        addi sp sp -4
      

Task 5. The key idea is to reserve two general purpose registers, one that is the accumulator, and another that is a temporary, storing the second argument to operations like addition, and multiplication that require two arguments. If the processor has no explicit stack points (RISC-V has no explicit stack points), a third general purpose register needs to be reserved for use as stack pointer.