Close

Creating string methods for logging

A project log for Sparkfun RED-V bare metal

I wanted to learn RISC-V, not on an emulator, but on a real bare metal RISC-V processor. Even though Sparkfun RED-V is no longer produced.

olaf-baeyensOlaf Baeyens 10/24/2024 at 17:330 Comments

For debugging we need a way to handle strings, so lets first build C like string functions.

I start with macro's, I wand the ability to create then inline when needed for speed and as a function call.

List contains a small sample of the string macro's.
Still in development I need to think how this will be used in my code.

I can give you a clue: In this case chatGPT can create code that helps a lot, but you need to manually check every generated code line. We can optimize later on, for now we need something working.

# string-macros.s

# ----------------------------------------------------------------------- 
# Copy string (ASCIIZ)
# -----------------------------------------------------------------------
.macro STRCPY dest_string_ptr, src_string_ptr
    la a0, \dest_string_ptr         # dest_string_ptr
    la a1, \src_string_ptr          # src_string_ptr 

    jal _strcpy
.endm

# ----------------------------------------------------------------------- 
#  String copy with specific length
# -----------------------------------------------------------------------
.macro STRNCPY dest_string_ptr, src_string_ptr, len
    la a0, \dest_string_ptr         # dest_string_ptr
    la a1, \src_string_ptr          # src_string_ptr 
    li a2, \len                     # Load the specified length into a0

    jal _strncpy
.endm

# ----------------------------------------------------------------------- 
# FILL BYTES
# -----------------------------------------------------------------------
.macro FILL_BYTES dest_ptr, value, length
    la a0, \dest_ptr            # Load destination address into t3
    li a1, \value               # Load value into t0
    li a2, \length              # Load length into t1

    jal _fill_bytes    
.endm

# ----------------------------------------------------------------------- 
# FILL BYTES STRING (ASCIIZ)
# -----------------------------------------------------------------------
.macro FILL_STRING dest_ptr, value, length
    li t0, \value               # Load the value to be repeated into t0
    li t1, \length              # Load the length into t1
    la t3, \dest_ptr            # Load the destination address into t3

fill_string_loop:
    sb t0, 0(t3)                # Store the value into the destination address
    addi t3, t3, 1              # Increment the destination address
    addi t1, t1, -1             # Decrement the length
    bnez t1, fill_string_loop   # If length is not zero, repeat the loop

    sb zero, 0(t3)              # Store null character at the end
.endm

# ----------------------------------------------------------------------- 
# Get string length (ASCIIZ)
# -----------------------------------------------------------------------
.macro STRLEN dest_reg, input_string_ptr
    la t0, \input_string_ptr
    li \dest_reg, 0

.loop_strlen:
    lb t1, 0(t0)
    beqz t1, .end_strlen          # If t1 is zero (null-terminator), exit loop
    addi \dest_reg, \dest_reg, 1
    addi t0, t0, 1                # Move to the next character
    j .loop_strlen

.end_strlen:
.endm

 Accompanying code

# strings.s

.section .text

.text

.globl _fill_bytes
.globl _strcpy
.globl _strncpy

# ----------------------------------------------------------------------- 
# FILL BYTES
# -----------------------------------------------------------------------
_fill_bytes:
    addi t0, a0, 0              # Load destination address into t0
    addi t1, a1, 0              # Load value into t1
    addi t2, a2, 0              # Load length into t2

fill_bytes_loop:
    sb t1, 0(t0)                # Store byte from t0 to the destination address
    addi t0, t0, 1              # Increment destination address
    addi t2, t2, -1             # Decrement length
    bnez t2, fill_bytes_loop    # If length is not zero, repeat the loop
    ret

# ----------------------------------------------------------------------- 
# Copy string (ASCIIZ)
# -----------------------------------------------------------------------
_strcpy:
    addi t0, a0, 0              # Load the destination string pointer to t0
    addi t1, a1, 0              # Load the source string pointer to t1

.loop_strcpy:
    lbu t2, 0(t1)
    beqz t2, .end_strcpy        # If t2 is zero (null-terminator), exit loop
    sb t2, 0(t0)                # Copy the character to the destination
    addi t0, t0, 1              # Move to the next character in src
    addi t1, t1, 1              # Move to the next character in dest
    j .loop_strcpy

.end_strcpy:
    sb zero, 0(t0)                  # Null-terminate the destination string
    ret

# ----------------------------------------------------------------------- 
#  String copy with specific length
# -----------------------------------------------------------------------
_strncpy:
    addi t0, a0, 0              # Load the destination string pointer to t0
    addi t1, a1, 0              # Load the source string pointer to t1
    addi t2, a2, 0              # Load the specified length into t2

.loop_strncpy:
    beqz t2, .end_strncpy       # If t2 is zero (length reached), exit loop
    lb t3, 0(t1)
    sb t3, 0(t0)                # Copy the character to the destination
    addi t0, t0, 1              # Move to the next character in dest
    addi t1, t1, 1              # Move to the next character in src
    addi t2, t2, -1             # Decrement the length
    j .loop_strncpy

.end_strncpy:
    sb zero, 0(t0)              # Null-terminate the destination string
    ret


Discussions