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

ARM汇编实现保加利亚纸牌游戏遇段错误及冻结问题求助

保加利亚纸牌游戏ARM汇编程序调试问题

问题说明

我正在编写实现保加利亚纸牌游戏的ARM汇编程序:将45张“纸牌”随机分成若干堆(每堆数量随机),之后每次从每堆取1张组成新堆,当所有纸牌形成1、2、3、4、5、6、7、8、9的堆(顺序不限)时游戏结束。

程序打印初始设置后触发Segmentation Fault(段错误),GDB调试输出如下:

Program received signal SIGSEGV, Segmentation fault.
0xf7f831b8 in randtbl () from /lib/arm-linux-gnueabihf/libc.so.6

另外,当初始数组元素超过8个时,程序直接冻结。我已调试18小时仍无进展。

实现思路:先生成随机数组(已完成);每一步遍历数组,每个元素减1,随后执行打印数组、移除零元素、排序操作,检查是否符合1-9的堆形式,不符合则重复步骤。

代码实现

play.s

.cpu cortex-a72
.fpu neon-fp-armv8
.section .data
    finished: .asciz "We finished! Hooray!"
    labelPointerFour: .word 0
.section .text
    .extern printf
    .extern scanf
    .global startPlay
    .type startPlay, %function
startPlay:
    @ Parameters:
    @ r0 = the address of the first location of the array
    @ r1 = the byte offset of the first unfilled byte of the array
    @ Uses:
    @ r0, r4, r5, r6, r7, r8
    push {r4-r10, fp, lr}
    mov fp, sp
@ initialization skipped: r4 is the address of the first element of the array, r5 is the offset, in bytes, assuming a number is 4 bytes of the last element, r6 is a copy of r4, and r9 is the last memory location in the array.
    playLoop:
        
        
        add r9, r4, r5 
        
        mov r8, #0 @ gives r8 a value of zero - it later gets used to be the new pile
        @ r6 is a modifiable copy of r4 and r8 is the counter representing the new pile
        mov r2, #0 
        @ r2 is the counter
        mov r6, r4
        b innerPlayLoop
        innerPlayLoop:
            
            cmp r2, r5 @ if(counter >= offset){postPlay()}
            bge postPlay
            
            ldr r7, [r6]
            sub r7, r7, #1
            add r8, r8, #1
            str r7, [r6]
            
            @ increment counters
            add r6, r6, #4
            add r2, r2, #4
            b innerPlayLoop
        postPlay: 
            str r8, [r9]
            
            
            mov r8, #1
            @ r8 is what we are looking for in nexter
            mov r6, r4
            @ establishing a solid copy of r4
            mov r7, #0
            @ the found flag
            push {r9}
            sub r9, r9, r4
            cmp r9, r5 
            beq addermost
            nextGuy:
            pop {r9}
            
            push {r4, r5, r6}
            mov r0, r4
            mov r1, r5
            bl printArray
            pop {r4, r5, r6}
            push {r4, r5, r6}
            mov r0, r4
            mov r1, r5, lsr #2
            bl removeZero
            pop {r4, r5, r6}
            push {r4, r5, r6}
            mov r0, r4
            mov r1, r5, lsr #2
            bl sort
            pop {r4, r5, r6}
            
            b nexter
        @ important info going into nexter:
        @ r5 is the max offset
        @ r6 is a modifiable copy of r4
        @ r7 is the found flag - make it 1 when you find something of a category
        @ r8 is the current number we're looking for
        @ r9 is the location of zero
        @ r2 is the current number's value
        @ r3 is the current offset
        @ if your search comes up empty, move to playLoop
        nexter:
            mov r7, #0
            
            looperb: @ haha get it? like superb ok i'll stop
                add r8, r8, #1
                mov r3, #0 @ everytime looperb runs, r3 goes to 0
                mov r6, r4
                looperc:
                    ldr r2, [r6]
                    add r6, r6, #4
                    add r3, r3, #4
                    cmp r2, r8
                    beq looperb
                    cmp r8, #10
                    bne looperb
                    cmp r8, #10
                    beq finishedPrinter
                    b looperc
                    
    addermost:
        add r5, r5, #4
        add r9, r9, #4
        b nextGuy
    finishedPrinter:
        ldr r0, =finished
        bl printf
        
            @ begin ending sequence
    mudithu:
    mov fp, sp
    b finisher
    pop {r4-r10, fp, pc}

printArray.s

.cpu cortex-a72
.fpu neon-fp-armv8
.section .data
    format: .asciz "%d "
    endFormat: .asciz "\n"
.section .text
    .extern printf
    .extern scanf
    .global printArray
    .type printArray, %function

printArray:
    @ Parameters:
    @ r0 = first memory address of array
    @ r1 = offset of first unfilled element of array
    @ Registers Used:
    @ r0, r1, r4, r5, r6
    push {fp, lr}
    mov fp, sp

    mov r4, r0   @ r4 = current memory address of the element
    mov r5, #0   @ r5 = current offset
    mov r6, r1   @ r6 = max offset

loopThrough:
    cmp r5, r6  @ if current offset >= max offset, end
    bge endPrint
    ldr r0, =format
    ldr r1, [r4]  @ load element value
    bl printf
    add r4, r4, #4  @ move to next element
    add r5, r5, #4  @ increment current offset
    b loopThrough

endPrint:
    ldr r0, =endFormat
    bl printf
    mov sp, fp
    pop {fp, pc}

genRanNum.s

.cpu cortex-a72
.fpu neon-fp-armv8
.section .data
    low: .word 50
    high: .word 100

.section .text
    .extern time
    .extern printf
    .extern srand
    .extern rand
    .global genRanNum
    .type genRanNum, %function

genRanNum:
    @ Input
    @ r0, the low bound
    @ r1, the high bound
    
    @ Registers used (maybe store them)
    @ r0, r1, r2, r3, r5
    
    @ Returns
    @ r0: A random number between the entered r0 and r1, inclusive
    push {r4-r10, fp, lr}
    mov fp, sp
    mov r2, #0
    mov r3, #0
    mov r5, #0
    ldr r3, =low
    str r0, [r3]
    ldr r3, =high
    str r1, [r3]

    mov r0, #0
    bl time
    push {r0}
    bl srand
    pop {r0}
    bl rand
    @ r0 contains a big random number
    
    ldr r1, =low
    ldr r2, =high
    ldr r1, [r1]
    ldr r2, [r2]
    @ now start modulus division
    sub r5, r2, r1
    add r5, r5, #1
    modLoop:
        cmp r0, r5
        blt addX
        sub r0, r0, r5
        b modLoop
    addX:
        
        add r2, r0, r1
    @ r2 now contains a random number between low and high
        mov r0, r2
        mov sp, fp
        pop {r4-r10, fp, pc}

补充信息

已知错误出在play.s中,但GDB仅提示randtbl触发段错误。编译命令为:

gcc -o l4 *file names here* -g

内容的提问来源于stack exchange,提问作者anonsaicoder9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:22:04