Error in C:\Users\user\Downloads\question2.asm line 12 column 2: "lui": Too many or incorrectly formatted operands. Expected: lui $t1,100 [duplicate] - mips

I used 'compiler explorer' to convert c++ to MIPS
but it doesn't work well in the MARS because of %hi and %lo
I know I should change the part, but I don't know how to change...
Please help
$L5:
lui $2,%hi($LC1)
lwc1 $f0,%lo($LC1+4)($2)
lwc1 $f1,%lo($LC1)($2)
b $L3
$LC1:
.word 1100470148
.word 0
$L17:
lw $2,16($fp)
addiu $3,$2,1
sw $3,16($fp)
lui $4,%hi(savepath)
sll $3,$2,2
addiu $2,$4,%lo(savepath)
addu $2,$3,$2
li $3,1 # 0x1
sw $3,0($2)
move $sp,$fp
lw $fp,36($sp)
addiu $sp,$sp,40
j $31

AFAIK, there is no way in Mars to have something like the gas %lo(label) or %hi(label) feature.
A simple workaround is to use the standard macro la that loads a label in a register with a pair or lui/ori instructions.
The first part of your code can be rewritten like that:
$L5:
la $2, $LC1
lwc1 $f0,4($2)
lwc1 $f1,0($2)
b $L3
$LC1:
.word 1100470148
.word 0
As the la macro is expanded to two instructions,that is an extra instruction compared to the use of %hi/%lo but it works.

Related

MIPS errors with %hi and %lo

lui $v0,%hi(length)
lw $v1,%lo(length)($v0)
li $v0,3 # 0x3
bne $v0,$zero,1f
div $zero,$v1,$v0
break 7
mfhi $v0
mflo $v0
sw $v0,28($fp)
lw $a1,28($fp)
lui $v0,%hi(game_over)
addiu $a0,$v0,%lo(game_over)
jal printf
nop
When I try running this for my MIPS code, it comes up with this error:
Your program produced these errors:
spim: (parser) Unknown character on line 180 of file measurement.s
lui $v0,%hi(length)
spim: (parser) syntax error on line 181 of file measurement.s
Instruction references undefined symbol at 0x00400038
[0x00400038] 0x0c000000 jal 0x00000000 [init_measure] ; 159: jal init_measure
Do I need to substitute %hi and $lo for something else in the code?
EDIT For the following code:
sw $v0,16($fp)
lui $a0,%hi(grid)
lw $v1,12($fp)
nop
move $v0,$v1
sll $v0,$v0,4
subu $v0,$v0,$v1
addiu $v1,$a0,%lo(grid)
addu $v1,$v0,$v1
lw $v0,16($fp)
And
lui $v0,%hi(column)
lb $v0,%lo(column)($v0)
nop
sw $v0,12($fp)
lui $v0,%hi(column)
addiu $v1,$v0,%lo(column)
lw $v0,8($fp)
nop
addiu $v1,$v0,-1
lui $v0,%hi(growth)
sw $v1,%lo(growth)($v0)
b true
nop
Will I be substituting %hi and % lo it in a similar manner or differently?
Those seem to be operators not supported by spim. %LO(label) should give you the lowest half of the address of label, and %HI(label) the upper half.
You can substitute these two instructions:
lui $v0,%hi(length)
lw $v1,%lo(length)($v0)
with this:
la $v0,length
lw $v1,0($v0)
So we use la pseudoinstruction to load the whole address of the label onto a register (in the example $v0) then you directly load its memory contents using 0 as the lw offset. Note that la pseudoinstruction would use 2 instructions for an arbitrary label address (and leave $at with the upper half address).
Also note that in your code $v0 would still hold the upper half of the label address whereas in the second snippet it will contain the whole address.
Similarily, instead of
lui $v0,%hi(game_over)
addiu $a0,$v0,%lo(game_over)
you can just issue:
la $a0, game_over
In this case, your code would end with $a0 having the address of game_over label (as in the second snippet), and $v0 holding the lower half of that address. la pseudoinstruction will leave the upper half of the label on $at

How do I use multiple arguments in a mips assembly function?

