I have this specific description of how to write a function called
tim2string , I have written this function but I'm unsure if I'm doing as it's Say's in the description. I have tried to run my code on MARS and I get this
tim2string is added in the end of code.
timetemplate.asm line 99: Runtime exception at 0x00400118: address out of range 0x00005958
The description of function is the following
Name: The subroutine must be called time2string. Parameters (two): Register $a0 contains the address of an area in memory, suitably large for the output from time2string . The 16 least significant bits of register $a1 contains time-info, organized as four NBCD-coded digits of 4 bits each. All other bits in register $a1 can have any value and must be ignored.
Example: register $a0 can contain the address 0x100100017 , and register $a1 can contain the value 0x00001653. Return value: None. Required action:
The following sequence of six characters must be written to the area in memory pointed to by register $a0 .
1) Two ASCII-coded digits showing the number of minutes, according to the two more significant NBCD-coded digits of the input parameter. Example: '1', '6' (ASCII 0x31, 0x36):
2) A colon character (ASCII : , code 0x3A).
3) Two ASCII-coded digits showing the number of seconds, according to the two less significant NBCD-coded digits of the input parameter. Example: '5', '3' (ASCII 0x35, 0x33). 4. A null byte (ASCII NUL, code 0x00). Notes:You must use the function hexasc to convert each NBCD-coded digit into the corresponding ASCII code. Use the sb instruction to store each byte at the destination. The macros PUSH and POP are useful for saving and restoring registers.
# timetemplate.asm # Written 2015 by F Lundevall # Copyright abandonded - this file is in the public domain. .macro PUSH (%reg) addi $sp,$sp,-4 sw %reg,0($sp) .end_macro .macro POP (%reg) lw %reg,0($sp) addi $sp,$sp,4 .end_macro .data .align 2 mytime: .word 0x5957 timstr: .ascii "text more text lots of text\0" .text main: # print timstr la $a0,timstr li $v0,4 syscall nop # wait a little li $a0,2 jal delay nop # call tick la $a0,mytime jal tick nop # call your function time2string la $a0,timstr la $t0,mytime lw $a1,0($t0) #load the adress contained in $t0 into $a1 jal time2string nop # print a newline li $a0,10 li $v0,11 syscall nop # go back and do it all again j main nop # tick: update time pointed to by $a0 tick: lw $t0,0($a0) # get time addiu $t0,$t0,1 # increase andi $t1,$t0,0xf # check lowest digit sltiu $t2,$t1,0xa # if digit < a, okay bnez $t2,tiend nop addiu $t0,$t0,0x6 # adjust lowest digit andi $t1,$t0,0xf0 # check next digit sltiu $t2,$t1,0x60 # if digit < 6, okay bnez $t2,tiend nop addiu $t0,$t0,0xa0 # adjust digit andi $t1,$t0,0xf00 # check minute digit sltiu $t2,$t1,0xa00 # if digit < a, okay bnez $t2,tiend nop addiu $t0,$t0,0x600 # adjust digit andi $t1,$t0,0xf000 # check last digit sltiu $t2,$t1,0x6000 # if digit < 6, okay bnez $t2,tiend nop addiu $t0,$t0,0xa000 # adjust last digit tiend: sw $t0,0($a0) # save updated result jr $ra # return nop # you can write your code for subroutine "hexasc" and below this line # hexasc: andi $a0,$a0,0xf #only 4 least significant bits ignore other bits addi $v0,$zero,0x30 #$v0 = 0x30 ('0') addi $t0,$zero,0x9 #t0 = 0x9 ble $a0,$t0,L1 #branch if a0 <= 0x9 nop addi $v0,$v0,0x7 #v0 = v0 +0x7 L1: add $v0,$a0,$v0 #v0 = V0 +a0 jr $ra nop delay: jr $ra nop time2string: PUSH ($t2) PUSH ($t0) PUSH ($a1) lb $t0, 0($a1) #load one byte from a1 "LINE 99" ERROR andi $t2, $t0,0xf #check the 4 lowest bits ignore other jal hexasc # call hexasc nop sb $t0, 0($a1) #stor back that byte in a1 lb $t0, 1($a1) # load the next byte andi $t2, $t0,0xf0 jal hexasc nop sb $t0, 1($a1) lb $t0, 2($a1) andi $t2, $t0,0xf00 jal hexasc nop sb $t0, 2($a1) lb $t0, 3($a1) andi $t2, $t0,0xf000 jal hexasc nop sb $t0, 3($a1) POP ($a1) POP ($t0) POP ($t2) jr $ra nop
I had some progress to written
time2string function i have come so far
and still i need some help.
I single step through my code it's working fine until this line
sb $v0, 0($t0) #stor that 4 bits in that location that a0 points to
I get this error
timetemplate.asm line 115: Runtime exception at 0x00400158: address out of range 0x00000009
Here is the updated code
time2string: PUSH ($t0) PUSH ($t1) PUSH ($t2) PUSH ($t3) PUSH ($t4) PUSH ($t5) PUSH ($ra) #nested subroutine must store $ra too add $t0,$0,$a0 #contaisn the adress of string (timstr) add $t1,$0,$a1 #contains the time-info(0x5957) andi $t2,$t1,0xf000 #check the 4 most signifaicant bits ignore other bits srl $a0,$t2,12 #shift the MSB to LSB position (hexasc take only 4 bits in the LSB position) jal hexasc # call hexasc nop sb $v0, 0($t0) #stor that 4 bits in that location that a0 points to andi $t3,$t1,0x0f00 #mask to get those 4 bits you and ignore other bits srl $a0,$t3,8 #shift those bits to the LSB position(0x000f) jal hexasc nop sb $v0,1($t0) li t5,0x3A sb $t5,2($t0) andi $t4,$t1,0x00f0 srl $a0,$t4,4 jal hexasc nop sb $v0,3($t0) move $a0,$t1 jal hexasc nop sb $v0, 4($t0) POP ($ra) POP ($t5) POP ($t4) POP ($t3) POP ($t2) POP ($t1) POP ($t0) jr $ra nop
lb $t0, 0($a1) #load one byte from a1
This will load one byte from memory from address
a1 does not contain valid address, it contains BCD time value, like
0x5958, which is meant as time 59:58.
So you don't need to load the time value from memory, you already have the values in the
a1 loaded. You have to pick out each group of 4 bits separately (from low 16 bits), that's where the 4 digits are encoded.
Oh, and this:
I have tried to run my code on MARS
That's not, how people are programming in Assembly. You don't RUN your code. You step over single instruction in debugger, one by one, verifying after each single instruction, that it did change only the registers/memory which it was supposed to change, and only in the way how it was supposed to change it.
(that's why you need first English comments describing the algorithm, because otherwise you can't reason if the instruction did what you did want ... of course it will always do, what it does, according to the CPU docs, you will hardly ever in your life encounter the situation when the instruction itself fails to execute properly (although it's technically possible, when some electrons "jump" over the "walls" of supposed path, usually after being hit hard by some proton from X-rays/etc ... maybe if you will live long enough, it may happens once or twice near you ... it's very likely you will never notice, as the SW will probably survive it, or crash like it does normally from code bugs))
Also make sure you avoid the brain playing tricks on you, taking shortcuts to save it's effort, so instead of your brain reading what is on the screen, it will try to tell you, what you did want to write and see there.
Like when you write in the code
sb $t0,0($a1) instead of
sb $t0,0($a0), if you will try to re-read the source shortly after writing it, you will read
sb $t0,0($a0), unless you focus really hard and make sure your brain is not cheating you.
Same goes for debugging and checking resulting values in registers, etc.. if you for example expect value
t1, and it by accident ends in
t2, you may easily miss the the fact that the
1 did change in
t2, not in
t1, because your brain cares mostly that the result is
It's tricky. That's why people love Assembly, and code almost everything in it.
User contributions licensed under CC BY-SA 3.0