我从文件中读取二进制机器代码并将其转换回汇编指令,并且遇到负立即值(I-Type指令的最后16位)的问题。我一次读取1位的行,并在使用此函数时将二进制数转换为十进制数:
readBits: #Function to read bits
add $t5, $a0, $zero #set t5 to parameter
li $t1, 2 #base value (2)
li $t7 , 0 #j = 0
li $s0, 0 # Set return value to 0
li $s7, '0' # load ascii value of '0'
readBitsLoop:
beq $t7, $t5, endReadBitsLoop #If we are past our length's iteration, we have rs
lb $t2, fileInputBuffer($t0) #Load in byte in file
addi $t0, $t0, 1 # iterator for file++
addi $t7, $t7, 1 # j++
mult $s0, $t1 #multiply return value and base
mflo $t3 #set result to t5
sub $t4, $t2, $s7 #subtract fileInputBuffer[i] and ascii value for '0'
add $s0, $t3,$t4 #Add those 2 together
j readBitsLoop #Jump to start of loop
endReadBitsLoop:
add $v0, $s0, $zero #move return value to return register
jr $ra #go back to where we were
此函数接收该部分的长度输入。例如,对于立即值,参数将为16。
这适用于正值,但不适用于负值,因为我需要在解析之前补充它。是否有捷径可寻?或者有一些方法可以在它已经是十进制之后进行转换吗?
感谢您对此提供任何帮助。如果您需要查看更多代码以了解我尝试做什么,请告诉我。
答案 0 :(得分:1)
我认为你真正想要的是sign-extend一个16位有符号2的补码整数到一个32位有符号2的补码整数,它填充一个寄存器,所以你可以将它与add / sub / multiply指令一起使用
如果您想将其打印为字符串(即执行v0=1
syscall
所做的事情,您只需要转换为十进制。)
无论如何,算术右移是制作符号位副本的一种方法。首先左移你的窄整数,使其符号位在寄存器的左边,然后使用算术移位。
# $s0 = all 4 bytes of a 32-bit I-type instruction
# where the immediate is the low 16 bits.
sll $t3, $s0, 16 # shift left logical
sra $t3, $t3, 16 # shift right arithmetic
# $t3 = a 32-bit integer from -65536 to +65535 = the immediate
# $t3 = sign_extend(low16($s0))
MIPS指令始终是对齐的,因此您可以安全地lw
整个指令或lh
下半部分,而无需将两个8位的一半与两个{{1}组合在一起}指令和转移/或。
顺便说一句,你一次只读一个字节,而不是一位。 lb
乘以1 addi
每次循环迭代一整个字节。
$t0
您似乎正在使用 lb $t2, fileInputBuffer($t0) #Load in byte in file
addi $t0, $t0, 1
常量mult
而不是左移。这是非常低效的。更好的是,您可以通过向自身添加数字来离开。 2
addu $t3, $s0, $s0
。