汇编程序循环无法正常执行

时间:2018-03-02 20:34:08

标签: assembly delay avr

我创建了一个简单的汇编程序子程序(asmFunction),它应该每10 ms切换一次PORTD的输出。

这是汇编程序源代码:

#define __SFR_OFFSET 0
#include <avr/io.h>

.section .text      ; Defines a code section


;initialize
initialize:
    ldi r24,0xFF    ; set 11111111 value to the r24 register
    out DDRD,r24    ; put r24 register value into DDRD register
    ldi r24,0x00    ; set the r24 register to 00000000 value
    out PORTD,r24   ; put the r24 register value to PORTD
    ret             ; return from a branch

;wait 100uS
subdelay:
    ldi r23,99      ; set register r23 to 99
    loop:
        dec r23     ; 1 cycle, decrement r23
        cpi r23,0   ; 1 cycle, compare r23 and 0
        ;nop to get exactly 16 clock cycles per loop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        brne loop   ; 2 cycles, if r23 not eqal to 0, continue the loop
    ;wait a bit more (11 cycles to get exactly 100uS of delay
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    ret             ; return from branch

;delay x/10 ms (R22)
delay:
    ldi r23,100     ; set delay to 100x100uS
    loop1:
        dec r23     ; decrement r23
        cpi r23,0   ; compare r23 to 0
        call subdelay; call subdelay routine
        brne loop1  ; if r23 is not equal to 0, continue the loop
ret                 ; otherwise return from the delay branch

.global asmFunction ; makes asm function visible in other source files

asmFunction:        ; Start of asmfunc_calledfrom_c subroutine
    call initialize ; call initialize branch
    while:          ; main loop
        ;turn output high
        ldi r24,0xFF
        out PORTD,r24

        ;delay 10mS
        call delay

        ;turn output low
        ldi r24,0x00
        out PORTD,r24

        ;delay 10 ms
        call delay

        rjmp while  ; jump to while (for loop to continue existing)

main.c:

#include "avr/io.h"

void asmFunction();

int main()
{
    asmFunction();
    return 0;
}

这里是反汇编的hex文件:

Atmega328p_test.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800100  000000f4  00000168  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         000000f4  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .comment      00000011  00000000  00000000  00000168  2**0
                  CONTENTS, READONLY
  3 .note.gnu.avr.deviceinfo 00000040  00000000  00000000  0000017c  2**2
                  CONTENTS, READONLY

Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 34 00     jmp 0x68    ; 0x68 <__ctors_end>
   4:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
   8:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
   c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  10:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  14:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  18:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  1c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  20:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  24:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  28:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  2c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  30:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  34:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  38:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  3c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  40:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  44:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  48:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  4c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  50:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  54:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  58:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  5c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  60:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  64:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>

00000068 <__ctors_end>:
  68:   11 24           eor r1, r1
  6a:   1f be           out 0x3f, r1    ; 63
  6c:   cf ef           ldi r28, 0xFF   ; 255
  6e:   d8 e0           ldi r29, 0x08   ; 8
  70:   de bf           out 0x3e, r29   ; 62
  72:   cd bf           out 0x3d, r28   ; 61
  74:   0e 94 73 00     call    0xe6    ; 0xe6 <main>
  78:   0c 94 78 00     jmp 0xf0    ; 0xf0 <_exit>

0000007c <__bad_interrupt>:
  7c:   0c 94 00 00     jmp 0   ; 0x0 <__vectors>

00000080 <initialize>:
  80:   8f ef           ldi r24, 0xFF   ; 255
  82:   8a b9           out 0x0a, r24   ; 10
  84:   80 e0           ldi r24, 0x00   ; 0
  86:   8b b9           out 0x0b, r24   ; 11
  88:   08 95           ret

0000008a <subdelay>:
  8a:   73 e6           ldi r23, 0x63   ; 99

0000008c <loop>:
  8c:   7a 95           dec r23
  8e:   70 30           cpi r23, 0x00   ; 0
    ...
  a8:   89 f7           brne    .-30        ; 0x8c <loop>
    ...
  be:   00 00           nop
  c0:   08 95           ret

000000c2 <delay>:
  c2:   74 e6           ldi r23, 0x64   ; 100

000000c4 <loop1>:
  c4:   7a 95           dec r23
  c6:   70 30           cpi r23, 0x00   ; 0
  c8:   0e 94 45 00     call    0x8a    ; 0x8a <subdelay>
  cc:   d9 f7           brne    .-10        ; 0xc4 <loop1>
  ce:   08 95           ret

000000d0 <asmFunction>:
  d0:   0e 94 40 00     call    0x80    ; 0x80 <initialize>

000000d4 <while>:
  d4:   8f ef           ldi r24, 0xFF   ; 255
  d6:   8b b9           out 0x0b, r24   ; 11
  d8:   0e 94 61 00     call    0xc2    ; 0xc2 <delay>
  dc:   80 e0           ldi r24, 0x00   ; 0
  de:   8b b9           out 0x0b, r24   ; 11
  e0:   0e 94 61 00     call    0xc2    ; 0xc2 <delay>
  e4:   f7 cf           rjmp    .-18        ; 0xd4 <while>

000000e6 <main>:
  e6:   0e 94 68 00     call    0xd0    ; 0xd0 <asmFunction>
  ea:   80 e0           ldi r24, 0x00   ; 0
  ec:   90 e0           ldi r25, 0x00   ; 0
  ee:   08 95           ret

000000f0 <_exit>:
  f0:   f8 94           cli

000000f2 <__stop_program>:
  f2:   ff cf           rjmp    .-2         ; 0xf2 <__stop_program>

问题在于,当我在atmega328p微控制器上运行此代码时,它会产生周期为200μS的信号。 似乎subdelay子例程正常执行并产生100uS的延迟但由于某种原因loop1 delay子例程内的subdelay不起作用,导致turtle.bgpic("bkgrd.jpg") 子例程只执行

问题是:我做错了什么?

1 个答案:

答案 0 :(得分:0)

在延迟和子延迟中使用r23。您需要在调用子延迟之前保存它的值,然后使用push和pop将其恢复,或者将其存储在特定的内存位置。