You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIPS计算器开发遇运行时异常:地址未按字边界对齐

MIPS计算器开发中的字对齐异常问题

问题描述

开发MIPS计算器时,需读取用户输入的运算符号存入数据段,后续取出用于比较。但执行lw $t4, stopsign和lw $t5, addb时,始终触发运行时异常:

Runtime exception at 0x004000b8: fetch address not aligned on word boundary 0x1001005a

而lw $t3, mulb和lw $t6, subb无异常,怀疑是字符(!/+)导致问题,相关代码如下:

.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

问题原因

MIPS架构的lw(加载字)指令要求访问的内存地址必须是字对齐的(即地址值能被4整除)。而.asciiz定义的字符串会自动在末尾添加null终止符(\0),每个字符串占用2字节(字符+null)。数据段中变量按顺序存储,前几个字符串的地址排列刚好让mulb和subb的地址是4的倍数,而stopsign和addb的地址不满足对齐要求,因此执行lw时触发异常——这和字符本身无关,完全是地址对齐问题。

解决方案

  1. 改用字节加载指令:我们只需要单个字符的ASCII值,用lb(加载字节)指令替代lw,lb不要求地址对齐,能正确读取单个字符:

    lb $t3, mulb #mul sign
    lb $t6, subb #sub sign
    lb $t4, stopsign
    lb $t5, addb #add sign
    
  2. 强制地址对齐:在数据段中每个字符串前添加.align 2指令,强制让变量地址按字对齐:

    .data
    IfStart: .asciiz "Start Calculator? (0: no, 1: yes):"
    msg: .asciiz "Enter operation symbol (+, -, *) or ‘!’ to quit:"
    .align 2
    mulb: .asciiz "*"
    .align 2
    addb: .asciiz "+"
    .align 2
    subb: .asciiz "-"
    .align 2
    stopsign: .asciiz "!"
    
  3. 修正比较逻辑:当前代码中beq $t3,$a0,stop的比较逻辑错误——$a0是buffer的内存地址,而$t3是字符的ASCII值,应该读取buffer中的第一个字符再和运算符号的ASCII值比较:

    # 在读取完运算符号输入后,添加以下代码
    lb $t7, ($t2)  # 从buffer中读取输入的第一个字符
    # 修正比较指令
    beq $t4,$t7,stop
    beq $t3,$t7,multp
    beq $t5,$t7,adds
    beq $t6,$t7,subbs
    

内容的提问来源于stack exchange,提问作者Shalev Levi Sagzan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:26:28