2016-11-29 6 views
1

2つの浮動小数点の違いを返す関数を作成する必要があります。アセンブリMips - (Floatを含む)2つの文字列を変換し、それらの間のギャップを見つける

例:ユーザーAのLatは22.00、ユーザーBのLatは20.00(または24.00)です。結果は2.00でなければなりません。

これは簡単な減算ですね......私は\ nとポイントなしで浮動小数点を格納する方法を見つけましたが、算術演算で配列を使用する方法を見つけることができません。それはとても不満です。

私は誰かが私に

.data 

dot: .asciiz "." 
aCapo: .asciiz "\n" 

A: .word nome1, cognome1, lat1, long1 
nome1: .asciiz "Paolo\n" 
cognome1: .asciiz "Bonomi\n" 
lat1: .asciiz "69.31\n" 
long1: .asciiz "45.00\n" 

B: .word nome2, cognome2, lat2, long2 
nome2: .asciiz "Xhoni\n" 
cognome2: .asciiz "Lara\n" 
lat2: .asciiz "40.02\n" 
long2: .asciiz "90.00\n" 

array: .space 256 

.text 
.globl main 

main: 

la $a1, A 
la $a2, B 

la $t8, array 

lw $s1, 8($a1) 
lb $t0, 0($s1) 
sb $t0, 0($t8) 
lb $t0, 1($s1) 
sb $t0, 1($t8) 
lb $t0, 3($s1) 
sb $t0, 2($t8) 
lb $t0, 4($s1) 
sb $t0, 3($t8) 

EDITを助ける願っています:私はちょうどこの

この機能を実行する方法を見つけることはそれほど冗長性がある..ところで私は全く機能しないことを知っている、素晴らしい作品しかし、私は多くの時間を持っていけないので...ヒントに感謝そんなにと

diff_geo助ける:

array: .word 1 
array2: .word 1 

risultatoLat: .word 1 
empty: .word 1 

risultatoLong: .word 1 
empty2: .word 1 

# 
# this fuction takes two utentiR in $a1 and $a2 
# and return the difference by lat and long from the two user 
# 

try_lat: 
lw $s1, 8($a1) # put in s1 adress lat1 
la $t8, array 

lb $t0, 4($s1) # 
sb $t0, 0($t8) # 
lb $t0, 3($s1) # 
sb $t0, 1($t8) # 
lb $t0, 1($s1) # 
sb $t0, 2($t8) # 
lb $t0, 0($s1) # 
sb $t0, 3($t8) # 
lw $s0, 0($t8) # put in s0 lat1 without "." and "\n" 

lw $s2, 8($a2) # put in s2 address lat2 
la $t9, array2 # 

lb $t0, 4($s2) # 
sb $t0, 0($t9) # 
lb $t0, 3($s2) # 
sb $t0, 1($t9) # 
lb $t0, 1($s2) # 
sb $t0, 2($t9) # 
lb $t0, 0($s2) # 
sb $t0, 3($t9) # 
lw $s1, 0($t9) # put in s1 lat2 without "." and "\n" 

blt $s0, $s1, switch_utenti  # if latA < latB goto switch 
beq $s0, $s1, return_equal  # if latA = latB return "00.00" 

j do_sub_lat # else do sub 

return_equal: 
la $a0, str_diffLat # stamp "Differenza Latitudine: " 
li $v0, 4 
syscall 

la $a0, str_same # stamp "00.00\n" 
li $v0, 4 
syscall 

j try_long # goto process long 

switch_utenti: 
move $a0, $a1 
move $a1, $a2 
move $a2, $a0 

