ich Ihren Code festgelegt haben. Ich habe versucht, ihm möglichst treu zu bleiben, musste aber erhebliche Umstrukturierungen vornehmen.
Ein paar Dinge zu beachten.
Ich habe Funktionen erstellt (nach der Problembeschreibung). Das heißt, anstelle von einem langen main
, teile ich Dinge auf, genau wie in C. Ich habe Blockkommentare für jede Funktion hinzugefügt.
In main
, ich die Array-Anzahl in $s0
und die Array-Basisadresse in $s1
geladen. Die Berechnungsfunktionen richten ihre Werte hieraus ein, anstatt den Code zu replizieren. (d. h.) Die Array-Adresse und der Zählwert können in einen Ort eingestellt/geändert werden, falls gewünscht.
Ich habe einige Kommentare in der Seitenleiste geändert, um die Absicht besser zu beschreiben, anstatt lediglich die Mechanik der Anweisungen neu zu formulieren.
Ich habe auch die Etiketten so war es einfacher, sie zu den Funktionen entsprechen sie in waren (zum Beispiel alle Etiketten in Funktion foo
sind foo_blah
)
I statische Testdaten erstellt Tests zu beschleunigen. Notieren Sie den auskommentierten jal dataread
, um den Benutzer tatsächlich aufzufordern.
Hier ist der korrigierte Code:
.data
array: .space 80
array2: .word 3, 3, 3, 17, 3
.word 3, 24, 3, 3, 4
.word -4, -8, 97, 3, 2
.word 3, 3, 3, 3, 3
newLine: .asciiz "\n" # I will use it to start a new line
space: .asciiz " " # I will use it to have a space
Prompt: .asciiz "\n Enter an integer: "
msg_min: .asciiz "The smallest value in the array is "
msg_max: .asciiz "The largest value in the array is "
msg_div4: .asciiz "The number of integers divisible by 4 is "
msg_sum: .asciiz "The sum of the integers is "
msg_prod: .asciiz "The product of the integers is "
.globl main
.text
main:
li $s0,20 # set array count
la $s1,array2 # set array address
# NOTE: uncomment this to really prompt user (vs. testing)
###jal dataread # prompt user for data
jal minmax # compute minimum/maximum
jal div4 # count number divisible by 4
jal sumprod # compute sum and product
li $v0,10
syscall
# dataread -- prompt user for data
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
dataread:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
dataread_loop:
la $a0,Prompt
li $v0,4
syscall
li $v0,5 # reading an integer
syscall
sw $v0,0($t1) # storing the integer entered
add $t0,$t0,-1 # decrement the number of integers by one
add $t1,$t1,4 # load the address of the next integer
bgtz $t0,dataread_loop # branch to read and store the next integer
jr $ra # return
# minmax -- compute min/max
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
# t2 -- minimum value
# t3 -- maximum value
# t4 -- current array value
minmax:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
lw $t2,0($t1) # initialize smallest
move $t3,$t2 # initialize largest
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
minmax_loop:
blez $t0,minmax_done # at end of array? if yes, fly
lw $t4,0($t1) # fetch current array element
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
bge $t4,$t2,minmax_notlt # new minimum? if no, fly
move $t2,$t4 # yes, set it
minmax_notlt:
ble $t4,$t3,minmax_loop # new maximum? if no, loop
move $t3,$t4 # yes, set it
b minmax_loop
minmax_done:
li $v0,4 # system call code for print_str
la $a0,msg_min # message to print
syscall
move $a0,$t2 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
li $v0,4 # system call code for print_str
la $a0,msg_max # message to print
syscall
move $a0,$t3 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
jr $ra # return
# div4 -- get number of integers divisible by 4
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
# t2 -- count of array elements divisible by 4
# t4 -- current array value
div4:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
li $t2,0 # initialize count
div4_loop:
blez $t0,div4_done # at end of array? if yes, fly
lw $t4,0($t1) # fetch current array value
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
andi $t4,$t4,0x03 # divisible by 4?
bnez $t4,div4_loop # no, loop
addi $t2,$t2,1 # yes, increment count
b div4_loop # loop
div4_done:
li $v0,4 # system call code for print_str
la $a0,msg_div4 # message to print
syscall
move $a0,$t2 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
jr $ra
# sumprod -- compute sum and product
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
# t2 -- summation value
# t3 -- product value
# t4 -- current array value
sumprod:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
li $t2,0 # initialize sum
li $t3,1 # initialize product
sumprod_loop:
blez $t0,sumprod_done # at end of array? if yes, fly
lw $t4,0($t1) # fetch current array value
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
add $t2,$t2,$t4 # compute the sum
mul $t3,$t3,$t4 # compute the product
b sumprod_loop
sumprod_done:
li $v0,4 # system call code for print_str
la $a0,msg_sum # message to print
syscall
move $a0,$t2 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
li $v0,4 # system call code for print_str
la $a0,msg_prod # message to print
syscall
move $a0,$t3 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
jr $ra # return
Hier ist eine kompaktere Variante, die einen Trick von Sorten verwendet. Es verwendet das Äquivalent von "Tail Call Optimization", um eine gemeinsame Druckroutine zu haben, anstatt den Druckcode in jeder Berechnungsfunktion zu replizieren.
Das heißt, der „Trick“ ist die Berechnungsfunktionen Argumente für den Druck einrichten und dann Sprung, um es über j
[stattdessen eine zweite Ebene zu tun jal
] und die Druckfunktion wird die jr $ra
, die normalerweise wären getan durch die Berechnungsfunktionen.
Wie auch immer, hier ist der Code:
.data
array: .space 80
array2: .word 3, 3, 3, 17, 3
.word 3, 24, 3, 3, 4
.word -4, -8, 97, 3, 2
.word 3, 3, 3, 3, 3
newLine: .asciiz "\n" # I will use it to start a new line
space: .asciiz " " # I will use it to have a space
Prompt: .asciiz "\n Enter an integer: "
msg_min: .asciiz "The smallest value in the array is "
msg_max: .asciiz "The largest value in the array is "
msg_div4: .asciiz "The number of integers divisible by 4 is "
msg_sum: .asciiz "The sum of the integers is "
msg_prod: .asciiz "The product of the integers is "
.globl main
.text
main:
li $s0,20 # set array count
la $s1,array2 # set array address
# NOTE: uncomment this to really prompt user (vs. testing)
###jal dataread # prompt user for data
jal minmax # compute minimum/maximum
jal div4 # count number divisible by 4
jal sumprod # compute sum and product
li $v0,10
syscall
# dataread -- prompt user for data
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
dataread:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
dataread_loop:
la $a0,Prompt
li $v0,4
syscall
li $v0,5 # reading an integer
syscall
sw $v0,0($t1) # storing the integer entered
add $t0,$t0,-1 # decrement the number of integers by one
add $t1,$t1,4 # load the address of the next integer
bgtz $t0,dataread_loop # branch to read and store the next integer
jr $ra # return
# minmax -- compute min/max
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
# t2 -- minimum value
# t3 -- maximum value
# t4 -- current array value
minmax:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
lw $t2,0($t1) # initialize smallest
move $t3,$t2 # initialize largest
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
minmax_loop:
blez $t0,minmax_done # at end of array? if yes, fly
lw $t4,0($t1) # $v0 = Mem($t1)
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
bge $t4,$t2,minmax_notlt # new minimum? if no, fly
move $t2,$t4 # yes, set it
minmax_notlt:
ble $t4,$t3,minmax_loop # new maximum? if no, loop
move $t3,$t4 # yes, set it
b minmax_loop
minmax_done:
la $a2,msg_min # first message
la $a3,msg_max # second message
j print
# div4 -- get number of integers divisible by 4
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
# t2 -- count of array elements divisible by 4
# t4 -- current array value
div4:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
li $t2,0 # initialize count
div4_loop:
blez $t0,div4_done # at end of array? if yes, fly
lw $t4,0($t1) # fetch current array value
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
andi $t4,$t4,0x03 # divisible by 4?
bnez $t4,div4_loop # no, loop
addi $t2,$t2,1 # yes, increment count
b div4_loop # loop
div4_done:
la $a2,msg_div4 # first message
li $a3,0 # _no_ second message
j print
# sumprod -- compute sum and product
#
# registers:
# t0 -- remaining count
# t1 -- array address pointer
# t2 -- summation value
# t3 -- product value
# t4 -- current array value
sumprod:
move $t0,$s0 # initialize array count
move $t1,$s1 # initialize array pointer
li $t2,0 # initialize sum
li $t3,1 # initialize product
sumprod_loop:
blez $t0,sumprod_done # at end of array? if yes, fly
lw $t4,0($t1) # fetch current array value
add $t1,$t1,4 # load the address of the next integer
addi $t0,$t0,-1 # decrement remaining count
add $t2,$t2,$t4 # compute the sum
mul $t3,$t3,$t4 # compute the product
b sumprod_loop
sumprod_done:
la $a2,msg_sum # first message
la $a3,msg_prod # second message
j print
# print -- common print function
#
# arguments:
# a2 -- first message
# t2 -- first value
# a3 -- second message
# t3 -- second value
print:
beqz $a2,print_skip1 # skip if no first argument
li $v0,4 # system call code for print_str
move $a0,$a2 # get address of first message
syscall
move $a0,$t2 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
print_skip1:
beqz $a3,print_skip2 # skip if no second argument
li $v0,4 # system call code for print_str
move $a0,$a3 # get address of second message
syscall
move $a0,$t3 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
print_skip2:
jr $ra # return
Hier ist ein C-Programm, das ich für den Vergleich Tests und Validierung verwendet:
// mipsmmdsp/mipsmmdsp -- check validity of mask for divisibility
#include <stdio.h>
#include <stdlib.h>
int array2[20] = {
3,3,3,17,3,
3,24,3,3,4,
-4,-8,97,3,2,
3,3,3,3,3
};
// sumprod -- calculate sum and product
void
sumprod(void)
{
int idx;
int val;
int sum;
int prod;
int div4;
int min;
int max;
sum = 0;
prod = 1;
div4 = 0;
min = array2[0];
max = array2[0];
for (idx = 0; idx < 20; ++idx) {
val = array2[idx];
if (val < min)
min = val;
if (val > max)
max = val;
if ((val % 4) == 0)
++div4;
sum += val;
prod *= val;
}
printf("min=%d max=%d div4=%d sum=%d prod=%d\n",min,max,div4,sum,prod);
}
// modcheck -- check validity of mod mask
void
modcheck(void)
{
int lo;
int hi;
int val;
int mskflg;
int modflg;
long long cnt;
lo = -100;
hi = 100;
lo = -2000000000;
hi = 2000000000;
cnt = 0;
for (val = lo; val <= hi; ++val, ++cnt) {
mskflg = ((val & 0x03) == 0);
modflg = ((val % 4) == 0);
#if 0
printf("modcheck: %4d/%8.8X: mskflg=%d modflg=%d\n",
$val,$val,$mskflg,$modflg);
#endif
if (mskflg != modflg) {
printf("modcheck: FAIL %4d/%8.8X: mskflg=%d modflg=%d\n",
val,val,mskflg,modflg);
exit(1);
}
}
printf("modcheck: cnt=%lld\n",cnt);
}
// main -- main program
int
main(void)
{
modcheck();
sumprod();
return 0;
}
Randbemerkung:
Neben dem spim
Simulator gibt es den mars
Simulator. Es ist hier zu finden: http://courses.missouristate.edu/KenVollmar/MARS/
ich beide und es vorziehen, in den meisten Fällen mars
verwendet haben - YMMV
Verwenden Sie Ihren Debugger/Simulator zu einzelnen Schritt der Code und sehen, wo es schief geht. Hinweis: Bei 'ret2' überschreiben Sie den Wert in' $ v0', den Sie später drucken wollen ... PS: Sie wissen, dass Sie keine Funktionen geschrieben haben, oder? (Außer für "Summe") – Jester
@Jester - danke für die schnelle Antwort und Hilfe. Wie kommt es, dass mein Code keine Funktionen erfüllt? Ich bin immer noch sehr neu in der Montage und stecken geblieben, also jede Hilfe würde geschätzt werden! –
Sie lesen ganze Zahlen in "main", dann folgen Sie sofort durch Berechnen von min/max. Wenn ein anderer Teil Ihrer App sie erneut verwenden möchte, kann sie nicht aufgerufen werden. Um es zu einer Funktion zu machen, verschieben Sie den Code außerhalb von main und rufen Sie ihn mit 'jal' auf. (und einen Weg definieren, wie die Funktionsparameter, d. h. die Array-Länge, der Array-Zeiger und wie sie Min und Max zurückgibt, angegeben werden. Auf diese Weise können Sie dann die Min/Max-Funktion von jedem Teil der App aus auf jedem beliebigen Array aufrufen. – Ped7g