I am reading in two integers, the first must be between 1 and 7. The second must be between 1 and 7, and not less than the first. To check these number I am using a function and then returning either 1 or 0, which will repeat the input in a loop until a valid input is given.
Here is my problem: The first number seems to go in well, and it loops until a valid input is given. However for my second function, it's pretty much the same but I am using two arguments ($a0 for the first number and $a1 for the second). Whenever I run the program on QTSpim, it freezes immediately after entering the second integer. Can anyone help me?
Here is my code:
main:
li $v0,5
syscall
move $a0,$v0
jal checkdiv
move $s0,$a0
slt $t0,$zero,$v1
beq $t0,$zero,NE
j main
NE:
li $v0,5
syscall
move $a0,$v0
move $a1,$s0
jal checknum
#These are the two check functions
checkdiv:
addiu $sp,$sp,-8
sw $ra,4($sp)
sw $a0,0($sp)
li $t0,1
slt $v1,$a0,$t0
beq $v1,$t0,D1
li $t0,7
slt $v1,$t0,$a0
D1:
lw $ra,4($sp)
lw $a0,0($sp)
addiu $sp,$sp,8
jr $ra
#Second check function
checknum:
addiu $sp,$sp,-16
sw $ra,8($sp)
sw $a0,4($sp)
sw $a1,0($sp)
slt $v1,$a0,$a1
li $t0,1
beq $v1,$t0,N1
li $t0,7
slt $v1,$t0,$a0
N1: lw $ra,8($sp)
lw $a0,4($sp)
lw $a1,0($sp)
addiu $sp,$sp,16
jr $ra

Self-Modifying MIPS Code

I'm trying to write a program in MIPS that continuously prompts for two integers and prints the sum until the sum is 0. The trick is that if the sum is 13, I need to call a method to change the assembled MIPS code so that
add $t2, $t0, $t1
becomes
and $t2, $t0, $t1
and all subsequent runs of the loop use the and instruction.
I have the summation loop working so that when 13 is the sum the method instMod is called which I want to modify the instruction. Unfortunately, I have no idea where to start and can't find any examples of this online. I assume I need to somehow get the hex code of the add out of the assembled code and replace it with the hex code for the and but I do not know how to do that or if that is the right course of action to take.
# Nick Gilbert
# MIPS Program to demonstrate self-modifying code
.data
num1Prompt: .asciiz "Enter num1: "
num2Prompt: .asciiz "Enter num2: "
num1: .word 0
num2: .word 0
addOut: .asciiz "ADD: "
andOut: .asciiz "AND: "
.text
main:
sumLoop:
la $a0, num1Prompt #Asking user for num1
li $v0, 4 #Call code to print string
syscall
li $v0, 5 #Call code to read an int
syscall
move $t0, $v0 #Moving read int to $t1
la $a0, num2Prompt #Asking user for num2
li $v0, 4 #Call code to print string
syscall
li $v0, 5 #Call code to read an int
syscall
move $t1, $v0 #Moving read int to $t2
add $t2, $t0, $t1 #Adding num1 and num2 together
la $a0, addOut
li $v0, 4
syscall
move $a0, $t2
li $v0, 1
syscall
beq $t2, 13, instMod #Calling method to modify add instruction if sum = 13
bne $t2, 0, sumLoop #If result is not yet 0, ask for new sum
endSumLoop:
li $v0, 10
syscall
instMod: #Method to change add instruction to an and instruction
Add a label at the instruction you want to replace, e.g:
instruction_to_be_replaced:
add $t2, $t0, $t1 #Adding num1 and num2 together
then in your routine instMod
instMod: #Method to change add instruction to an and instruction
lw $t1, instruction_to_replace
sw $t1, instruction_to_be_replaced
j sumLoop # go back to your sumLooop
instruction_to_replace:
and $t2, $t0, $t1
The code loads in temporary register $t1 the contents of the instruction you want to replace, and then stores it in the location labelled instruction_to_be_replaced.
The "source" of the instruction goes labelled in instruction_to_replace.
To do this, you need to be able to write on the code section which I assume you have otherwise you would not be asking this question.
Try this:
Assemble the instruction that you need to an object file
Extract the hexadecimal of the equivalent machine code
Place a label in front of the code you need to change
mov the hexidecimal from step 2 into the location from step 3 in your instMod section
For this to function the two instructions with operands must be of identical length. If they are not, pad the original or the replacement with nop as appropriate.

What is a function/How to distinguish a function in MIPS?

