使用 avr-gcc 编译汇编程序

Compiling an Assembly Program using avr-gcc

我正在尝试在 Attiny85 上使用 avr-gcc 将一个简单的汇编程序编译为 运行。不幸的是,该程序根本不起作用。而且我在上传和编译时没有出错。我知道程序本身应该可以工作,因为它使用 C 工作。那么我错过了什么?

编译上传:

avr-gcc blinky.S -mmcu=attiny85 -Os -g -o blinky.out
avr-objcopy -O ihex blinky.out blinky.hex
sudo avrdude -p attiny85 -c usbasp -P usb -e -U flash:w:blinky.hex

blinky.S

#define F_CPU 1000000L
#include <avr/io.h>

        .section text
        .org 0
        .global init

        rjmp init

init:
        ldi r23,0x00
        ldi r24,0xFF
        out _SFR_IO_ADDR(DDRB), r24
        out _SFR_IO_ADDR(PORTB), r23

        rjmp main

        .org 0x020
        .global main
main:
        out _SFR_IO_ADDR(PORTB), r24
        rjmp main

输出:

Philipps-MacBook-Pro:Desktop philippbraun$ sh script.sh attiny85 blinky.S

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b
avrdude: erasing chip

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

COMPILING AS ASSEMBLY FILE

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b
avrdude: erasing chip
avrdude: reading input file "blinky.hex"
avrdude: input file blinky.hex auto detected as Intel Hex
avrdude: writing flash (46 bytes):

Writing | ################################################## | 100% 0.03s



avrdude: 46 bytes of flash written
avrdude: verifying flash memory against blinky.hex:
avrdude: load data flash data from input file blinky.hex:
avrdude: input file blinky.hex auto detected as Intel Hex
avrdude: input file blinky.hex contains 46 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.03s



avrdude: verifying ...
avrdude: 46 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

以下C程序编译成功!

#define F_CPU 1000000L
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRB = 0xFF; // PORTB is output, all pins
PORTB = 0x00; // Make pins low to start

for (;;) {
PORTB = 0xFF; // invert all the pins
//_delay_ms(5000); // wait some time
}
return 0;
}

首先我想知道您可以使用命令行进行汇编!对我来说根本行不通!

那么你想要达到什么目的?使用 stdlib 支持进行编译( irq jump table,在开始时跳转到 main?还是你想全部手动完成?

全部手工完成:

avr-gcc -xassembler-with-cpp x.s -mmcu=attiny85 -nostdlib

使用stdlib获取跳转table:

avr-gcc -xassembler-with-cpp x.s -mmcu=attiny85

如果你在没有跳转的情况下使用它table你应该使用 avr-as 而不是 avr-gcc!

所以我用手工制作的版本尝试了你的代码,但我的程序集完全是空的!为什么?

你打错了:

.section text

错了!

使用:

.section .text

我的转储看起来像这样:

00000000 <init>:
   0:   8f ef           ldi r24, 0xFF   ; 255
   2:   87 bb           out 0x17, r24   ; 23
   4:   0d c0           rjmp    .+26        ; 0x20 <main>
...

00000020 <main>:
  20:   88 bb           out 0x18, r24   ; 24
  22:   fe cf           rjmp    .-4         ; 0x20 <main>

这里没有闪烁!

下一篇:为什么在这里使用.org?如果您向 init 添加的代码大小大于 0x020,它将被 main 覆盖!所以只需删除那些脏线!

#include <avr/io.h>

    ldi r23,0x00
    ldi r24,0xFF
    out _SFR_IO_ADDR(DDRB), r24

main:
    out _SFR_IO_ADDR(PORTB), r24
    out _SFR_IO_ADDR(PORTB), r23
    rjmp main

结果:

00000000 <__ctors_end>:
   0:   70 e0           ldi r23, 0x00   ; 0
   2:   8f ef           ldi r24, 0xFF   ; 255
   4:   87 bb           out 0x17, r24   ; 23

00000006 <main>:
   6:   88 bb           out 0x18, r24   ; 24
   8:   78 bb           out 0x18, r23   ; 24
   a:   fd cf           rjmp    .-6         ; 0x6 <main>

为什么你用了.global?没有人在您定义的符号 initmain.

上进行外部引用

因此,如果您使用带有 stdlib 的版本,则只需导出 main 使其在启动代码中可见。但是如果你想那样做,没有办法在 main 之前使用 init。据我所知,avr-libc 根本不知道额外的用户初始化方法。