2015-07-13 187 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

謝謝你這麼好的回答! –