ARM程序集:循环只会迭代一次,然后是较差的错误

时间:2017-12-08 06:59:08

标签: c++ assembly arm

我正在为我的装配课程的最终项目进行二十一点游戏。我有一系列单词代表一副牌中的52张牌。我的游戏不会像二十一点那样,但我需要展示游戏的基本概念。

我试图循环我的交易功能两次,但不管我放入r4(循环计数器)的值是什么,它只打印交易功能的输出一次。我在GDB中看过这个,在第一次交易后我得到一个错误:

[Inferior 1(流程1585)退出代码04]

mov r4, #0
cmp r4, #4
beq display_2
add r4, r4, #1
bal deal

整个源代码:

.equ INPUT, 0
.equ OUTPUT, 1
.equ LOW, 0
.equ HIGH, 1

.equ PIN0, 0    // wipi pin 0 - bcm 17
.equ PIN1, 1    // wipi pin 1 - bcm 18
.equ PIN2, 2    // wipi pin 2 - bcm 27
.equ PIN3, 3    // wipi pin 3 - bcm 22
.equ PIN4, 4    // wipi pin 4 - bcm 23
.equ PIN5, 5    // wipi pin 5 - bcm 24
.equ PIN6, 6    // wipi pin 6 - bcm 25
.equ PIN7, 7    // wipi pin 7 - bcm 4

.global main
.data
format: .asciz "r1=%d\n"
.balign 4
// Create a deck of 52 cards
deck:
.word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10
.word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10
.word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10
.word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10

.text
// ripped from C++ compiler's assembly output
.align 2
.L3: .word 1321528399

main:
push {lr}
bl wiringPiSetup

mov r0, #PIN0
mov r1, #OUTPUT
bl pinMode

mov r0, #PIN1
mov r1, #OUTPUT
bl pinMode

mov r0, #PIN2
mov r1, #OUTPUT
bl pinMode

mov r0, #PIN3
mov r1, #OUTPUT
bl pinMode

mov r0, #PIN4
mov r1, #OUTPUT
bl pinMode

deal:
// the following code was disassembled from the C++ compiler's
// rand function
mov     r0, #0
bl      time
mov     r3, r0
mov     r0, r3
bl      srand
bl      rand

mov     r2, r0
ldr     r3, .L3
smull   r1, r3, r3, r2
mov     r1, r3, asr #4
mov     r3, r2, asr #31
rsb     r3, r3, r1
mov     r1, #52
mul     r3, r1, r3
rsb     r3, r3, r2
// end of C++ compiler's code
ldr r0, =format
// mov the random number generated (r3) into r1 for printing
mov r1, r3
// take the same value and store it also into r7 to preserve it
mov r7, r1
bl printf
ldr r0, =format
ldr r1, =deck
// setup r9 as the increment value leading to the next index
// of the array
mov r9, #4
// multiply into r8 the random number times the increment value
// of the array (4 bytes)
mul r8, r7, r9
// r8 now holds the randomized card just dealt to the player
// add this to the players score and get the actual value
// at from the address
add r1, r1, r8
ldr r1, [r1]
// mov into r7 the players score to preserve it
mov r7, r1
bl printf

display_2:
mov r4, #0
l:
cmp r4, #2
bne deal
add r4, r4, #1

bal l
// write the players score to the led display
mov r0, r7
bl digitalWriteByte

示例输出:

pi@raspberrypi:~ $ ./6leds.out 
r1=50 // the random index chosen
r1=10 // the value stored at that array index
pi@raspberrypi:~ $ ./6leds.out 
r1=6
r1=7
pi@raspberrypi:~ $ ./6leds.out 
r1=6
r1=7

^我希望它能做两次而不是一次

1 个答案:

答案 0 :(得分:0)

循环可能的结构如下:

    // Initialize loop counter. Note this is outside the loop body.
    mov #r4, 0
loop_entry:
    // Test if the loop is done. This is a "while (...) { }" or for style loop
    cmp #r4, <loop_limt>
    bge loop_exit
    // code that you want to execute multiple times.
    // In the above this would be everything between deal: and display_2:
    <...>
    add r4, r4, #1
    bal loop_entry

loop_exit:
    // Do stuff after the loop.

在您发布的代码中,初始化为零有效地发生在循环内部。我希望这会产生一个无限循环,而不是一个在一次执行后终止的循环。 (例如,我不知道bal l是如何执行的。你可以通过调试器来验证这一点。)

我能想到的唯一一个简单的事情就是标签和功能之间的区别。在您发布的代码中,标识函数的唯一标签是main:。在其他地方,代码只是在一条直线上继续执行标签。 (当然,main:标签也没有什么特别之处,它的使用方式也是如此。)因此,在printf之后的deal:之后,move r4, #0位于display_2:之下1}}被执行。