在MARS4_5运行交叉编译的MIPS汇编代码报错的修复咨询
修复MARS 4.5中MIPS汇编代码的运行错误
看起来你是用GNU交叉编译器生成了MIPS汇编,但MARS对汇编语法的兼容性和GAS(GNU汇编器)有差异,所以出现了这些错误。下面逐个解决每个问题:
错误1和2:.align/.ascii不能出现在text段
GNU汇编用.rdata表示只读数据段,但MARS更常用.rodata作为只读数据段的标识(虽然部分版本也支持.rdata,但换成.rodata更稳妥)。另外,确保所有数据相关的伪指令(.align、.ascii)都在数据段内,不要混入text段。
错误3和4:1不是合法操作符、1f操作数类型错误
这是GAS的本地标签语法(数字+f表示向前跳转的标签),MARS不支持这种格式。你需要把这类本地标签替换成普通的、有意义的标签名,比如skip_div_check。
错误5:$31操作数类型错误
j指令在MIPS中是绝对跳转,只能接受地址作为操作数;而$31是返回地址寄存器ra,要跳转到寄存器存储的地址,应该用jr $ra(跳转寄存器指令),而不是j $31。
额外需要移除的GAS专属伪指令
GNU汇编生成的.frame、.mask、.fmask是用于调试和栈帧描述的伪指令,MARS不识别这些,需要直接删除。
修复后的完整汇编代码
.file 1 "test3.c" .rodata .align 2 $LC0: .ascii "Array of numbers: \n\000" .align 2 $LC1: .ascii "%d \000" .align 2 $LC2: .ascii "\n\n\000" .align 2 $LC3: .ascii "Array of prime numbers: \n\000" .align 2 $LC4: .ascii "Max prime numbers: \n\000" .align 2 $LC5: .ascii "%d\000" .text .align 2 .globl main .ent main main: addiu $sp,$sp,-72 sw $ra,64($sp) sw $fp,60($sp) sw $s0,56($sp) move $fp,$sp sw $sp,40($fp) li $2,1000 # 0x3e8 sw $2,20($fp) sw $0,24($fp) lw $2,20($fp) sll $2,$2,2 addiu $2,$2,7 addiu $2,$2,7 srl $2,$2,3 sll $2,$2,3 subu $sp,$sp,$2 addiu $2,$sp,16 addiu $2,$2,7 srl $2,$2,3 sll $2,$2,3 sw $2,44($fp) lw $2,24($fp) sll $2,$2,2 addiu $2,$2,7 addiu $2,$2,7 srl $2,$2,3 sll $2,$2,3 subu $sp,$sp,$2 addiu $2,$sp,16 addiu $2,$2,7 srl $2,$2,3 sll $2,$2,3 sw $2,48($fp) la $4,$LC0 jal printf sw $0,16($fp) $L2: lw $2,16($fp) lw $3,20($fp) slt $2,$2,$3 beq $2,$0,$L3 lw $2,16($fp) sll $2,$2,2 lw $3,44($fp) addu $s0,$2,$3 jal rand sw $2,0($s0) lw $2,16($fp) sll $2,$2,2 lw $4,44($fp) addu $2,$2,$4 la $4,$LC1 lw $5,0($2) jal printf lw $2,16($fp) addiu $2,$2,1 sw $2,16($fp) j $L2 $L3: la $4,$LC2 jal printf la $4,$LC3 jal printf sw $0,16($fp) $L5: lw $2,16($fp) lw $3,20($fp) slt $2,$2,$3 beq $2,$0,$L6 sw $0,32($fp) li $2,1 # 0x1 sw $2,28($fp) $L8: lw $2,16($fp) slt $2,$2,$3 bne $2,$0,$L9 lw $2,16($fp) sll $2,$2,2 lw $4,44($fp) addu $2,$2,$4 lw $3,0($2) lw $2,28($fp) div $0,$3,$2 bne $2,$0,skip_div_check break 7 skip_div_check: mfhi $2 bne $2,$0,$L10 lw $2,32($fp) addiu $2,$2,1 sw $2,32($fp) $L10: lw $2,28($fp) addiu $2,$2,1 sw $2,28($fp) j $L8 $L9: lw $3,32($fp) li $2,2 # 0x2 bne $3,$2,$L7 lw $2,24($fp) sll $2,$2,2 lw $4,48($fp) addu $3,$2,$4 lw $2,16($fp) sll $2,$2,2 lw $4,44($fp) addu $2,$2,$4 lw $2,0($2) sw $2,0($3) lw $2,24($fp) sll $2,$2,2 lw $3,48($fp) addu $2,$2,$3 la $4,$LC1 lw $5,0($2) jal printf lw $2,24($fp) addiu $2,$2,1 sw $2,24($fp) $L7: lw $2,16($fp) addiu $2,$2,1 sw $2,16($fp) j $L5 $L6: la $4,$LC2 jal printf lw $2,24($fp) blez $2,$L13 la $4,$LC4 jal printf lw $4,48($fp) lw $2,0($4) sw $2,32($fp) li $2,1 # 0x1 sw $2,16($fp) $L14: lw $2,16($fp) lw $3,24($fp) slt $2,$2,$3 beq $2,$0,$L15 lw $2,16($fp) sll $2,$2,2 lw $3,48($fp) addu $2,$2,$3 lw $3,0($2) lw $2,32($fp) slt $2,$3,$2 bne $2,$0,$L16 lw $2,16($fp) sll $2,$2,2 lw $4,48($fp) addu $2,$2,$4 lw $2,0($2) sw $2,32($fp) $L16: lw $2,16($fp) addiu $2,$2,1 sw $2,16($fp) j $L14 $L15: la $4,$LC5 lw $5,32($fp) jal printf lw $sp,40($fp) sw $0,36($fp) j $L1 $L13: lw $sp,40($fp) li $2,-1 # 0xffffffffffffffff sw $2,36($fp) $L1: lw $2,36($fp) move $sp,$fp lw $ra,64($sp) lw $fp,60($sp) lw $s0,56($sp) addiu $sp,$sp,72 jr $ra .end main
补充说明
- 我把
$16替换成了$s0(MARS里更常用的寄存器别名),这样可读性更好,功能完全一致。 - 替换了GAS的本地标签
1f为skip_div_check,解决了标签识别问题。 - 把末尾的
j $31改成了jr $ra,符合MIPS指令集规范。 - 删除了MARS不支持的
.frame、.mask、.fmask伪指令。
现在你可以把这段代码复制到MARS 4.5中运行,应该就能正常执行了。
内容的提问来源于stack exchange,提问作者Duy Nguyễn Lê Bảo




