Hello World with RISC-V Again

Writing Hello World in RISC-V Assembly with ANSI teminal codes.

Hello World Agian

Following on from the basic Hello World RISC-V Assemly language program, next we will add a couple of improvements.

We make the assumption that you are working on Linux with a teminal emulator that supports ANSI (such as the default one in Ubuntu).

Our improvements are as follows:
We will clear the screen.
We will output the message in the middle of the screen.
We will print the first line in blue and the second in red.
We will only output each line once the user presses the space bar followed by the enter key.

A default terminal size of 80 columns and 24 lines is assumed for this program.

hello.s

#
# RISC-V Assembler program to clear the screen and print "Hello World!"
# and "Hello Again!" to stdout upon pressing the space bar.
# We assume that the terminal supports ANSI escape sequences.
# We assume the terminal size is 80 columns by 24 rows by.
#

.global _start      # Provide program starting address to linker

_start: 
        la    a1, clear_screen # load address of clear screen escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 4        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

# Initialize counter
        addi  t0, x0, 0        # Initialize counter t0 to 0

wait_for_space:
        # Read a character from stdin
        addi  a0, x0, 0        # 0 = StdIn
        la    a1, input_char   # load address of input_char
        addi  a2, x0, 1        # read 1 byte
        addi  a7, x0, 63       # linux read system call
        ecall                  # Call linux to read input

        # Check if the character is space (ASCII 32)
        lb    t1, 0(a1)        # Load the input character to t1
        addi  t2, x0, 32       # Load ASCII value of space to t2
        beq   t1, t2, process_space # If space, process

        j wait_for_space       # Otherwise, keep waiting

process_space:
        # Increment counter
        addi  t0, t0, 1

        # Check counter value
        li    t3, 1
        beq   t0, t3, print_hello_world

        li    t3, 2
        beq   t0, t3, print_hello_again

        li    t3, 3
        beq   t0, t3, exit_program

        j wait_for_space       # If counter not 1, 2, or 3, wait for next space

print_hello_world:
        la    a1, cursor_pos   # load address of cursor position escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 8        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        la    a1, colour_blue  # load address of blue colour escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 5        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        addi  a0, x0, 1        # 1 = StdOut
        la    a1, helloworld   # load address of helloworld
        addi  a2, x0, 13       # length of our string
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        j wait_for_space       # Wait for next space press

print_hello_again:
        la    a1, cursor_pos2  # load address of second cursor position escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 8        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        la    a1, colour_red   # load address of red colour escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 5        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        addi  a0, x0, 1        # 1 = StdOut
        la    a1, helloagain   # load address of helloagain
        addi  a2, x0, 13       # length of our string
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        j wait_for_space       # Wait for next space press

exit_program:
        la    a1, cursor_pos3  # load address of third cursor position escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 8        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        la    a1, colour_reset # load address of reset colour escape sequence
        addi  a0, x0, 1        # 1 = StdOut
        addi  a2, x0, 4        # length of escape sequence
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        addi  a0, x0, 1        # 1 = StdOut
        la    a1, doreturn     # load address of doreturn
        addi  a2, x0, 2        # length of our string
        addi  a7, x0, 64       # linux write system call
        ecall                  # Call linux to output the string

        addi    a0, x0, 0      # Use 0 return code
        addi    a7, x0, 93     # Service command code 93 terminates
        ecall                  # Call linux to terminate the program

.data
helloworld:      .ascii "Hello World!\n"
helloagain:      .ascii "Hello Again!\n"
doreturn:        .ascii " \n"
clear_screen:    .ascii "\033[2J"
cursor_pos:      .ascii "\033[12;30H"
cursor_pos2:     .ascii "\033[14;30H"
cursor_pos3:     .ascii "\033[24;0H"
colour_red:      .ascii "\033[31m"
colour_blue:     .ascii "\033[34m"
colour_reset:    .ascii "\033[0m"
input_char:      .byte 0
		

Assemble and Run

as -mno-relax -o hello.o hello.s
ld -o hello hello.o
./hello
				

Mission Accomplished

And there we have it, you now have a functioning RISC-V Hello World that takes a user input and places a colourful message in the middle of the terminal.