assembly 0x004000b8处出现运行时异常:读取地址在字边界0x1001005a上未对齐

kcugc4gi  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(112)

我有一个任务,建立一个计算器在mips,我需要从用户那里得到符号,并使用这个操作数进行计算。我把操作数保存在数据中,我想让他们比较。我不知道我做错了什么,但这是行不通的。

.data

IfStart: .asciiz "Start Calculator? (0: no, 1: yes):"
msg: .asciiz "Enter operation symbol (+, -, *) or ‘!’ to quit:"
mulb: .asciiz "*"
addb: .asciiz "+"
subb: .asciiz "-"
stopsign: .asciiz "!"
newline: .asciiz "\n"
pick1: .asciiz "Enter first number (A):"
pick2: .asciiz "Enter second number (B):"
badnumber: .asciiz "Bad input\n"
bye: .asciiz "Good bye!"
one: .word 1
result: .asciiz "The result is:"
buffer: .space 20

.text

main:

li $v0,4 
la $a0,IfStart
syscall

li $v0,5 #get number from user
syscall 

move $t0,$v0

lw $t1, one

beq $t1,$t0,if1
beq $zero,$t0,if0

li $v0,4 
la $a0,badnumber
syscall

li $v0,4 
la $a0,bye
syscall

li $v0,10
syscall

if1: 
jal Calculator

if0:
li $v0,4 
la $a0,bye
syscall

li $v0,10
syscall


Calculator:

li $v0,4 #print first message
la $a0,msg
syscall

li $v0,8 #take in input
la $a0, buffer #load byte space into address
li $a1, 20 # allot the byte space for string
move $t2,$a0 #save string t2
syscall

li $v0,5 #Read int A
syscall 

move $t0,$v0 #t0 is A

li $v0,5 #Read int B
syscall 

move $t1,$v0 #t1 is B

lw $t3, mulb #mul sign
lw $t6, subb #sub sign
lw $t4, stopsign
lw $t5, addb #add sign



beq $t3,$a0,stop
beq $t4,$a0,multp
beq $t5,$a0,adds
beq $t6,$a0,subbs

multp:
jal Multiply
j print

adds:
jal Sum
j print

subbs:
jal Substract

print:
li $v0,4 #print the result is:
la $a0,result
syscall

#print result
li $v0, 1
move $a0, $t3
syscall

li $v0,4 #print new line
la $a0,newline
syscall

jal Calculator
stop:
li $v0,10
syscall

在执行下列其中一个数据列之后:

lw $t4, stopsign  
lw $t5, addb #add sign

李世民总是不停地写信给我这个错误:
Runtime exception at 0x004000b8: fetch address not aligned on word boundary 0x1001005a
但类似的行:

lw $t3, mulb #mul sign  
lw $t6, subb #sub sign

完全没有问题。是字符做的问题(!/+)吗?
谢谢你的帮助!

irtuqstp

irtuqstp1#

MIPS和其他RISC CPU有一个限制,这个限制就是对齐规则。(ARM和Motorola 68000在较小程度上是相似的。)如果使用lw加载32位值,则该值的地址需要是4的倍数。更简单地说,它需要以0、4、8或C结尾。另一方面,阅读字节时,可以在任何地址处进行,而不管对准如何。

la $t0,msg    ;load the address of "msg" into $t0
lb $t1,0($t0) ;load the "E" in "Enter operation symbol (+, -, *) or ‘!’ to quit:" into $t1

使用正确的load命令之所以如此重要,* 是因为CPU不知道数据的类型。* 当您使用.word.byte.asciiz指令输入数据时,您使用的是对您(程序员)最方便的格式。然而,当您的源代码转换为可执行程序时,数据的类型信息将丢失。假设您有以下内容,并且假设下面的标签“MyString”与4的倍数对齐(即,其地址以0、4、8或C结尾)。

.data
MyString: .asciiz "123"
.text

la $t0,MyString
lw $t1,0($t0)

这里实际发生的是0x31323300值被加载到$t1中(假设是big-endian体系结构,但这是一个完全不同的蠕虫)。这意味着字符串“123”和整数0x31323300(十进制,825,373,400),* 在CPU内存中具有相同的表示形式,并且完全可以互换。* 通过在字符串上使用lw,您得到的实体与预期的完全不同,即使数据本身根本没有改变!

相关问题