Essentially, I am trying to store a char (1 byte) into memory using sb.
I am writing MIPS assembly to reproduce the functionality of some C code. I put the function str_make_lower in a separate file and compiled the C code with it.
#include <stdio.h>
/* uses tolower() to convert upper case to lower case*/
void str_make_lower(char *s);
// while(*s != '\0'){
// *s = tolower(*s);
// s++;
// }
// }
int main(int argc, char const *argv[])
{
char *s = "AB\000";
str_make_lower(s);
printf("%s\n", s);
return 0;
}
My assembly is as follows, which should mimic the C code that is commented out:
.text
.global str_make_lower
str_make_lower:
# arg passed in:
# a0: char *s
addi $sp, $sp, -40
sw $ra, 32($sp)
sw $s0, 36($sp)
# save char *s
move $s0, $a0
while_str_make_lower:
# initialize registers
add $t0, $zero, $zero
add $a0, $zero, $zero
lb $t0, 0($s0) # get a char from pointer
beq $t0, $zero, str_make_lower_return
nop
move $a0, $t0 # load arg for tolower
jal tolower # yeah
nop
add $t0, $zero, $zero
move $t0, $v0 # collect lower letter
sb $t0, 0($s0) # store it back
addiu $s0, $s0, 1 # increment pointer
j while_str_make_lower
nop
str_make_lower_return:
# restore and return
lw $s0, 36($sp)
lw $ra, 32($sp)
addi $sp, $sp, 40
jr $ra
nop
Ultimately, by using gdb, I found that it was the store byte (sb) that was giving seg fault. I inspected the content of $t0 and $s0 but the values of the two seem to be what they should be. I wonder whether it is me using the sb wrong, or something else.
(gdb) p $t0
$5 = 97
Program received signal SIGSEGV, Segmentation fault.
while_str_make_lower () at tl.s:35
35 sb $t0, 0($s0) # store it back
(gdb) bt
#0 while_str_make_lower () at tl.s:35
#1 0x00400700 in while_str_make_lower () at tl.s:30
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) p (char*)$s0
$9 = 0x4008c0 "AB"
Thanks!