我决定用MIPS(little-endian)汇编语言为linux终端写一个吃豆人游戏(只是为了好玩)。然而,我最近遇到了一个以前从未遇到过的奇怪错误:我在递减堆栈指针时得到一个SEGFAULT。错误发生在标记为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
更具体地说,它发生在这里(最后一条指令):
#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上的最大堆栈大小是千字节或兆字节,与GNU C编译器生成的代码不同,我的汇编代码只使用堆栈来存储寄存器值。因此,我不太可能耗尽堆栈空间。
另外,$sp的值是0x407fff7c
。
1条答案
按热度按时间pbwdgjma1#
将所有出现的
addi $sp, $sp, -4
更改为addiu $sp, $sp, -4
,并将addi $sp, $sp, 4
更改为addiu $sp, $sp, 4
,解决了这个问题(稍后我将更改代码,以便每个函数偏移$sp
一次,并使用相对于它的偏移量)。谢谢,@Erik Eidt,@Michael和@Peter Cordes。