assembly 为什么在Linux的MIPS汇编代码中递减堆栈指针时会得到SEGFAULT?

bvpmtnay  于 2023-05-29  发布在  Linux
关注(0)|答案(1)|浏览(123)

我决定用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

pbwdgjma

pbwdgjma1#

将所有出现的addi $sp, $sp, -4更改为addiu $sp, $sp, -4,并将addi $sp, $sp, 4更改为addiu $sp, $sp, 4,解决了这个问题(稍后我将更改代码,以便每个函数偏移$sp一次,并使用相对于它的偏移量)。谢谢,@Erik Eidt,@Michael和@Peter Cordes。

相关问题