MIPS Assembly convert integer to ascii string using memory - type-conversion

Hi i have a problem with my subroutine code. here is my code. It's giving a
Runtime exception at 0x00400074: address out of range 0x000000c8 error.
The line is: sb $t2, 0($t4) - It's the second store byte.
intToa: addi $sp, $sp, -12
sw $ra ,8($sp)
sw $a0, 4($sp)
sw $a1, 0($sp)
move $t0, $a0
move $t4, $a1
bne $t0, $zero, while
li $t2, 48
sb $t2, 0($t4)
addi $t4, $t4, 1
b end
while: beq $t0, $zero, end
li $t6, 10
div $t0, $t6 # divide $t0 by 10
mfhi $t1 # $t3 = $t0%10 (last digit of $t0)
mflo $t0 # $t0 = $t0/10 (first digit of $t0)
addi $t2, $t1, 48 # store character '0' to $t1 in
sb $t2, 0($t4) # out destinationg string
addi $t4, $t4, 1 # increment our string pointer
j while # continue looping
end:
sb $zero, 0($t4) # null terminate our string
move $a1, $a0
jal reverse
lw $ra, 12($sp)
addiu $sp, $sp, 12 # put stack back in place
jr $ra

Related

Why is the output the way it is? -Splitting and chop

I'm trouble understanding the output of the below code.
1. Why is the output Jo Al Ch and Sa? Doesn't chop remove the last character of string and return that character, so shouldn't the output be n i n and y? 2. What is the purpose of the $firstline=0; line in the code?
3. What exactly is happening at the lines
foreach(#data)
{$name,$age)=split(//,$_);
print "$name $age \n";
The output of the following code is
Data in file is:
J o
A l
C h
S a
The file contents are:
NAME AGE
John 26
Ali 21
Chen 22
Sally 25
The code:
#!/usr/bin/perl
my ($firstline,
#data,
$data);
open (INFILE,"heading.txt") or die $.;
while (<INFILE>)
{
if ($firstline)
{
$firstline=0;
}
else
{
chop(#data=<INFILE>);
}
print "Data in file is: \n";
foreach (#data)
{
($name,$age)=split(//,$_);
print "$name $age\n";
}
}
There are few issues with this script but first I will answer your points
chop will remove the last character of a string and returns the character chopped. In your data file "heading.txt" every line might be ending with \n and hence chop will be removing \n. It is always recommended to use chomp instead.
You can verify what is the last character of the line by running the command below:
od -bc heading.txt
0000000 116 101 115 105 040 101 107 105 012 112 157 150 156 040 062 066
N A M E A G E \n J o h n 2 6
0000020 012 101 154 151 040 062 061 012 103 150 145 156 040 062 062 012
\n A l i 2 1 \n C h e n 2 2 \n
0000040 123 141 154 154 171 040 062 065 012
S a l l y 2 5 \n
0000051
You can see \n
There is no use of $firstline because it is never been set to 1. So you can remove the if/else block.
In the first line it is reading all the elements of array #data one by one. In 2nd line it is splitting the contents of the element in characters and capturing first 2 characters and assigning them to $name and $age variables and discarding the rest. In the last line we are printing those captured characters.
IMO, in line 2 we should do split based on space to actual capture the name and age.
So the final script should looks like:
#!/usr/bin/perl
use strict;
use warnings;
my #data;
open (INFILE,"heading.txt") or die "Can't open heading.txt: $!";
while (<INFILE>) {
chomp(#data= <INFILE>);
}
close(INFILE);
print "Data in file is: \n";
foreach (#data) {
my ($name,$age)=split(/ /,$_);
print "$name $age\n";
}
Output:
Data in file is:
John 26
Ali 21
Chen 22
Sally 25

Mips Assembly. Connect, read, and write

My objective is to open a socket, connect to that socket on a port, and then whenever that socket sends data to me, I want to write it to stdout.
My code works fine, but for some reason the string that is writing doesn't null terminate? I'm not so sure what the issue is and I have yet to find anything online about it.
#socket(2,1,0)
li $t7, -6
nor $t7, $t7, $zero
addi $a0, $t7, -3
addi $a1, $t7, -3
slti $a2, $zero, -1
li $v0, 4183
syscall 0x40404
sw $v0, -4($sp)
#connect(3, &addr, 16)
lw $a0, -4($sp)
li $t7, -3
nor $t7, $t7, $zero
sw $t7,-32($sp)
lui $t6,0x7a69
ori $t6,$t6,0x7a69
sw $t6, -28($sp)
lui $t5, 0x7F00
ori $t5, $t5, 0x1
sw $t5, -26($sp)
addiu $a1, $sp, -30
li $t4, -17
nor $a2, $t4, $zero
li $v0, 4170
syscall 0x40404
#read(3, addr, 50)
nex:
lw $a0, -4($sp)
addiu $a1, $sp,-64
li $a2, 50
addi $a2, $a2, -1
li $v0, 4003
syscall 0x40404
beqz $a3, next
move $a2,$v0
negu $a2,$v0
next:
blez $a2,nextt
#write(1, addr, 50)
li $a0, 1
li $v0, 4004
syscall 0x40404
j nex
nextt:
Here is the strace of me writing a\n to the socket, and it writing a\n\0\0\0\0\0\0\0\0 to stdout.
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
read(3, "a\n", 49) = 2
write(1, "a\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 49a
zi3▒ݤ) = 49
As you can see, it prints out some weird characters at the end. Thanks for any help!
Notice in your strace output that your read syscall returns a value of 2 [in $v0].
Also notice that your write syscall has a length much greater than 2.
After your read syscall you have:
move $a2,$v0 # this reg has 2
negu $a2,$v0 # BUG: this changes it to -2 (0xFFFFFFFE)
The length for the write was interpreted as an unsigned number [and a very large one]
Change this to just [i.e. remove the negu]:
move $a2,$v0

beq command not jumping to a label in MIPS

I am creating a MIPS code in MARS that allows only an input of a numerical expression, and print an error message when characters other than numbers, +,-,*, and / are present.
In my following code, I set $s0 to zero if there is an invalid character, otherwise it stays at 1. If it is equal to zero, using the beq command I would jump to "erroneous" which handles the error message.
However, that last part does not seem to happen. If you run my code you'll see that it actually gets the proper values of $s0 right (that is, if the expression is invalid, it becomes equal to 0).
I need a fresh set of eyes, I would appreciate any help. Thanks!
.data
input: .space 102
trial: .asciiz "LOLLOL\n"
errormsg: .asciiz "ERROR\n"
.text
main:
addi $v0, $zero, 8
la $a0, input
addi $a1, $a0, 102
syscall
addi $t1 , $zero, 0
add $s1, $zero, $zero
addi $a0, $zero, -1
addi $s0, $zero,1
check_invalid_char_1:
#beq $s0, $s1, erroneous
jal check_invalid_char
j allowed
check_invalid_char:
addi $sp,$sp,-8
sw $ra, 0($sp)
sw $a0, 4($sp)
#sw $v0, 8($sp)
addi $a0, $a0,1
addi $t3, $zero,0
beq $s0, $zero, erroneous
lb $t2, input($a0)
beq $t2, 48, check_invalid_char_1 #pwede 0
beq $t2, 49, check_invalid_char_1 #pwede 1
beq $t2, 50, check_invalid_char_1 #pwede 2
beq $t2, 51, check_invalid_char_1 #pwede 3
beq $t2, 52, check_invalid_char_1 #pwede 4
beq $t2, 53, check_invalid_char_1 #pwede 5
beq $t2, 54, check_invalid_char_1 #pwede 6
beq $t2, 55, check_invalid_char_1 #pwede 7
beq $t2, 56, check_invalid_char_1 #pwede 8
beq $t2, 57, check_invalid_char_1 #pwede 9
beq $t2, 43, check_invalid_char_1 #pwede +
beq $t2, 45, check_invalid_char_1 #pwede -
beq $t2, 42, check_invalid_char_1 #pwede *
beq $t2, 47, check_invalid_char_1 #pwede /
beq $t2, 0, allowed #pwede null terminator
beq $t2, 10, allowed #pwede newline
add $s0, $zero,$zero
lw $ra, 0($sp)
lw $a0, 4($sp)
#lw $v0, 8($sp)
addi $sp, $sp, 8
jr $ra
erroneous:
#add $a0, $zero, $zero
la $a0, errormsg
addi $v0, $zero, 4
syscall
allowed:
addi $v0, $zero, 1
add $a0, $s0, $zero
syscall
#la $a0, errormsg
#addi $v0, $zero, 4
#syscall
addi $v0, $zero, 10
syscall
To anyone who may encounter this question, I may have solved my own problem, but I am not sure if it is really a fix, or a "cheat". It's more of a work around really.
I moved the "beq $s0, $zero, erroneous" line to the "allowed:" label. I don't know why it doesn't work from inside check_valid_char, but it works.
Then inside erroneous, I reset $s0 to 0 by using "sub $s0, $s0, $s0" so that when the code goes again to allowed: , beq will just be skipped and it will end normally.
If others can find a "real" solution for my problem, please post that.
Thanks!
edit: some punctuations.

MIPS float printing

I wrote this code in MIPS to calculate the sum of N-numbers with double float precision.
But when I print the result it prints 0.00000 althought I see that in memory it's the correct result.
Anyone can help me with this?
#architecture ex.2
.data
first: .asciiz "Give the number of the summation"
m1: .asciiz "Give the"
m2: .asciiz "th number."
nl: .asciiz "\n"
final: .asciiz "The sum is"
.text
main:
li $v0, 4
la $a0, first
syscall
li $v0,5
syscall
move $t1,$v0
li $v0, 4
la $a0, nl
syscall
li $t2,0
li $t0,1
mtc1.d $t2, $f2
cvt.d.w $f2, $f2
Sumin:
li $t3,0
li $v0, 4
la $a0, m1
syscall
li $v0,1
move $a0,$t0
syscall
li $v0, 4
la $a0, m2
syscall
li $v0, 4
la $a0, nl
syscall
li $v0,5
syscall
move $t3,$v0
mtc1.d $t3, $f14
cvt.d.w $f14, $f14
add.d $f2,$f2,$f14
addi $t0,$t0,1
ble $t0,$t1,Sumin
Sumexit:
li $v0, 4
la $a0, final
syscall
li $v0, 4
la $a0, nl
syscall
li $v0,2
mov.d $f12,$f2
syscall
END:jr $ra
I'd just suggest printing the double in $f12, not just the float
li $v0, 3
mov.d $f12, $f2
syscall

MIPS - IEEE binary64 (double) and signed integer multiplication

I have a problem with MIPS project. The task is to multiply binary64(double) number by a signed integer without using floating-point Unit. It is almost working well, but for some numbers an error occurs(ex. float-123456789123456, int - 1). By error I mean that after 7th digit my result seems to differ from the proper one. I suspect there can be a problem with transfer of some bit during the procedure(maybe in process of adding $high of mantissa2 and $low of mantissa2). I tried to correct it, but so far I have no idea how to do it. Please verify my code and correct it if possible.
.data
text1: .asciiz "Enter double: "
text2: .asciiz "Enter integer: "
text3: .asciiz "Result: "
quest: .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: "
num1a: .word 0 #multiplicand and result(sign exponent and first part of mantissa)
num1b: .word 0 #second part of the multiplicand and result(remaining part of mantissa)
num2: .word 0 #integer
.text
.globl input
input:
#print "Enter double: "
la $a0, text1
li $v0, 4
syscall
# saving input double into num1
li $v0, 7
syscall
swc1 $f0, num1b
swc1 $f1, num1a
#print "Enter integer: "
la $a0, text2
li $v0, 4
syscall
# saving input int into num2
li $v0, 5
syscall
sw $v0, num2
# loading data to registers
lw $t0, num1a
lw $t1, num1b
lw $t2, num2
#########################################################sign
sign:
move $t3, $t0
andi $t3, $t3, 0x80000000 #preserve sign, zero the rest
bgez $t2, extract #if less than zero we change the final sign and negate the value of integer
xori $t3, $t3, 0x80000000 #multiply signs (if integer is negative, then the sign is equal to $s0)
neg $t2, $t2 #absolute value of int
extract:
################################################checking for zero
or $t5, $t0, $t1 #if both part of double are equal to zero we skip all the calculation
beqz $t5, result_zero
beqz $t2, result_zero
###############################sign, exponent and mantissa
move $t7, $t0
andi $t7, $t7, 0x7FF00000 #extracting exponent to $t7
move $t8, $t0
andi $t8, $t8, 0x000FFFFF #extracting first part of mantissa
ori $t8, $t8, 0x00100000 #adding prefix one to mantissa
#remaining mantissa stays in register $t1
#########################################################
multiply:
########################multiplying mantissa part 1
multu $t8, $t2 #multiply mantissa1 by integer
mflo $t8 #low part of multiplication to $t8
mfhi $s1 #high part of multiplication to $s1
########################multiplying mantissa part 2
multu $t1, $t2 #mantissa part 2 multiplication
mflo $t1 #low part to $t1
mfhi $t0 #with overflow going to $t0
########################partial accumulation
addu $t8, $t8, $t0 #adding the high part of mantissa2 to result of low part of mantissa1
bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high
addiu $s1, $s1, 1
######
skip_add:
bnez $s1, shift
bltu $t8, 0x00200000, result
shift: #else we shift 3 parts of mantissa and increment the the exponent
###extracting least significant bit of high mantissa1
sll $s2, $s1, 31 #copying least significant beat of $s1 to most significant bit in $s2
sll $t9, $t8, 31 #copying least significant beat of $s8 to most significant bit in $t9
######
srl $s1, $s1, 1 #shifting right mantisa part1 high
srl $t8, $t8, 1 #shifting right mantisa part1 low
or $t8, $t8, $s2 #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low
srl $t1, $t1, 1 #shifting right mantisa part2
or $t1, $t1, $t9 #copying least significant bit from mantissa1 to most significant bit of mantissa2
######
addiu $t7, $t7, 0x00100000 #increment exponent by one
######
bnez $s1, shift #if mantissa1 high is greater than zero we continue
bgeu $t8, 0x00200000, shift #if mantissa1 low exceeds final mantissa space
result:
andi $t8, $t8, 0x000FFFFF #preserve mantissa, zero the rest(cut the prefix - one)
move $t0, $t3 #copy propoer sign
or $t0, $t0, $t7 #add exponent
or $t0, $t0, $t8 #add mantissa part1
b output
result_zero:
li $t0, 0
li $t1, 0
output:
sw $t0, num1a
sw $t1, num1b
#print "Result: "
la $a0, text3
li $v0, 4
syscall
lwc1 $f12, num1b
lwc1 $f13, num1a
#print double - the result
li $v0, 3
syscall
question:
la $a0, quest #Do you want to enter new numbers or finish?
li $v0, 4
syscall
li $v0, 5 #reads the answer (integer)
syscall
beq $v0, 1, input #if input =1, continue, if 0 finish, otherwise ask again
beqz $v0, fin
b question
fin:
li $v0, 10 #exit
syscall
I think the problem might be in this section(multiply):
addu $t8, $t8, $t0 #adding the high part of mantissa2 to result of low part of mantissa1
bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high
#addiu $s1, $s1, 1
######
skip_add:
bnez $s1, shift
bltu $t8, 0x00200000, result
The process of adding may cause a carry out. I tried to handle it with instruction held in comment (addiu).It means that if the result of adding two unsigned numbers is less than one of them we obtain a cary out and have to add 1 to register $s1 which holds the most significant part of mantissa.It didn't help.
In my opinion this is the correct code:
.data
text1: .asciiz "Enter double: "
text2: .asciiz "Enter integer: "
text3: .asciiz "Result: "
quest: .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: "
num1a: .word 0 #multiplicand and result(sign exponent and first part of mantissa)
num1b: .word 0 #second part of the multiplicand and result(remaining part of mantissa)
num2: .word 0 #integer
.text
.globl input
input:
#print "Enter double: "
la $a0, text1
li $v0, 4
syscall
# saving input double into num1
li $v0, 7
syscall
swc1 $f0, num1b
swc1 $f1, num1a
#print "Enter integer: "
la $a0, text2
li $v0, 4
syscall
# saving input int into num2
li $v0, 5
syscall
sw $v0, num2
# loading data to registers
lw $t0, num1a
lw $t1, num1b
lw $t2, num2
#########################################################sign
sign:
move $t3, $t0
andi $t3, $t3, 0x80000000 #preserve sign, zero the rest
bgez $t2, extract #if less than zero we change the final sign and negate the value of integer
xori $t3, $t3, 0x80000000 #multiply signs (if integer is negative, then the sign is equal to $s0)
neg $t2, $t2 #absolute value of int
extract:
################################################checking for zero
or $t5, $t0, $t1 #if both part of double are equal to zero we skip all the calculation
beqz $t5, result_zero
beqz $t2, result_zero
###############################sign, exponent and mantissa
move $t7, $t0
andi $t7, $t7, 0x7FF00000 #extracting exponent to $t7
move $t8, $t0
andi $t8, $t8, 0x000FFFFF #extracting first part of mantissa
ori $t8, $t8, 0x00100000 #adding prefix one to mantissa
#remaining mantissa stays in register $t1
#########################################################
multiply:
########################multiplying mantissa part 1
multu $t8, $t2 #multiply mantissa1 by integer
mflo $t8 #low part of multiplication to $t8
mfhi $s1 #high part of multiplication to $s1
########################multiplying mantissa part 2
multu $t1, $t2 #mantissa part 2 multiplication
mflo $t1 #low part to $t1
mfhi $t0 #with overflow going to $t0
########################partial accumulation
addu $t8, $t8, $t0 #adding the high part of mantissa2 to result of low part of mantissa1
bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high
addiu $s1, $s1, 1
######
skip_add:
bnez $s1, shift
bltu $t8, 0x00200000, result
shift: #else we shift 3 parts of mantissa and increment the the exponent
###extracting least significant bit of high mantissa1
sll $s2, $s1, 31 #copying least significant beat of $s1 to most significant bit in $s2
sll $t9, $t8, 31 #copying least significant beat of $s8 to most significant bit in $t9
######
srl $s1, $s1, 1 #shifting right mantisa part1 high
srl $t8, $t8, 1 #shifting right mantisa part1 low
or $t8, $t8, $s2 #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low
srl $t1, $t1, 1 #shifting right mantisa part2
or $t1, $t1, $t9 #copying least significant bit from mantissa1 to most significant bit of mantissa2
######
addiu $t7, $t7, 0x00100000 #increment exponent by one
######
bnez $s1, shift #if mantissa1 high is greater than zero we continue
bgeu $t8, 0x00200000, shift #if mantissa1 low exceeds final mantissa space
result:
andi $t8, $t8, 0x000FFFFF #preserve mantissa, zero the rest(cut the prefix - one)
move $t0, $t3 #copy propoer sign
or $t0, $t0, $t7 #add exponent
or $t0, $t0, $t8 #add mantissa part1
b output
result_zero:
li $t0, 0
li $t1, 0
output:
sw $t0, num1a
sw $t1, num1b
#print "Result: "
la $a0, text3
li $v0, 4
syscall
lwc1 $f12, num1b
lwc1 $f13, num1a
#print double - the result
li $v0, 3
syscall
question:
la $a0, quest #Do you want to enter new numbers or finish?
li $v0, 4
syscall
li $v0, 5 #reads the answer (integer)
syscall
beq $v0, 1, input #if input =1, continue, if 0 finish, otherwise ask again
beqz $v0, fin
b question
fin:
li $v0, 10 #exit
syscall