do_sub_lat: 
lw $s1, 8($a1)   # put in s1 adress lat1 
lw $s2, 8($a2)   # put in s2 adress lat2 
lb $t0, 0($s1)   # load first number of lat1 
lb $t1, 0($s2)   # load first number of lat2 
sub $t2, $t0, $t1  # t2 = t0 - t1 (decimal) 
lb $t0, 1($s1)   # load second number lat1 
lb $t1, 1($s2)   # load second number lat2 
bge $t0, $t1, jEDLat # if (T0 >= T1) jump exception 
li $t7, 1    # load 1 in t7 
li $t6, 9    # load 9 in t6 
sub $t2, $t2, $t7  # sub 1 from first number of the result 
add $t0, $t0, $t6  # add 9 to t0 
sub $t1, $t1, $t7  # sub 1 to t1 (i have to made this because if i try to ad 10 to t0, 10 will be like "a" no "10")   
jEDLat: 
sub $t3, $t0, $t1  # T0 - T1 risultato DECIMALE in T3 
lb $t0, 3($s1)   # carico secondo numero di A 
lb $t1, 3($s2)   # carico secondo numero di B 
bge $t0, $t1, jETLat # if (T0 >= T1) salta eccezione 
li $t7, 1    # carico 1 in T7 
li $t6, 9    # carico 10 in T6 
sub $t3, $t3, $t7  
add $t0, $t0, $t6 
sub $t1, $t1, $t7 
jETLat: 
sub $t4, $t0, $t1  # T0 - T1 risultato DECIMALE in T4 
lb $t0, 4($s1)   # carico quarto numero di A 
lb $t1, 4($s2)   # carico quarto numero di B 
bge $t0, $t1, jEQLat # if (T0 >= T1) salta eccezione 
li $t7, 1    # carico 1 in T7 
li $t6, 9    # carico 10 in T6 
sub $t4, $t2, $t7  
add $t0, $t0, $t6  
sub $t1, $t1, $t7 
jEQLat: 
sub $t5, $t0, $t1  # T0 -T1 risultato DECIMALE in T5 

addi $t2, $t2, 48 
addi $t3, $t3, 48 
addi $t4, $t4, 48 
addi $t5, $t5, 48 


la $t8, risultatoLat 
la $t7, aCapo 
lb $t7, 0($t7) 
sb $t7, 5($t8) 
sb $t5, 4($t8) 
sb $t4, 3($t8) 
la $t7, dot 
lb $t7, 0($t7) 
sb $t7, 2($t8) 
sb $t3, 1($t8) 
sb $t2, 0($t8) 


la $a0, str_diffLat 
li $v0, 4 
syscall 

la $a0, risultatoLat 
li $v0, 4 
syscall 

try_long: 
lw $s1, 12($a1) # Metto in S1 la parola puntata da A1 
la $t8, array 

lb $t0, 4($s1) # 
sb $t0, 0($t8) # 
lb $t0, 3($s1) # 
sb $t0, 1($t8) # 
lb $t0, 1($s1) # 
sb $t0, 2($t8) # 
lb $t0, 0($s1) # 
sb $t0, 3($t8) # 
lw $s0, 0($t8) # IN S0 LONGITUDINE A 

lw $s2, 12($a2) # Metto in S2 la parola puntata da A2 
la $t9, array2 

lb $t0, 4($s2) # 
sb $t0, 0($t9) # 
lb $t0, 3($s2) # 
sb $t0, 1($t9) # 
lb $t0, 1($s2) # 
sb $t0, 2($t9) # 
lb $t0, 0($s2) # 
sb $t0, 3($t9) # 
lw $s1, 0($t9) # IN S1 LONGITUDINE B 

blt $s0, $s1, switch_utenti2 # se latA < latB inverto 
beq $s0, $s1, return_equal2  # se latA = a latB ritorno 00.00  

j do_sub_long 

return_equal2: 
la $a0, str_diffLong # stampo "Differenza Longitudine: " 
li $v0, 4 
syscall 

la $a0, str_same # stampo "00.00\n" 
li $v0, 4 
syscall 

jr $ra # fine funzione 

switch_utenti2: 
move $a0, $a1 
move $a1, $a2 
move $a2, $a0 