Extremely new to MIPs assembly language -- I haven't been able to find a link that specifically tells you what a function is distinguished as in MIPS, examples of how we use jal, jr, etc..
It's very difficult to find out how these actions work -- My text book for this section of the course is very broad and assumes I already know the language and just outlines a code (under the assumption that I know exactly what the code means)
Hence, the book isn't helping me so I'm trying to practice on my own..
Anywho, in my class we wrote a simple array code which supposedly has a "function" in it.
My question is -- how do I know what is the "function"
Below is a code we did in class -- it's supposed to output an array from 1 to 10.. I understand where it increments and such (addi) and why it's a 1 and 4 but I don't understand
what $ra, jal , jr mean... but I'm assuming that these have something to do with what a "function" is
#Load an array and display
.data
.align 2
a1: .space 40
.text
.globl main
main:
la $s0, a1
jal loadArray
la $s0, a1# <- return here after function return
jal displayArray
# <- return here after 2nd function
exit:
li $v0, 10
syscall
displayArray:
#$ra = the address of line 14
li $t0, 1 #int i = 0
displayLoop: blt $t0, 11, display
#else
jr $ra
display:
lw $t0, ($s0) # a1[i] = i;
li $v0, 1
move $a0, $t0
syscall
#incremment i and array pointer
addi $t0, $t0, 1
addi $s0, $s0, 4
j displayLoop
loadArray:
#$ra = the address of line 14
li $t0, 1 #int i = 0
loadLoop: blt $t0, 11, load
#else
jr $ra
load:
sw $t0, ($s0) # a1[i] = i;
#incremment i and array pointer
addi $t0, $t0, 1
addi $s0, $s0, 4
j loadLoop
So this is the sample code but the only difference between this code and a usual code with just labels is the jump register and jump and link...
Does that distinguish what is a function???
Sorry for the long wall of text -- TL;DR In MIPS, how do you know what is a "function" I know what a label is (obv.) but not a function...
This isn't as straight forward to me as it is in cpp or java lol.
A function (or subroutine) is really just any piece of code that you can call (with jal) and expect to return to you (with jr $ra). It is also generally expected to keep your stack and registers intact across the call.
The term function is used more often by high-level languages like C, whereas subroutine is more common at the assembly-language level.
jal means "Jump And Link" - I would expect this to be covered in your textbook. This instruction 1) stores the return address (the address of the instruction after the jal) in $ra, the link register (or return address register) and then 2) jumps to the target address. This is how you call a function.
When the function is finished, it returns to the caller by jumping to the address in the return address register, with the jr $ra instruction (Jump to Register $ra).
Your comments imply that you already understand this:
jal loadArray
la $s0, a1# <- return here after function return
jal displayArray
# <- return here after 2nd function
So loadArray can be considered a function, as can displayArray.
Read more:
Subroutines/Functions in MIPS
MIPS Quick Tutorial
MIPS Instruction Reference
MIPS Assembly/Control Flow Instructions
jal and jr

MIPS load address la doesn't always use register $1?

