.section .data ;;;# Constants .equ SYS_WRITE, 64 .equ SYS_BRK, 214 .equ STDOUT, 1 .equ NULL, 0 .section .text ;;;# size_t strlen(char *buf) ;;;# returns the lenght of buf ;;;# (buf must be a NULL-terminated) ;;;# returns 0 when buf is empty .globl strlen ;;;# int puts(char *buf) ;;;# does a sys_write on buf ;;;# (buf must be a NULL-terminated) ;;;# returns the amount of charaters written ;;;# < 0 on fail .globl puts ;;;# int putc(char ch) ;;;# does a sys_write on ch ;;;# returns 1 on success .globl putc ;;;# int printf(char *buf, ...) ;;;# does what libc printf does ;;;# (buf must be NULL-terminated) ;;;# (the variadic args are on the stack ;;;# with the first begin at 0(sp)) ;;;# returns the amount of characters written ;;;# < 0 on fail .globl printf ;;;# strlen strlen: mv t0, a0 ;# copy buf addr li t3, NULL ;# NULL strlen_loop: lb t2, 0(t0) ;# load cur char beq t2, t3, strlen_end ;# end loop when its \0 addi t0, t0, 1 ;# next element in the array j strlen_loop strlen_end: sub a0, t0, a0 ;# get the amount of elements ret ;;;# puts puts: mv a1, a0 ;# copy buf addi sp, sp, -4 ;# save ra sw ra, 0(sp) ;# call strlen mv a2, a0 ;# move the len into a2 lw ra, 0(sp) ;# load ra addi sp, sp, 4 ;# li a7, SYS_WRITE li a0, STDOUT ecall ret ;;;# putc putc: addi sp, sp, -1 ;# save the char on the stack sb a0, 0(sp) ;# so it is an address li a7, SYS_WRITE ;# li a0, STDOUT ;# mv a1, sp ;# do of write syscall li a2, 1 ;# ecall ;# addi sp, sp, 1 ;# restore the stack ret ;;;# printf printf: ;;# using t6 and t5 like saved registers since i can't ;;# use the stack normally because of the variadic args mv t6, zero ;# the character counter mv t5, a0 ;# the fmt string printf_loop: lb t4, 0(t5) ;# load the next char li t3, NULL ;# branch to end on null beq t4, t3, printf_end ;# li t3, '%' ;# branch on % beq t4, t3, printf_on_fmt ;# li t3, '\' ;# branch on escape character beq t4, t3, printf_on_esc ;# li a0, STDOUT ;# mv a1, t5 ;# the character must be normal li a2, 1 ;# so we just write it li a7, SYS_WRITE ;# ecall ;# addi t6, t6, 1 ;# we wrote one more byte printf_loop_again: addi t5, t5, 1 ;# go to the next char j printf_loop printf_end: mv a0, t6 ;# return the amount of written bytes ret ;;;# each branch pops the data from the stack, ;;;# then it prints it and increases the byte counter (t6) printf_on_fmt: addi t5, t5, 1 ;# go to the next char lb t4, 0(t5) ;# load the next char li t3, NULL beq t4, t3, printf_end ;# branch to end on null li t3, '%' beq t4, t3, printf_perc ;# print '%' on '%' li t3, 's' beq t4, t3, printf_string ;# print string on 's' li t3, 'd' beq t4, t3, printf_dec_num ;# print decimal on 'd' j printf_loop_again ;# no such program character ;;;# each branch sets a0 to a char, then the char is written printf_on_esc: addi t5, t5, 1 ;# go to the next char lb t4, 0(t5) ;# load the next char li t3, NULL beq t4, t3, printf_end ;# branch to end on null li t3, '\' beq t4, t3, printf_esc_slsh ;# putc slash li t3, 'n' beq t4, t3, printf_esc_nl ;# putc \n printf_on_esc_ret: addi sp, sp, -4 ;# push ra to the stack sw ra, 0(sp) ;# call putc lw ra, 0(sp) ;# pop ra from the stack addi sp, sp, 4 ;# add t6, t6, a0 ;# add amount of printed chars j printf_loop_again printf_esc_slsh: li a0, '\' j printf_on_esc_ret printf_esc_nl: li a0, 0xA j printf_on_esc_ret printf_perc: addi sp, sp, -4 ;# push ra to the stack sw ra, 0(sp) ;# li a0, '%' ;# putc '%' call putc ;# lw ra, 0(sp) ;# pop ra from the stack addi sp, sp, 4 ;# add t6, t6, a0 ;# add amount of printed chars j printf_loop_again printf_string: lw a0, 0(sp) ;# get the string from the stack sw ra, 0(sp) ;# save ra to stack call puts lw ra, 0(sp) ;# pop ra from the stack addi sp, sp, 4 ;# add t6, t6, a0 ;# add amount of printed chars j printf_loop_again printf_dec_num: addi t0, zero, 10 ;# divisor mv t2, zero ;# counter lw t3, 0(sp) ;# pop the number from the stack addi sp, sp, 4 ;# printf_dec_num_loop: remu t1, t3, t0 ;# get the last digit addi t2, t2, 1 ;# inc the counter addi t1, t1, '0' ;# turns digit into a char addi sp, sp, -1 ;# one byte on stack sb t1, 0(sp) ;# save on stack divu t3, t3, t0 ;# remove the last digit bne t3, zero, printf_dec_num_loop ;# loop again when the number is not 0 li a0, STDOUT ;# mv a1, sp ;# do a write syscall mv a2, t2 ;# on the string in the stack li a7, SYS_WRITE ;# ecall ;# add sp, sp, t2 ;# clear the stack add t6, t6, t2 ;# add to the char counter j printf_loop_again