do_sub_long: 
lw $s1, 12($a1)   # Metto in S1 la parola puntata da A1 
lw $s2, 12($a2)   # Metto in S2 la parola puntata da A2 
lb $t0, 0($s1)   # carico primo numero di A 
lb $t1, 0($s2)   # carico primo numero di B 
sub $t2, $t0, $t1  # T0 - T2 risultato DECIMALE in T2 
lb $t0, 1($s1)   # carico secondo numero di A 
lb $t1, 1($s2)   # carico secondo numero di B 
bge $t0, $t1, jEDLong # if (T0 >= T1) salta eccezione 
li $t7, 1    # carico 1 in T7 
li $t6, 9    # carico 10 in T6 
sub $t2, $t2, $t7   
add $t0, $t0, $t6 
sub $t1, $t1, $t7  
jEDLong: 
sub $t3, $t0, $t1  # T0 - T1 risultato DECIMALE in T3 
lb $t0, 3($s1)   # carico secondo numero di A 
lb $t1, 3($s2)   # carico secondo numero di B 
bge $t0, $t1, jETLong # if (T0 >= T1) salta eccezione 
li $t7, 1    # carico 1 in T7 
li $t6, 9    # carico 10 in T6 
sub $t3, $t3, $t7  
add $t0, $t0, $t6 
sub $t1, $t1, $t7 
jETLong:  
sub $t4, $t0, $t1  # T0 - T1 risultato DECIMALE in T4 
lb $t0, 4($s1)   # carico quarto numero di A 
lb $t1, 4($s2)   # carico quarto numero di B 
bge $t0, $t1, jEQLong # if (T0 >= T1) salta eccezione 
li $t7, 1    # carico 1 in T7 
li $t6, 9    # carico 10 in T6 
sub $t4, $t2, $t7  
add $t0, $t0, $t6  
sub $t1, $t1, $t7 
jEQLong: 
sub $t5, $t0, $t1  # T0 -T1 risultato DECIMALE in T5 

addi $t2, $t2, 48 
addi $t3, $t3, 48 
addi $t4, $t4, 48 
addi $t5, $t5, 48 

la $t7, aCapo 
lb $t7, 0($t7) 
la $t8, risultatoLong 
sb $t7, 5($t8) 
sb $t5, 4($t8) 
sb $t4, 3($t8) 
la $t7, dot 
lb $t7, 0($t7) 
sb $t7, 2($t8) 
sb $t3, 1($t8) 
sb $t2, 0($t8) 


la $a0, str_diffLong 
li $v0, 4 
syscall 

la $a0, risultatoLong 
li $v0, 4 
syscall 

la $a0, aCapo 
li $v0, 4 
syscall 

jr $ra 
を3210

私は緯度と長い形式はすべて

ctrl_geoで同じであることを省略している:これは私がフロートのような緯度と長い値を格納していないかもしれない場合は...私はことを知っているので、官能化されてないです

# 
# questa funzione prende come argomento in $a0 una indirizzo ad una stringa 
# la funzione contolla se il formato è corretto cioè rispetta il formato "xx.xx\n" con x compreso tra 0 e 9 
# restituisce in $a0 1 se l'inserimento è avvenuto correttamente altrimenti stampa a video una stringa di errore 
# e restituisce in $a0 0 
# 

lb $t0, 0($a0) # carico numero decine in $t0 
lb $t1, min 
blt $t0, $t1, errore_geo # controllo se è minore di 0 
lb $t1, max 
bgt $t0, $t1, errore_geo # controllo se è maggiore di 9 

lb $t0, 1($a0) # carico numero unità in $t0 
lb $t1, min 
blt $t0, $t1, errore_geo # controllo se è minore di 0 
lb $t1, max 
bgt $t0, $t1, errore_geo # controllo se è maggiore di 9 

lb $t0, 2($a0) # carico punto in $t0 
lb $t1, dot 
bne $t0, $t1, errore_geo # se non c'è un punto in t0 mando ad errore 