Please refers to the edit portion for my explanation.
This is a bit long and difficult to illustrate. But I appreciate taking your time to read this. Please bear with me.
Suppose I have this:
.data
str1: .asciiz "A"
str2: .asciiz "1"
myInt:
.word 42 # allocate an integer word: 42
myChar:
.word 'Q' # allocate a char word
.text
.align 2
.globl main
main:
lw $t0, myInt # load myInt into register $t0
lw $t3, str1 # load str1 into register $t3
lw $t4, str2 #load str2 into register $t4
la $a0, str1 # load address str1
la $a1, str2 # load address str2
Then in SPIM, the user text segment is
User Text Segment [00400000]..[00440000]
[00400000] 8fa40000 lw $4, 0($29) ; 183: lw $a0 0($sp) # argc
[00400004] 27a50004 addiu $5, $29, 4 ; 184: addiu $a1 $sp 4 # argv
[00400008] 24a60004 addiu $6, $5, 4 ; 185: addiu $a2 $a1 4 # envp
[0040000c] 00041080 sll $2, $4, 2 ; 186: sll $v0 $a0 2
[00400010] 00c23021 addu $6, $6, $2 ; 187: addu $a2 $a2 $v0
[00400014] 0c100009 jal 0x00400024 [main] ; 188: jal main
[00400018] 00000000 nop ; 189: nop
[0040001c] 3402000a ori $2, $0, 10 ; 191: li $v0 10
[00400020] 0000000c syscall ; 192: syscall # syscall 10 (exit)
[00400024] 3c011001 lui $1, 4097 ; 23: lw $t0, myInt # load myInt into register $t0
[00400028] 8c280004 lw $8, 4($1)
[0040002c] 3c011001 lui $1, 4097 ; 25: lw $t3, str1 # load str1 into register $t3
[00400030] 8c2b0000 lw $11, 0($1)
[00400034] 3c011001 lui $1, 4097 ; 27: lw $t4, str2 #load str2 into register $t4
[00400038] 8c2c0002 lw $12, 2($1)
[0040003c] 3c041001 lui $4, 4097 [str1] ; 29: la $a0, str1 # load address str1
[00400040] 3c011001 lui $1, 4097 [str2] ; 31: la $a1, str2 # load address str2
[00400044] 34250002 ori $5, $1, 2 [str2]
I understand that lw is a pseudocode so it needs to be broken down into two instructions. I understand this part. We use the entry address of data segment as a "base pointer" and relatively accessing other data (including the first data).
I also observed that loading address of str1 and str2 used two different registers: $4 and $1. $4 is $a0.
Why is that?
If I swap the last two instructions, on SPIM I see
...
[0040003c] 3c011001 lui $1, 4097 [str2] ; 31: la $a1, str2 # load address str2
[00400040] 34250002 ori $5, $1, 2 [str2]
[00400044] 3c041001 lui $4, 4097 [str1] ; 32: la $a0, str1 # load address str1
So why is load address so strange? Why did str2 use $1 ???
How can I go about explaining how lui $1, 4097 [str2] and lui $4, 4097 [str1] are different?
PS: Can someone also explain to me why we need the bracket [str2] ?
lui, $1, 4097, [str2] only pushes the entry address of data segment to register $1. That is, 0x10010000 .
Thank you very much!
EDIT
I rewrote the entire script to simplify the situation.
Script: http://pastebin.com/BHh89iqt
Text Segment: http://pastebin.com/t2eDEs1f
Let me remind you that we write in pseudo instructions, rather than true MIPS machine code. That is, "lw", "jal", "addi", etc are all pseudo instructions.
For example, lw (load word) is broken down into two machine instructions (look at the text segement):
lui $1, 4097 ; 23: lw $t0, myInt # load myInt into register $t0
lw $8, 4($1)
MIPS is 32-bit, we therefore break it down into two instructions. The total of addressing a 32-bit address will result in 43 bits instruction set.. this is why we break down into 2 parts.
A label is a memory address pointing at the thing we assigned to.
MIPS can only read instructions of the form lw $rt, offset($rs). So most of the load instructions follow this approach and use $at to convert pseudoinstructions that involve labels to MIPS machine instructions.
For lw it's pretty easy. For la load address it's a bit tricky.
Pay attention to the last four load address instructions. MIPS translates them into this:
[0040003c] 3c041001 lui $4, 4097 [str1] ; 27: la $a0, str1 # load address str2
[00400040] 3c011001 lui $1, 4097 [str2] ; 28: la $a0, str2 # load address str1
[00400044] 34240002 ori $4, $1, 2 [str2]
[00400048] 3c011001 lui $1, 4097 [str2] ; 30: la $a0, str2 # load address str2
[0040004c] 34240002 ori $4, $1, 2 [str2]
[00400050] 3c041001 lui $4, 4097 [str1] ; 31: la $a0, str1 # load address str1
$4 refers to $a0. If you look at the instructions, I swapped the first two load instructions and the result is the last two instructions.
I purposely did this to illustrate the strange behavior: before swapping, lui uses $4 to store the address of str1, but if I want to load the address of str2, I will use $at and then apply offset.
I couldn't figure out why last night, and just now, I realized that this is done because the compiler is smart enough to know that str1 is the first data in the data segement, so there is no need to convert anything.
Yet this is also strange because how does the compiler know at what byte to stop printing the string? (if we want to print a string...)
My guess: Null character to terminate print.
Anyhow. I guess this is just a convention that the MIPS uses.
Second Edit
In fact if you just add a new data on top of str1, you will see that
my explanation is correct.
New script: http://pastebin.com/8DuzFrk0
New Text Segment: http://pastebin.com/YXbvzc4z
I only added myCharB to the top of the data segment.
[0040003c] 3c011001 lui $1, 4097 [str1] ; 29: la $a0, str1 #
load address str2
[00400040] 34240004 ori $4, $1, 4 [str1]
[00400044] 3c011001 lui $1, 4097 [str2] ; 30: la $a0, str2 #
load address str1
[00400048] 34240006 ori $4, $1, 6 [str2]
I also observed that loading address of str1 and str2 used two
different registers: $4 and $1. $4 is $a0. Why is that?
Well, who cares? xD It's internal SPIM implementation and it's free to use any register as long as it does not break MIPS ABI. I just suggest you not relying too much on pseudo-instructions to make sure what registers have changed/what values they hold. Also usually LW is not a pseudo-instruction, but in the way you're using it is.
Can someone also explain to me why we need the bracket [str2] ?
You don't need any brackets. That's just a SPIM information to the programmer to show this instruction is loading the str2 address. It's not part of the assembly.
lui, $1, 4097, [str2] only pushes the entry address of data segment to
register $1. That is, 0x10010000
Well actually it only load upper half-word of $1. It just happens that the lower half-word is plain zeroes. Keep in mind LUI does not modify lower half-word, so you have to make sure it holds the value you want (reseting register or using LI).
Yet this is also strange because how does the compiler know at what
byte to stop printing the string? (if we want to print a string...)
Null-terminated, as you guessed right.
I guess this is just a convention that the MIPS uses.
This is way older than MIPS. And MIPS doesn't define anything about this, either does any other architecture. This is data handling and it's defined on a upper layer like OS. In this case it is SPIM convention on its own syscalls. Anyway null-terminated strings are pretty common. C programming language uses so for strings.