How do I write MIPS code for vector multiplication - cpu-architecture

Define vector mul(vector v, float t). It returns a vector by multiplying it by t.
If a=4i+3j+12k then mul(a,0.5) will return 2i+1.5j+6k.
Here's the code I've written:
.globl main
.text
main:
la $s0,t #loading t into s1
lw $s1,0($s0)
ori $s2,$zero,0
la $s3,v
#la $s0,v
#lw $s3,0($s0)
la $s0,s
lw $s4,0($s0)
jal f
f:
#if <cond>
bge $s2,$s4,DONE
#<for body>
lw $s5, 0($s3)
mul $s3,$s3,$s1
li $v0,10
syscall
j UPDATE
UPDATE:
addi $s2,$s2,1 #i=i+1
addi $s3,$s3,4 #moving address 4 bytes since int
j f
DONE:
li $v0,10
syscall
.data
s: .word 3
v: .word 4 3 12 #hard coding vector coefficients
t: .word 2 #value to be multiplied by
When I run this on SPIM simulator, the registers don't produce any value. Is my code wrong or do I need to add something?

mul $s3,$s3,$s1 : this instruction is wrong because $s3 register contains the address of the vector and no the value .
li $v0,10 ; syscall And remove these lines just ahead the jump to UPDATE .
Otherwise , a program will multiply only once
.data
s: .word 3
v: .word 14 3 12 #hard coding vector coefficients
t: .word 2 #value to be multiplied by
.globl main
.text
main:
la $s0,t #loading t into $s0
lw $s1,0($s0) # $s1=2
ori $s2,$zero,0 # $s2=0
la $s3,v # loading v into $s3
li $s7,0
la $s0,s # loading s into $s0
lw $s4,0($s0) # $s4 = 3
j f
f:
#if <cond>
bge $s2,$s4,DONE
#<for body>
lw $s5, ($s3) # $s5= 4
mulu $s5,$s5,$s1
addu $s7,$s7,$s5 # result stored into $s7
j UPDATE
UPDATE:
addiu $s2,$s2,1 #i=i+1
addiu $s3,$s3,4 #moving address 4 bytes since int
j f
DONE:
li $v0,10
syscall

Related

GNU ASM .section directive not working/linker issue

I'm trying to move my _start function to 0x0, as it is the bootloader.
Flash ROM exists from 0x0 to the first 128MB (=1Gb), other memory is DDR3 RAM but we will map RAM to 0x80000000 to 0xFFFFFFFF.
The issue is with the directive .section ".vect", the _start address is not going into the .vect section, it is going into the .text section.
_start:
.section ".vect" /* I've tried .section .vect and I've tried moving above _start */
b ResetHandler
b UndefHandler
b SVC_Handler
b PrefetchAbortHandler
b DataAbortHandler
b NotUsedHandler
b IRQ_Handler
b FIQ_Handler
1:
b 1b /* Hang and don't return */
In my linker script, the MEMORY command and then the start of SECTIONS is:
MEMORY
{
vect (rx) : o = 0x0, l = 1M
rom (rx) : o = 1M, l = 127M
ram (wx) : o = 0x80000000, l = 0x80000000
}
SECTIONS
{
.vect : ALIGN(64)
{
. = 0x0;
*(.vect*)
VectTableEnd = .;
VectTableSize = SIZEOF(.vect);
} > vect
.... (.text, .bss, .data, .stack, etc are other SECTIONS entries)
}
But no matter what, the _start assembly function code gets shoved into the standard .text section, not at address 0x0. Does anyone know what I'm going wrong?
The code is targetted at bare-metal ARMv7A machines, compiled/linked with arm-none-eabi-as/ld
Cheers.
No surprises here if your _start label ends up in .text:
/* implicitly default section .text */
_start:
/* still the same section .text */
.section .vect
/* explicitly the section .vect */
b ResetHandler
You probably want to switch the section before defining the _start label to make that label end up in the intended section.
/* implicitly default section .text */
.section .vect
/* explicitly the section .vect */
_start:
b ResetHandler
Using the name _start as the symbol for a vector table is a bit weird (I would have expected a symbol like __vectors or vector_table), but that is beyond the scope of this question.

Is there a way in MIPS to read input from a user that can be either an integer or a character?