lb $t0, 3($a0) # carico numero dopo punto decine in $t0 
lb $t1, min 
blt $t0, $t1, errore_geo # controllo se è minore di 0 
lb $t1, max 
bgt $t0, $t1, errore_geo # controllo se è maggiore di 9 

lb $t0, 4($a0) # carico numero dopo punto unità in $t0 
lb $t1, min 
blt $t0, $t1, errore_geo # controllo se è minore di 0 
lb $t1, max 
bgt $t0, $t1, errore_geo # controllo se è maggiore di 9 

lb $t0, 5($a0) # a capo in $t0 
lb $t1, aCapo 
bne $t0, $t1, errore_geo # se in t0 non ho aCAPO mando a errore 

li $a0, 1 
jr $ra # fine funzione 

errore_geo: 
la $a0, str_erroreNumerico 
li $v0, 4 
syscall 

li $a0, 0 
jr $ra # fine funzione 

アスキーのようなもので、大きなトラブルを防ぎました。

+0

幸運は実際にあなたのためにこれを書く時間がかかります誰かを見つける。あなたが求めていることは、Assemblyでたくさんあります!私はもはや言語をよく覚えていないか、私は試してみるでしょう。 – Sethmr

+1

緯度と経度の値をASCII形式で保存する必要がありますか?あなたがフロートとしてそれらを保存することができれば、これはもっと簡単になります。 – Tim

+0

@Timもし彼が文字列から浮動小数点への変換をしていなければ、文字列としてそれらを減算する方が簡単かもしれません:... D ...または整数に変換する方が簡単です。すべてのものに100 *整数を使うことができ、ちょうど最後の2桁の前に ''。 ''で出力します。 (私は一種のことは考えていませんが、ascii - > floatコンバータを書くことから始めます。恐らくC++を使って、それは危険なコードの1つです)。 – Ped7g

答えて

1

は、私はあなたが何を意味するかわからない:

のようにも明確に定義されたことはありません総会における演算処理

ように配列を使用する方法を見つけることができません"array"ですが、多分連続したバイト数を意味します。

subのような算術命令は、レジスタ(ワードサイズのみ)でしか動作できません。以下のようなので、

削除した小数のドットと改行を含む文字列に2つのASCII「数字」を持っている場合、:

num1: .byte '1', '2', '7', '8', 0 # was "12.78\n" 
num2: .byte '5', '6', '3', '4', 0 # was "56.34\n" 
res: .space 16 # should be plenty for lat/lon difference 

n1i = 3, n2i = 3resi = max(n1i, n2i)を設定し、両方のための最後の数字のインデックスを取得します。

ここで、subの絶対値を求めたい場合は、小さい方をチェックし、大きい方から小さい方を引くことができます。

num1bigger = (n2i < n1i) || (n1i == n2i && first_different_digit_is_bigger_in_n1); 
// equal numbers will produce "false" 

EDIT:実際には、これは1特殊なケースのために間違った結果を生成する:先行ゼロを考慮ASCII番号の一部ではないときnum1bigger = true;を生成するnum1 = "0012"num2 = "345"対は、説明したものにのみ機能します。

これは、(空のデータや空のデータなど、該当する場合など)把握できるコーナーケース数でアルゴリズムをユニットテストする必要がある理由と、タスクは簡単にバグでコード化することができます。まあ、単にコード化されていませんが、すでにのバグが高レベルに設計されています。


(あなたがCを知っていない場合はC-のような疑似言語で、その後、申し訳ありません)今減算アルゴリズム:

