Arrays 汇编Mips-转换两个字符串(包含Float)并找到它们之间的间隙

Arrays 汇编Mips-转换两个字符串(包含Float)并找到它们之间的间隙,arrays,assembly,floating-point,int,mips,Arrays,Assembly,Floating Point,Int,Mips,我必须创建一个函数,返回两个浮点数之间的差值 示例:用户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 "Paol

我必须创建一个函数,返回两个浮点数之间的差值

示例:用户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)
编辑:我只是想办法做到这一点

这个功能很好用,顺便说一句,我知道它根本不起作用。。有这么多多余的工作,但我没有那么多时间,所以。。非常感谢你的提示和帮助

不同地理位置:

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

这太没用了我知道。。。如果我存储lat和long值,比如float,而不是ascii,可能会避免很多麻烦。

我不确定你的意思:

找不到在算术运算中使用数组的方法

就像在汇编中一样,甚至没有一个定义良好的东西,比如“数组”,但您可能指的是一些连续的字节

sub
这样的算术指令只能在寄存器上工作(并且只能在字大小上工作)

因此,如果字符串中有两个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=3的最后一位的索引,并设置
resi=max(n1i,n2i)

现在,当您想要sub的绝对值时,您可以检查哪个数字较小,然后从较大的数字中减去那个数字

num1bigger = (n2i < n1i) || (n1i == n2i && first_different_digit_is_bigger_in_n1);
// equal numbers will produce "false"
这是每字节ASCII绝对值减法算法。(输入[22,20]和[22,24]都将产生+02结果!)

顺便说一句,对于非绝对减法,它实际上几乎是一样的,但是当
时!num1biger
,负号必须在result=>
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)
init:
num1biger=false,借用=false,res[4]=0
循环第一次迭代:
*1取数、交换、借用调整:r1='4',r2='8'
*2减法,调整:r3='6',借用=真
*3存储结果:res[3]=“6”,n1i==n2i==resi==2
(0)再次循环
*1取数、交换、借用调整:r1='3',r2='8'
*2减法,调整:r3='5',借用=真
*3存储结果:res[2]=“5”,n1i==n2i==resi==1
(0)再次循环
*1取数、交换、借用调整:r1='6',r2='3'
*2减法,调整:r3='3',借用=假
*3存储结果:res[1]=“3”,n1i==n2i==resi==0
(0)再次循环
*1取数、交换、借用调整:r1='5',r2='1'
*2减法,调整:r3='4',借用=假
*3存储结果:res[0]=“4”,n1i==n2i==resi==1
!(0退出循环)
//此处res字节设置为“4”、“3”、“5”、“6”和“0”
//可将其格式化为结果43.56(=56.34-12.78)
…我不打算尝试在MIPS汇编中编写它,因为我从来没有在其中编写过代码,而且我也不能从您那里窃取所有的乐趣。我希望上面的内容能让您了解如何对ASCIIZ数字字符串进行算术运算

基本上,你们应该把它写在纸上,当你们每一步只能操作一位数的时候,你们会做什么,然后把它作为一个算法写下来

在几个值上尝试它(确保有一些特殊情况,比如我的“第一个不同的数字比第一个大”,或者两个相等的值,或者
123.45-7.89
0.00
输入,甚至可能是空字符串)


如果它看起来很可靠,只需在这些步骤之间编写指令(我试图将我的算法分解为许多简单的小步骤,其中大多数步骤最多只能由1-2条指令来解决,有时可能是3-4条指令,因为我太错过了MIPS体系结构。我习惯了x86指令,所以我尝试遵循更多类似RISC的逻辑(例如,避免使用标志),但仍然…).

祝你好运,找到一个真正愿意花时间为你写这篇文章的人。你要求的是汇编语言!我已经记不太清楚这门语言了,否则我会尝试。你必须将lat和long值存储为ascii吗?如果你能将它们存储为浮点,这会容易得多。@Tim如果他没有字符串来浮点转换如果他知道小数点后总是只有2位,那么他可以使用100*整数来表示所有内容,只需在最后两位之前加上“
”。
”。(我有点不知道,我从写ASCII—浮点转换器开始,可能是用C++来做的,那是一个背信弃义的代码).@Tim对于固定格式来说,它是..可能很简单..但在/10和/100之前,您已经引入了舍入,我不确定累积最小可能错误的正确策略。但是完整的浮点字符串解析,包括科学记数法和正确处理溢出/下溢…我不会写是的,但我认为它很容易消耗掉几天的时间来消除bug,而且感觉非常乏味。另外,我没有理由写它,我很乐意使用clib版本。:@Ped7g和Tim:Fast and precision
strod()
是一个很难解决的问题,有很多特殊情况。详细描述了glibc使用的算法。它还有一个链接,指向另一个广泛使用的实现的类似描述(由David Gay编写):。有趣的阅读。这应该很容易扩展以处理点
字符(它应该同时在
num1/num2
中遇到,只需复制到
res
,跳过减法并继续循环)。可能比从输入中删除它更容易。
'\n'
也是如此,您可能可以将它们保留在那里,只要在加载
\n
时跳转到下一个循环迭代即可。如果需要,甚至可以将其复制到结果中。
    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) 
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)