RISC-V Assembly Language - String To Integer

Introduction

To convert a string to an integer in RISC-V assembly (a function often called atoi), you must manually loop through each character of the string, subtract the ASCII offset of '0', multiply your current total by 10, and add the new digit.

Below is a complete, and optimized RISC-V assembly implementation that handles positive integers, negative numbers, and stops when encountering a null-terminator or non-digit character.

Code

Note: Convert this code to a function with a prologue, body,
and epilogue.

.data .align 2 integer_string: .asciz "123" .align 2 newline: .asciz "\n" .text .global main # ------------------------------------------------------------------------- # Function: string_to_integer # Arguments: # a0 = pointer to the null-terminated string (char *) # Return Value: # a0 = parsed integer value # ------------------------------------------------------------------------- string_to_integer: # --------------------------------------------------------------------- # function prologue? # --------------------------------------------------------------------- li t0, 0 # t0 = result accumulator (total = 0) li t1, 0 # t1 = negative flag (0 = positive, 1 = negative) li t4, 10 # t4 = constant 10 for decimal shifting # --------------------------------------------------------------------- # function body # --------------------------------------------------------------------- # 1. Check for optional sign characters ('+' or '-') lb t2, 0(a0) # Load first character li t3, 45 # ASCII code for '-' is 45 bne t2, t3, check_plus li t1, 1 # Set negative flag to 1 addi a0, a0, 1 # Move string pointer to next character j digit_loop check_plus: li t3, 43 # ASCII code for '+' is 43 bne t2, t3, digit_loop addi a0, a0, 1 # Move string pointer past '+' # 2. Main processing loop digit_loop: lb t2, 0(a0) # Load current character beqz t2, finish # If character is '\0' (null-terminator), # we are done # Check if character is a valid digit ('0' to '9') li t3, 48 # ASCII '0' blt t2, t3, finish # If char < '0', exit loop li t3, 57 # ASCII '9' bgt t2, t3, finish # If char > '9', exit loop # Convert ASCII character to raw integer digit addi t2, t2, -48 # t2 = char - '0' # Shift accumulator and add the new digit: total = (total * 10) + digit mul t0, t0, t4 # total = total * 10 add t0, t0, t2 # total = total + digit addi a0, a0, 1 # Advance pointer to next character j digit_loop # 3. Finalize and apply the sign finish: beqz t1, return_val # If negative flag is 0, skip negation neg t0, t0 # Negate the accumulator (two's complement) # --------------------------------------------------------------------- # function epilogue? # --------------------------------------------------------------------- return_val: mv a0, t0 # Place final result into return register a0 ret # Return to caller # ------------------------------------------------------------------------- # main # ------------------------------------------------------------------------- main: la a0, integer_string call string_to_integer

How the Algorithm Works