init: 
     already set: n1i, n2i, num1bigger, num1, num2, res, resi 
     borrow = false, res[resi+1] = 0 

    sub_loop: 
    *1 r1 = (0 <= n1i) ? num1[n1i--] : '0' 
     r2 = (0 <= n2i) ? num1[n2i--] : '0' 
     if (!num1bigger) swap(r1,r2) 
     // r1 is byte-part of bigger number, r2 of smaller 
     if (borrow) ++r2 
    *2 r3 = r1 - r2  // ASCII - ASCII = numeric value 
     borrow = (r3 < 0) 
     if (borrow) r3 += 10 // adjust negative into 0-9 
     r3 += '0'   // add ASCII encoding back 
    *3 res[resi--] = r3 
     if (0 <= resi) jump sub_loop 
     // as the smaller number is subtracted from larger, borrow=0 at end 
     // so no need to patch the result in sign flip way 

     // but you may want to remove leading zeroes 
     // (but keep at least three of them for "0.00" result) 

これはバイトあたりのASCII絶対値減算アルゴリズムです。 (入力[22,20]と[22,24]の両方が+02の結果になります)。

ところで、実際にはほぼ同じですが、!num1biggerの場合、結果=>22-24 = -02の前にマイナス記号を追加する必要があります。

init: 
num1bigger = false, borrow = false, res[4] = 0 
    Loop first iteration: 
    *1 fetching, swapping, borrow adjust: r1 = '4', r2 = '8' 
    *2 subtraction, adjustment: r3 = '6', borrow = true 
    *3 store result: res[3] = '6', n1i == n2i == resi == 2 
    (0 <= resi (2)) -> loop again 
    *1 fetching, swapping, borrow adjust: r1 = '3', r2 = '8' 
    *2 subtraction, adjustment: r3 = '5', borrow = true 
    *3 store result: res[2] = '5', n1i == n2i == resi == 1 
    (0 <= resi (1)) -> loop again 
    *1 fetching, swapping, borrow adjust: r1 = '6', r2 = '3' 
    *2 subtraction, adjustment: r3 = '3', borrow = false 
    *3 store result: res[1] = '3', n1i == n2i == resi == 0 
    (0 <= resi (0)) -> loop again 
    *1 fetching, swapping, borrow adjust: r1 = '5', r2 = '1' 
    *2 subtraction, adjustment: r3 = '4', borrow = false 
    *3 store result: res[0] = '4', n1i == n2i == resi == -1 
    !(0 <= resi (-1)) -> exit loop 
    // here res bytes are set to '4', '3', '5', '6', 0 
    // which can be formatted as result 43.56 (== 56.34 - 12.78) 

が...私はMIPSアセンブリでそれを書こうとするつもりはない、私はそれでコーディングやったことがないように、プラスI:私の例のアレイの場合

ループ内の値は次のようになりますあなたからのすべての楽しみを盗むことはできません。上の例では、ASCIIZ文字列の算術演算をどのように行うことができるのかをご理解いただければ幸いです。

基本的には紙に書いておき、ステップごとに1桁の数字しか操作できないときにはどうすればよいかに焦点を当ててください。それをアルゴリズムとして書き留めます。

は、いくつかの値(いくつかのコーナーケースは、私の「first_different_digit_is_bigger_in_n1」、または二つの等しい値、または123.45 - 7.890.00入力多分空の文字列のように、そこにあることを確認してください)上でそれを試してみてください。

もし見た目が固いようであれば、それらのステップの間に指示を書いてください(私はアルゴリズムを非常に多くの簡単な小さなステップに分けようとしました。そのほとんどは1-2命令、私がMIPSアーキテクチャをあまりにも逃してしまったときには、私はx86命令に慣れていたので、もっと多くのRISCのようなロジックに従うようにしました。

+0

これは、ドット ''。 ''文字( 'num1/num2'と同時に見つかるはずで、' res'にコピーされ、減算をスキップしてループを続けるだけです) 。入力から削除する方が簡単かもしれません。同じことが ''\ n' 'の場合は、おそらくそこに置くことができます。' \ n'がロードされたときに次のループの繰り返しにジャンプしてください。また、必要に応じて結果にコピーすることもできます。 – Ped7g

関連する問題