2015-07-13 190 views
1

我想编译一个简单的汇编程序,用avr-gcc在Attiny85上运行。不幸的是,该程序根本无法工作。我在上传和编译时没有遇到任何错误。我知道程序本身应该工作,因为它使用C工作。那么我错过了什么?使用avr-gcc编译汇编程序

编译和上传:

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; 
} 
+0

您是否将此与C程序生成的程序集进行了比较?例如'DDRB = 0xff;','while(1)PORTB = 0xff;' –

+0

@BrettHale是的,我现在还包括成功编译的C程序。 –

+0

这两个程序是不相同的。 C版本将'PORTB'初始化为零,而汇编版本则不会。 – Michael

回答

2

首先,我想知道您可以使用您的命令行组装!对我而言,它根本行不通!

那么你想实现什么?与STDLIB支持(IRQ跳表编译,跳到主在启动或你想手工做这一切

做这一切的手:??

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

使用STDLIB获得跳表:

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

如果你不需要使用跳转表,你应该使用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> 

没有闪烁在这里!

Next:为什么在这里使用.org?如果你在代码大小上增加了一些大于0x020的init值,它将被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以使其通过启动代码可见即可。但如果你想这样做,主要之前没有办法使用init。据我所知,avr-libc根本不了解额外的用户init方法。

+0

谢谢你这么好的回答! –