程序集在从未设置的 LED 灯箱上显示来自寄存器的值

Assembly display a value from register on LEDs light box that is never set

架构:ATmega8535

开发板:STK200

我的代码基本上显示了我的 LED 开关灯箱上寄存器 r0 的值。板载按钮连接到端口 A,开关灯箱 LED 连接到端口 C。

1000 0000
1100 0000

1110 000 1 - 不应该出现(末尾的那个应该是 0)

0111 0000
0011 1000
0001 1100
0000 1110
0000 0111
0000 0011
0000 0001
0000 0000



;Stack and Stack Pointer Addresses - Necessary for subroutines
        .equ     SPH    =E              ;High Byte Stack Pointer Address 
        .equ     SPL    =D              ;Low Byte Stack Pointer Address 
        .equ     RAMEND =F             ;Stack Address 

    ;Port Addresses 
        ;INPUT
        .equ     DDRA   =A               ;Port A Data Direction Register Address 
        .equ     PINA   =               ;Port A Input Address 

        ;OUTPUT
        .equ     PORTC  =              ;Port C Output Address 
        .equ     DDRC   =              ;Port C Data Direction Register Address 

    ;Register Definitions 
        .def     leds   =r0               ;Register to store data for LEDs 
        .def     temp   =r26              ;Temporary storage register 

    ;Set stack pointer to end of memory #Used for subroutines
        ldi    temp,high(RAMEND) 
        out    SPH,temp          ;Load high byte of end of memory address 
        ldi    temp,low(RAMEND) 
        out    SPL,temp          ;Load low byte of end of memory address 

    ;Setting registers for the game [Available registers: r22, r28]
        ;r4 the amount of times user can miss before game the restarts
        inc r4
        inc r4
        inc r4
    restartGame:    
        ;registers used for random subroutines
            clr r3 
            ;r2 - [=11=]  

        ;Main game registers
        ldi r24,[=11=] //if 1 - Destroyer 2 - Battleship 3 - Aircraft Carrier
        ldi r25,[=11=] //if 1 - Left 2 - Right
        ldi r22,[=11=] //If 1 - user already shot the torpedo 0 - user didn't shot a torpedo yet
        //r3 - how many times overall has user missed
        //r29, r30 - used as 1st and 2nd loop counter respectively
        ldi r27,;

    ;Initialise input ports
         ldi    temp,[=11=] 
         out    DDRA,temp         //Set Port A for input by sending [=11=] to direction register 
    ;Initialise output ports
         ldi    temp,$ff    
         out    DDRC,temp         //Set Port C for output by sending $FF to direction register 

    ;========================================GAME LOOP========================================;
                    gameLoop:   ldi r24,  ;3 LEDs ship
                            ldi r25,  ; moving right                             

                                rcall spawnShip //initialize ship on switch light box LEDs

                                cpi r25,
                                breq moveLeft 
                                cpi r25,
                                breq moveRight

                        moveLeft:   lsl leds
                                    out    PORTC,leds       //Display leds to port C 
                                    rcall delayCheck
                                    cp r0,r2            //If register is empty the ship escaped from the player hence exit the loop and spawn a new ship
                                    breq gameLoop
                                    rjmp moveLeft

                        moveRight:  lsr leds
                                    out    PORTC,leds       //Display leds to port C 
                                    rcall delayCheck
                                    cp r0,r2            //If register is empty the ship escaped from the player hence exit the loop and spawn a new ship
                                    breq gameLoop
                                    rjmp moveRight

    ;========================================GAME LOOP========================================;

    ;Subroutines

    //**Spawn Ship** - Initialising ship on switch light box LEDs (in phases every aircraft carrier is initially destroyer on frame 1 [1 LED] then it is a battleship on frame 2 [2 LEDs] on frame 3 it is a full aircraft carrier [3 LEDs])
    spawnShip:  cpi r25,
                breq spawnShipLeftD //Spawn ship on the right hand side with direction left
                cpi r25,
                breq spawnShipRightD //Spawn ship on the left hand side with direction right


        spawnShipRightD:    clr leds
                            rcall delayNoCheck
                            inc r0      //Initialise Destroyer
                            swap r0     //Speeds up changeDirLoop subroutine
                            rcall changeDirLoop
                            out PORTC, leds
                            rcall delayCheck

                            cpi r24,  //If the ship is a battleship increment the size by 1
                            breq spawnBattleShipRightD
                            cpi r24,  //If the ship is a aircraft carrier increment the size by 3 
                            breq spawnAircraftCarrierRightD
                            ret

            spawnBattleShipRightD:clr r0    //clr r0 hence was modified to 0x80 from 0x01 so incrementing that value would destroy our ship
                                 inc r0
                                 inc r0
                                 inc r0
                                 swap r0
                                 rcall changeDirLoop
                                 out PORTC, leds

                                 rcall delayCheck
                                 ret

            spawnAircraftCarrierRightD:rcall spawnBattleShipRightD //Every aircraft carrier is a battleship during 2nd frame of initialisation on LED switch light box
                                 clr r0
                                 inc r0
                                 inc r0
                                 inc r0
                                 inc r0
                                 inc r0
                                 inc r0
                                 inc r0


                                 swap r0
                                 rcall changeDirLoop
                                 out PORTC, leds

                                 rcall delayCheck
                                 ret

                changeDirLoop:  rol r0      //Initially every ship is spawned on the right side of the LED light box so we rotate left until, negative flag turns on
                                brpl changeDirLoop
                                ret

    //Spawn Ship

    //*Check Press* - check button was pressed, restrict user to pressing only one buttone at once by checking register with powers of 2
    checkPress:             cpi r22, //Check if user missed this turn
                            breq checkButtons //If user missed this turn we invert r19 to be always false so it will check again methods below which won't speed up the ship after missing

                            in     r19, PINA  //put the pin A value in r19

            checkButtons:   com    r19   //basic state of switches is 1111 1111 so invert to get 0000 0000

                            cpi r19,
                            breq   press  //If r19 is 0xb0000 0001
                            cpi r19,
                            breq   press  //If r19 is 0xb0000 0010 
                            cpi r19,
                            breq   press  //If r19 is 0xb0000 0100 
                            cpi r19,
                            breq   press  //If r19 is 0xb0000 1000
                            cpi r19,
                            breq   press  //If r19 is 0xb0001 0000
                            cpi r19,
                            breq   press  //If r19 is 0xb0010 0000 
                            cpi r19,
                            breq   press  //If r19 is 0xb0100 0000 
                            cpi r19,
                            breq   press  //If r19 is 0xb1000 0000
                missedReturn:ret


                            press:  and  r19, r0  //It will only be equal to more than 0 if the ship was shot
                                    cp   r19, r2  //Compare to empty register
                                    brne shotDown
                                    cp   r19, r2
                                    breq missed

                                shotDown:   clr leds //Destroy the ship
                                            out PORTC, leds 
                                            rcall delayNoCheck
                                            subi r27, //Speed up the game
                                            ;ADD SCORE
                                            rjmp gameLoop //Spawn a new ship

                                missed:     ldi r22,  //Has user missed this turn
                                            inc r3 //Increment overall times user missed
                                            cp r3,r4
                                            breq restart //If user missed 3 times start over

                                            rjmp missedReturn

                                        restart:    ldi temp, $FF
                                                    out PORTC, temp
                                                    rjmp restartGame

    //Check Press

    //*Delay*
    delayCheck:  mov    r31,r27     //Copy value of r27 into r31     
        loop3:   ldi    r30,  ;02        //Initialise 2nd loop counter ;$DA - default Alternate - 1F
        loop2:   ldi    r29, ;1f          //Initialise 1st loop counter ;$FE - default Alternate - D6
        loop1:   rcall checkPress
                 dec    r29              //Decrement the 1st loop counter 
                 brne   loop1            //and continue to decrement until 1st loop counter = 0 
                 dec    r30              //Decrement the 2nd loop counter 
                 brne   loop2            //If the 2nd loop counter is not equal to zero repeat the 1st loop, else continue 
                 dec    r31              //Decrement the 3rd loop counter
                 brne   loop3            //If the 3rd loop counter is not equal to zero repeat the 2nd loop, else continue
                 ret

    delayNoCheck:ldi    r31,     ;06 //Copy value of r27 into r31     
        loop4:   ldi    r30,  ;DA        //Initialise 2nd loop counter ;$DA - default Alternate - 1F
        loop5:   ldi    r29, ;FE         //Initialise 1st loop counter ;$FE - default Alternate - D6
        loop6:   dec    r29              //Decrement the 1st loop counter 
                 brne   loop6            //and continue to decrement until 1st loop counter = 0 
                 dec    r30              //Decrement the 2nd loop counter 
                 brne   loop5            //If the 2nd loop counter is not equal to zero repeat the 1st loop, else continue 
                 dec    r31              //Decrement the 3rd loop counter
                 brne   loop4            //If the 3rd loop counter is not equal to zero repeat the 2nd loop, else continue
                 ret

    //Delay

我已经研究这段代码几个小时了,但我不明白为什么它在 LED 上的某一点显示为 1110 0001 而不是 1110 0000

据我所知,这个错误发生在执行 delayCheck 时,它指向子例程 checkPress 但 r19 是空的,因为我没有按任何东西,所以我应该直接进入 return 并完成循环。

因为任何指令集参考都会告诉您 ROL 通过进位循环,所以它将 CF 带入最低有效位。碰巧 CF1 所以你会得到那个 led 组。您可以改用 LSL 来解决这个问题。

就是说,您有一种极其复杂的加载常量的方法。如果,而不是这个:

clr r0
inc r0
inc r0
inc r0
inc r0
inc r0
inc r0
inc r0
swap r0
rcall changeDirLoop

你只需使用一个 ldi leds, [=16=]xe0 然后它不仅会修复你的错误,而且还会使程序更具可读性和效率;)