I am writing a program in MIPS to convert a temperature in Celsius input by the user to Fahrenheit. The program loops to allow the user to do as many conversions as they want. To exit the program they are supposed to enter q. Is there a way to take input that can be either an integer or a character? One possible solution I thought of is reading a string and converting it to an int, but I am a bit unsure how to go about doing that. Is there a simple way of doing that conversion?
.globl main
.data
prompt: .asciiz "Please input a Celsius temperature: "
num: .word 32
li $t4, 0
.text
main:
li $v0, 4
la $a0, prompt # prints Prompt
syscall
li $v0, 5 # user input
syscall
move $a0, $v0 # moves input value in $a0
lw $s0, num # Loads 32 in $s0
li $t0, 0 # Sets up 9/5
li $t1, 0
mtc1 $t0, $f2 # Converts into float point numbers
mtc1 $t1, $f30
move $a1, $t3
move $a2, $s0
jal Temp # jumps to function Temp
move $s4, $v0
li $v0, 1
move $a0, $s4
syscall
li $v0, 10
syscall
Temp:
mul $t0, $a0, 9 # 9 * userInput Should equal 180
div $t4, $t0, 5 # value of register in t0 divided by 5
add $t1, $t4, $a2 # Answer above + 32
move $v0, $t1 # places in return register
jr $ra # Jumps to line after function call
I have provided an example program that only takes the temperature input in Celsius from the user and converts it into Fahrenheit. Your idea can be implemented using while loop.
for example:
la $t0,str #str can be the string char "q"
loop: lb $a0,0($t0)
beq $a0,$0,exit
# your main code
addi $t0,$t0,1
j loop
exit:
however it isnt easy but doable task.

8085 program to add two 8-bit numbers in 8085 simulator

I am trying to add two 8 bit number and wrote the following code:
MVI D 08h
MVI B 03h
MVI C 00h
MOV A D
LOOP: CMP B
JC DOWN
INR A
SUB B
JNZ LOOP
DOWN: HLT
But I got incorrect output.
Well assuming my assumption is correct that you are storing answer in C,
then just do a small change on 7th line:
MVI D 08h
MVI B 03h
MVI C 00h
MOV A D
LOOP: CMP B
JC DOWN
INR C
SUB B
JNZ LOOP
DOWN: HLT
It should work now.

NASM local variables - are they, in fact, global macros?

I've been using the %local directive in NASM to define local variables and thus avoid typing [ebp - 8], [ebp - 24] etc. all the time.
However, I noticed that a local variable defined in one function between the preprocessor context %push and %pop is still available in the rest of the code, which may result in unexpected parsing errors.
Here, I've written a minimal example demonstrating the problem:
struc Rect
.left resd 1
.top resd 1
.width resd 1
.height resd 1
endstruc
%define RECT(x) g_rect + Rect. %+ x
segment .bss
g_rect resd 4
segment .text
; ================================================
function1:
%push
%stacksize flat
%assign %$localsize 0
%local width:dword ; defines local var "width"
push ebp
mov ebp, esp
sub esp, 4
pusha
; ...
popa
leave
ret
%pop
; ================================================
function2:
push ebp
mov ebp, esp
pusha
; ...
mov eax, RECT(height) ; OK
mov ebx, RECT(width) ; Parse error
; ...
popa
leave
ret
The exact error is:
nasm -f elf -d ELF_TYPE -g test.asm
test.asm:42: error: comma, colon, decorator or end of line expected after operand
Obviously, it happens because width is getting substituted with something else, and if I remove the local param definition, the problem goes away.
As you can see, the variable width is still available after the %pop. This doesn't look very local to me! I'd expect NASM to undefine width when the %pop is executed.
Is there a way to use %local but avoid these leaking macros? At the moment they act as a simple %define statement which is confusing.

MIPS: String Copy, Pass-by-reference

I am looking to implement string copy and I am not doing it correctly. I am given a string 'x' and I want to
1] copy the entire string 'x' into 'y'
2] copy the first 5 characters of 'x' into 'y'
and I want to pass arguments by reference.
.data
x: .asciiz "Hi, How do you do?"
y: .word 0:5
.text
.globl main
_copy:
lw $t0, ($a0)
la $a0, y
sw $t0, ($a0)
li $v0, 4
syscall
jr $ra
main:
la $a0, x
jal _copy
jr $ra
nop