Linux下MIPS汇编递减栈指针触发SEGFAULT的原因排查
MIPS汇编Pacman游戏栈指针递减触发段错误问题
我在为Linux终端编写小端模式的MIPS汇编版Pacman游戏(纯兴趣尝试),但在initializeScreen函数中遇到了一个奇怪的段错误:执行栈指针递减指令时触发SEGFAULT。
错误发生在以下代码的最后一条指令:
#Print it add $a0, $s0, $zero add $a1, $zero, $zero add $a2, $zero, $zero add $a3, $zero, $zero addi $sp, $sp, -4
排查情况
- 最初猜测是程序.text段空间不足,但GDB输出显示指令地址完全正常:
(gdb) x/6iw $pc => 0x400e88 <initializeScreen+432>: addi sp,sp,-4 0x400e8c <initializeScreen+436>: sw s1,0(sp) 0x400e90 <initializeScreen+440>: lw t8,96(s7) 0x400e94 <initializeScreen+444>: nop 0x400e98 <initializeScreen+448>: jalr t8 0x400e9c <initializeScreen+452>: nop
- 第二个猜想是栈空间耗尽,但Linux默认栈空间为KB或MB级别,而我的汇编代码仅用栈存储寄存器值,这个可能性极低。另外,出错时$sp的取值为0x407fff7c。
完整的initializeScreen函数代码
initializeScreen: #Save return address addi $sp, $sp, -4 sw $ra, ($sp) #Save s registers addi $sp, $sp, -4 sw $s0, ($sp) addi $sp, $sp, -4 sw $s1, ($sp) #Initialize screen. #Step #1: Clear the screen. #Step #2: Display the high score, current level, and points. #Step #3: Draw the maze. #Step #4: Draw pacman. #Step #5: Draw the ghosts. #Step #6: Draw the power pellets. #Step #7: Display the number of lives remaining. #Step #1: Clear the screen. la $a0, buffer #jal storeClearToString lw $t8, 76($s7) jalr $t8 addi $a0, $a0, 4 #jal storeRTOToString lw $t8, 80($s7) jalr $t8 #Print addi $a0, $zero, 1 la $a1, buffer addi $a2, $zero, 8 addi $v0, $zero, 4004 syscall #Step #2: Display the high score, current level, and points. #Current level (1st byte) #Print the text addi $a0, $zero, 1 la $a1, levelText addi $a2, $zero, 15 addi $v0, $zero, 4004 syscall #Print the number lw $s0, 0($s6) add $a0, $s0, $zero addi $t1, $zero, 24 sll $a0, $a0, $t1 srl $a0, $a0, $t1 #jal printInt lw $t8, 24($s7) jal $t8 #Print '\n' addi $a0, $zero, 1 la $a1, newline2 addi $a2, $zero, 1 addi $v0, $zero, 4004 syscall #High score (2nd byte) #Note for the future: Might want to allocate more memory for the scores. #Print the text addi $a0, $zero, 1 la $a1, highScoreText addi $a2, $zero, 12 addi $v0, $zero, 4004 syscall #Print the number add $a0, $s0, $zero addi $t1, $zero, 16 sll $a0, $a0, $t1 addi $t1, $zero, 24 srl $a0, $a0, $t1 #jal printInt lw $t8, 24($s7) jal $t8 #Print '\n' addi $a0, $zero, 1 la $a1, newline2 addi $a2, $zero, 1 addi $v0, $zero, 4004 syscall #Number of points (4th byte) #Print the text addi $a0, $zero, 1 la $a1, pointsCollText addi $a2, $zero, 18 addi $v0, $zero, 4004 syscall #Print the number add $a0, $s0, $zero addi $t1, $zero, 24 srl $a0, $a0, $t1 #jal printInt lw $t8, 24($s7) jal $t8 #Print '\n' addi $a0, $zero, 1 la $a1, newline2 addi $a2, $zero, 1 addi $v0, $zero, 4004 syscall #Step #3: Print the maze. #Create the drawing array addi $a0, $zero, 10 addi $a1, $zero, 10 addi $a2, $zero, 4 #jal createNewTwoDArray lw $t8, 44($s7) jalr $t8 add $s0, $v0, $zero #Test: Print a rectangle. #Create the Rectangle addi $a0, $zero, 7 addi $a1, $zero, 7 #jal createNewRectangle lw $t8, 92($s7) jalr $t8 add $s1, $v0, $zero #Print it add $a0, $s0, $zero add $a1, $zero, $zero add $a2, $zero, $zero add $a3, $zero, $zero addi $sp, $sp, -4 sw $s1, ($sp) #jal drawRectangle lw $t8, 96($s7) jalr $t8 #Exit: lw $s1, ($sp) addi $sp, $sp, 4 lw $s0, ($sp) addi $sp, $sp, 4 lw $ra, ($sp) addi $sp, $sp, 4 jr $ra
内容的提问来源于stack exchange,提问作者Kseniya Kolokolkina
相关产品推荐
相关产品推荐

