Forum: Mikrocontroller und Digitale Elektronik AVR Assemblersprache zu Opcode nicht nachvollziehbar


von Janik (Gast)


Lesenswert?

Hallo zusammen,

ich versuche zu verstehen, wie ein Programm in Assemblersprache und das 
Hexfile, welches in den Mikrocontroller übertragen wird, zusammenhängen.

Im Dokument „AVR Instruction Set Manual“, welches Atmel bzw. Microchip 
zum Download bereitstellt, ist der AVR Befehlssatz vollständig 
beschrieben, auch mit den zu jedem Befehl gehörigen Opcode. Ich erwarte 
natürlich, dass die Assemblerbefehle nach der Kompilierung als Opcode im 
Code des .Hex Files auftauchen. Und da finde ich ihn nicht...

Ich nutze AtmelStudio und einen Atmega32A, an welchen 8 LEDs an Port D 
angeschlossen sind. Der Code funktioniert und das Bitmuster 0xCC 
(0b11001100) wird über die LEDs angezeigt.

Hier der Assemblercode:
1
.INCLUDE "m32Adef.inc"
2
  .CSEG
3
  rjmp  start
4
  .ORG  0x13
5
  
6
start:
7
    ldi    r16, 0xFF      
8
  out  DDRD, r16
9
  
10
mainloop:  
11
  
12
  ldi  r16, 0xCC    
13
  out  PORTD, r16
14
  rjmp  mainloop
15
  
16
.EXIT

Und hier mein Hexfile, nachdem ich es in *.txt umbenannt und im 
Texteditor geöffnet habe:

:020000020000FC
:0200000012C02C
:0A0026000FEF01BB0CEC02BBFDCF95
:00000001FF

Die AVR Instruction Set Manual liefert für den Befehl "ldi" folgenden 
Opcode:
16-Bit Opcode: "1110 KKKK dddd KKKK"
Ich erwarte also die Code-Sequenz "EC0C". E für 1110. C für das erste 
Nibble der Konstante CC, 0 für das Register r16, und C für das zweite 
Nibble der Konstanten CC.

Wenn ich den Befehl
1
ldi r16, 0xCC
 ändere in
1
ldi r16, 0xFF
 so ändert sich nach erneuter Kompilierung mein Opcode zu:

:020000020000FC
:0200000012C02C
:0A0026000FEF01BB0FEF02BBFDCF8F
:00000001FF

Die letzten beiden Hexadezimalzahlen in Zeile drei ändern sich von 95 zu 
8F. Kann mir das jemand erklären?

Mit Dank und Gruß,
Janik

von m.n. (Gast)


Lesenswert?

Das ist die Prüfsumme ;-)

von Janik (Gast)


Lesenswert?

Tatsächlich :) Habe sogar zwei Cs gefunden, die zu Fs werden ^^

von Christian M. (Gast)


Lesenswert?

Da hat such noch mehr geändert! Am Ende ist die Prüfsumme.

https://de.m.wikipedia.org/wiki/Intel_HEX

Gruss Chregu

von Michael U. (amiga)


Lesenswert?

Hallo,

Janik schrieb:
>   ldi  r16, 0xCC

> :0A0026000FEF01BB-0CEC-02BBFDCF95

>
1
ldi r16, 0xCC
 ändere in
1
ldi r16, 0xFF
> :0A0026000FEF01BB-0FEF-02BBFDCF8F

Du solltest Dich noch mit dem Intel-Hex-Format und dem Thema Byteorder 
befassen.
Ich habe mal mit - die Befehle eingerahmt.
Das letzte Byte ist die Prüfsumme der Zeile.

Gruß aus Berlin
Michael

von Janik (Gast)


Lesenswert?

Trotzdem hätte ich die Codesequenz EC0C erwartet. Wieso taucht die nicht 
auf? ich würde gerne die Opcodes neben die entsprechenden 
Assemblerbefehle schreiben, um die zuzuordnen. Das gelingt mir aber 
nicht. Kann mir jemand helfen. Wenn ich einen schlüssigen opcode finde, 
kann ich den Rest sicher selbst rausarbeiten.

von Janik (Gast)


Lesenswert?

Ok, danke, ich les mich mal rein ^^ Und melde mich wieder ;)

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Janik schrieb:
> Trotzdem hätte ich die Codesequenz EC0C erwartet. Wieso taucht die nicht
> auf?

Janik schrieb:
> :0A0026000FEF01BB0CEC02BBFDCF95
                   ^^^^
Ist doch alles da: BB 0CEC 02

von Janik (Gast)


Lesenswert?

Kaj G. schrieb:
> Ist doch alles da: BB 0CEC 02

Wieso wird denn aus EC0C -> 0CEC?

von 1234567890 (Gast)


Lesenswert?

Janik schrieb:
> Wieso wird denn aus EC0C -> 0CEC?

Siehe da:

Michael U. schrieb:
> Du solltest Dich noch mit dem Intel-Hex-Format und dem Thema Byteorder
> befassen.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Janik schrieb:
> Wieso wird denn aus EC0C -> 0CEC?
Weil die Umwandlung von Format A (Asm) nach Format B (Intel-Hex) nicht 
1:1 stattfinden muss.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Ausserdem solltest du bedenken, das du aus dem Opcode nicht 
zwangslaeufig auf den verwendeten ASM-Befehl schliessen kannst. Da 
fallen einige raus.

Siehe hier:
Beitrag "AVR: Werden gleiche Opcodes unterschieden?"

von Karl B. (gustav)


Lesenswert?

Hi,
habe noch eine Frage zum Programm.
Also Pin Change A Interrupt Einsprungadresse wird da genommen:
.ORG  0x13 oder?
Aber es folgt darauf kein Sprungbefehl auf eine Interrupt Service 
Routine.
Wo gibt es dazu Infos, damit ich noch etwas dazulerne.
Also, wenn es erlaubt ist, "meine" Version:

.nolist
.INCLUDE "m32Adef.inc"
.list
;
.CSEG
.org 0x0000
rjmp  start
.ORG 0x0013
rjmp ISR
;
start:
ser r16
out  DDRD, r16
;
mainloop:
ldi  r16, 0xCC
out  PORTD, r16
rjmp  mainloop
;
ISR:
nop
reti
;ciao gustav

von Purzel H. (hacky)


Lesenswert?

Wenn man das Listfile zuschaltet erhaelt man ASM Code neben der Hex 
Codierung in der anderen Kolonne. Das Intel Hex file muss man nicht 
anschauen. Allenfalls kann man sich ueberlegen, erst aus Intel Hex 
Binaer zu machen.

von Kaj G. (Firma: RUB) (bloody)


Angehängte Dateien:

Lesenswert?

Karl B. schrieb:
> .nolist
> .INCLUDE "m32Adef.inc"
> .list
> ;
> ...

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
und noch das zugehörige Hexfile:

:020000020000FC
:0200000013C02B
:1000260005C00FEF01BB0CEC02BBFDCF000018951D
:00000001FF

Und zurück mit Disassemble-Feature (Bild)

ciao
gustav

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Karl B. schrieb:
> habe noch eine Frage zum Programm.
> Also Pin Change A Interrupt Einsprungadresse wird da genommen:
> .ORG  0x13 oder?

Oder.

> Wo gibt es dazu Infos, damit ich noch etwas dazulerne.

Im Datenblatt gibt es eine Tabelle, die die Interrupt-Vektoren und die 
dazugehörigen Adressen im Flash nennt. Aber da die Vektoren allen an 
geraden Adressen liegen, kann 0x0013 nicht richtig sein.

> Also, wenn es erlaubt ist, "meine" Version:
>
> .nolist
> .INCLUDE "m32Adef.inc"
> .list
> ;
> .CSEG
> .org 0x0000
> rjmp  start
> .ORG 0x0013
> rjmp ISR
> ;
> start:
...

Gräßlich.

Dein Startcode landet so mitten in der Vektortabelle. Und etliche 
Vektoren sind schlicht leer, weiß der Teufel was dann passiert, wenn so 
ein Interrupt mal ausgelöst wird.

Korrekt macht man das so, daß man immer die komplette Vektortabelle 
ausfüllt. Und erst dahinter kommt der eigentliche Programmcode. Ob man 
die ungenutzten Interrupt-Vektoren auf ein einsames RETI zeigen läßt 
oder auf eine Routine, die eine Fehler-LED einschaltet und dann in eine 
Endlosschleife geht, ist eine andere Frage. Zum Experimentieren eher 
letzteres.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Axel S. schrieb:
> Gräßlich.

Hi,
Genau, ist ja auch nicht meine Programm.
Die Frage zielte genau darauf ab, wieso eine Interrupteinsprungadresse 
angegeben wird, ohne sich weiter darum zu kümmern.

Also, persönlich mache das seit einiger Zeit immer so, wie im 
angehängten
File gezeigt, auch, wenn nur ein einziger Interrupt verwendet wird. Ist 
zwar "aufgeblasen", man erlebt dann aber auch keine Überraschungen.
(Nur beim Target-Wechsel muss man wieder anpassen.)

ciao
gustav

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Karl B. schrieb:
> Also, persönlich mache das seit einiger Zeit immer so, wie im
> angehängten
> File gezeigt

Du kannst dir die ganzen 'reti' sparen, es reicht ein einziges:
1
;Interrupt Service Routinen:
2
;
3
INT0adr:    ;Extern. Interrupt Request 0
4
INT1adr:    ;Extern. Interrupt Request 1
5
INT2adr:    ;Extern. Interrupt Request 2
6
INT3adr:    ;Extern. Interrupt Request 3
7
INT4adr:    ;Extern. Interrupt Request 4
8
INT5adr:    ;Extern. Interrupt Request 5
9
INT6adr:    ;Extern. Interrupt Request 6
10
INT7adr:    ;Extern. Interrupt Request 7
11
PCI0adr:    ;Pin Change Interrupt Request 0
12
PCI1adr:    ;Pin Change Interrupt Request 1
13
USB_GEN:    ;USB General Interrupt Request
14
USB_COM:    ;USB Endpoint/Pipe Interr. Com. Request
15
WDTadre:    ;Watchdog Timeout Interrupt
16
ICP1adr:    ;Timer/Counter2 Capture Event
17
OC1Aadr:    ;Timer/Counter2 compare match A
18
OC1Badr:    ;Timer/Counter2 compare match B
19
OC1Cadr:    ;Timer/Counter2 compare match C
20
OVF1adr:    ;Timer/Counter1 overflow
21
OC0Aadr:    ;Timer/Counter0 compare match A
22
OC0Badr:    ;Timer/Counter0 compare match B
23
OVF0adr:    ;Timer/Counter0 overflow
24
SPIadre:    ;SPI Serial Transfer Complete
25
URXC1ad:    ;USART1 RX Complete
26
UDRE1ad:    ;USART1 Data Register Empty
27
UTXC1ad:    ;USART1 TX Complete
28
ACIadre:    ;Analog Comparator
29
ERDYadr:    ;EEPROM Ready
30
SPMRadr:    ;Store Program Memory Read
31
: if desired, this would be the place for a 'Bad Interrupt' Routine
32
;
33
       reti
So zeigen alle Routinen erstmal auf einen Stub. Die benutzten Interrupts 
dann hier rausnehmen und behandeln.

: Bearbeitet durch User
von Karl B. (gustav)


Lesenswert?

Erst einmal "Danke" an @M..
Matthias S. schrieb:
> So zeigen alle Routinen erstmal auf einen Stub. Die benutzten Interrupts
> dann hier rausnehmen und behandeln.
Ja, wenn man von vorne herein nicht weiß, wie das Prog später aussehen 
soll, lieber 100 x abschreiben, sonst komm ich immer durcheinander.
Ist zwar unelegant, habe aber schon viele Fehler deswegen vermieden, die 
ich mir vorher nicht erklären konnte.


Hi, noch einmal zurück zum Prog. des TO
org. 0x13
Das stört mich irgendwie.
Darum nochmal eine Nachfrage.


Wie ich drauf komme ?:
Es gibt  auch "ungeradzahlige" Ints.
z.B. .equ  URXCaddr  = 0x0007  ; UART, Rx Complete  beim Attiny 2313

der verwendete 32-er hat die nicht. Das "falsche" def.inc file 
zugrundegelegt.sorry...

ciao
gustav

: Bearbeitet durch User
von Dirk (Gast)


Lesenswert?

>Du kannst dir die ganzen 'reti' sparen, es reicht ein einziges:
dann hast du ca. 20 Labels/Namen auf EINE Adresse.
Du kannst 100 Labels benutzen aber ohne nop o.ä. bleiben die Adressen 
gleich.
besser:
- bei kleineren µC (jmp==rjmp)=1W je Interrupt bsp. nop/rjmp/reti
- bei größeren '(mehr Flash) (jmp!=rjmp) 2W je Interrupt bsp. 
nop+nop/jmp /reti+nop oder nop+reti
vereinfacht: 13 ist möglich sofern der µC bescheiden unter 4kb(?) 
bleibt, ansonsten sind ungerade Zahlen von der Ziehung der 
Interupttadressen ausgeschlossen.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Dirk schrieb:
> dann hast du ca. 20 Labels/Namen auf EINE Adresse.

Ja, und? Das ist doch völlig egal. Es wird so genau eine Anweisung 
benötigt, statt für jede Routine eine eigene.
Es geht hier ja nur um die unbenutzten IRQ Vektoren.

Dirk schrieb:
> - bei kleineren µC (jmp==rjmp)=1W je Interrupt bsp. nop/rjmp/reti
Auch das ist völlig unnötig, was soll das für Vorteile haben?
Den entsprechenden Vektor nimmst du aus dem Stub raus und schreibst den 
Interrupt. Die Call Tabelle ruft ja diesen Vektor schon auf.

von Karl (Gast)


Lesenswert?

Matthias S. schrieb:
> Ja, und? Das ist doch völlig egal. Es wird so genau eine Anweisung
> benötigt, statt für jede Routine eine eigene. Es geht hier ja nur um die
> unbenutzten IRQ Vektoren.

Ähm - nö.

Du hast da was Grundlegendes übersehen. Die Adressen der 
Interrupteinsprünge sind sozusagen im Controller hartcodiert. Deine 
Labels interessieren den Controller einen Dreck. Die stehen in dem Fall 
alle an der gleichen Stelle, und zwar ganz vorn.

Entweder mit .org vor jedem Label die Adresse setzen, oder mit einem 
reti nach jedem Label die Adresse für das nächste inkrementieren. Oder 
wenigstens das einzige reti per .org ganz ans Ende der Tabelle, dann 
passiert Das was Du eigentlich erreichen willst. Aber dann kannst Du die 
Label auch komplett weglassen, den wie gesagt die sieht der Controller 
eh nicht. Da kannste auch Pippilangstrumpf reinschreiben.

von Rolf M. (rmagnus)


Lesenswert?

Karl B. schrieb:
> (Nur beim Target-Wechsel muss man wieder anpassen.)

Das ist der Nachteil dieser Variante. Auf einem anderen Prozessor kommt 
Blödsinn raus, wenn die Vektortabelle anders ist.
Bei den Angaben beim .ORG kann man statt Magic Numbers auch die 
vordefinierten Namen für die Einträge der Vektortabelle nutzen. Wenn man 
dann den Prozessor wechselt, sind die Interrupts dann trotzdem richtig 
sortiert, bzw. bei denen, die es dort nicht gibt, kommt ein Fehler, weil 
der Name nicht aufgelöst werden kann.

Karl B. schrieb:
> Wie ich drauf komme ?:
> Es gibt  auch "ungeradzahlige" Ints.
> z.B. .equ  URXCaddr  = 0x0007  ; UART, Rx Complete  beim Attiny 2313
>
> der verwendete 32-er hat die nicht. Das "falsche" def.inc file
> zugrundegelegt.sorry...

Wenn du schon weißt, dass die Namen definiert sind, warum um alles in 
der Welt nutzt du die dann nicht, sondern schreibst stattdessen 0x13 
hin?

Dirk schrieb:
> vereinfacht: 13 ist möglich sofern der µC bescheiden unter 4kb(?)

4k Words, also 8kB.

> bleibt, ansonsten sind ungerade Zahlen von der Ziehung der
> Interupttadressen ausgeschlossen.

von Axel S. (a-za-z0-9)


Lesenswert?

Karl schrieb:
> Du hast da was Grundlegendes übersehen. Die Adressen der
> Interrupteinsprünge sind sozusagen im Controller hartcodiert. Deine
> Labels interessieren den Controller einen Dreck. Die stehen in dem Fall
> alle an der gleichen Stelle, und zwar ganz vorn.

Ja und Nein. Ja, die Labels zeigen alle auf eine Adresse. Aber Nein, 
weder stehen sie ganz vorn noch sind sie dem Controller egal. Du bist 
gedanklich immer noch beim AVR hängen geblieben. Matthias hingegen ist 
bei einem Controller, in dem die Vektortabelle eine wirkliche Tabelle 
ist.

Der AVR springt bei einen Interrupt an die entsprechende Position im 
Flash, weswegen dort ein gültiger Befehl stehen muß (typischerweise ein 
RJMP). Andere µC haben in der Vektortabelle lediglich Adressen stehen 
und der Controller macht beim Interrupt einen indirekten Sprung: er 
fischt die Adresse aus der Tabelle und springt dann dahin.

Karl schrieb:
> Entweder mit .org vor jedem Label die Adresse setzen, oder mit einem
> reti nach jedem Label die Adresse für das nächste inkrementieren.

Nein. Ein ORG hat innerhalb der Tabelle nichts verloren. Da gehört nur 
ein einziges ORG an den Anfang der Tabelle. Spezifisch für den AVR 
würde die Tabelle so aussehen:
1
.org 0
2
RJMP RESET
3
RJMP INT0
4
RJMP INT1
5
...
(komplette Tabelle gefüllt mit RJMPs zu Labels mit sprechenden Namen)

Weiter hinten im Code werden alle vorerst ungenutzten Interrupts vor 
einen einzelnen RETI aufgereiht:
1
INT0:
2
INT1:
3
...
4
reti

von Route_66 H. (route_66)


Lesenswert?

Axel S. schrieb:
> Karl schrieb:
>> Du hast da was Grundlegendes übersehen. Die Adressen der
>> Interrupteinsprünge sind sozusagen im Controller hartcodiert. Deine
>> Labels interessieren den Controller einen Dreck. Die stehen in dem Fall
>> alle an der gleichen Stelle, und zwar ganz vorn.
>
> Ja und Nein.

Wieso Nein? Axel S. hat vollkommen Recht. Der Codeauszug von Matthias 
S. ist vollkommener Blödsinn.

Axel S. schrieb:
> Andere µC haben in der Vektortabelle lediglich Adressen stehen
> und der Controller macht beim Interrupt einen indirekten Sprung:

Auch dann wäre die Variante von Matthias S. nicht lauffähig!

Axel S. schrieb:
> Nein. Ein ORG hat innerhalb der Tabelle nichts verloren. Da gehört nur
> ein einziges ORG an den Anfang der Tabelle.

Das ist nun wieder absoluter Blödsinn!
Wenn ich nur die letzten drei INT-Vektoren der Tabelle brauche, müsste 
ich ja die Lücke vom RESET-Vektor bis zu meinen verwendeten Vektoren 
irgendwie ausfüllen. Das kann ich mit dem von Matthias falsch 
angedeutetem RETI oder mit der ORG-Anweisung lösen.

Das geht sowohl bei festen INT-Einsprungstellen (AVR, 8051, Z8...) und 
auch bei vektorisierten Interrupts (wie z.B. beim Z80)!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Route 6. schrieb:
> Der Codeauszug von Matthias S. ist vollkommener Blödsinn.

Ich glaube, Du hast den Codeauszug von Matthias S. einfach 
fehlinterpretiert. Das soll keine Interrupt-Tabelle sein, sondern der 
Code, der aus der Interrupt-Tabelle per RJMP angesprungen wird.

von Axel S. (a-za-z0-9)


Lesenswert?

Route 6. schrieb:
> Axel S. schrieb:
>> Karl schrieb:
>>> Du hast da was Grundlegendes übersehen. Die Adressen der
>>> Interrupteinsprünge sind sozusagen im Controller hartcodiert. Deine
>>> Labels interessieren den Controller einen Dreck. Die stehen in dem Fall
>>> alle an der gleichen Stelle, und zwar ganz vorn.
>>
>> Ja und Nein.
>
> Wieso Nein? Axel S. hat vollkommen Recht.

Du bist durcheinander. Erst kritisierst du meinen Post, um mir im 
nächsten Satz zu bescheinigen, ich hätte "vollkommen Recht".

> Der Codeauszug von Matthias S. ist vollkommener Blödsinn.

Du hast ihn wohl nur nicht verstanden.

>> Andere µC haben in der Vektortabelle lediglich Adressen stehen
>> und der Controller macht beim Interrupt einen indirekten Sprung:
>
> Auch dann wäre die Variante von Matthias S. nicht lauffähig!

Wieder: du hast es nur nicht verstanden. Ich hatte übrigens auch nicht 
genau genug geschaut. Matthias hat ja gar keine Tabelle gezeigt. Nur 
die Implementierung der Dummy-ISR.

>> Ein ORG hat innerhalb der Tabelle nichts verloren. Da gehört nur
>> ein einziges ORG an den Anfang der Tabelle.
>
> Das ist nun wieder absoluter Blödsinn!

Manieren!

> Wenn ich nur die letzten drei INT-Vektoren der Tabelle brauche, müsste
> ich ja die Lücke vom RESET-Vektor bis zu meinen verwendeten Vektoren
> irgendwie ausfüllen.

Die Vektortabelle hat keine Lücken. Das sind alles gültige Vektoren, 
auch dann wenn du sie nicht nutzt. Und es ist zwar vielleicht nicht 
absolut zwingend, trotzdem aber höchst empfehlenswert, auch die 
ungenutzten Vektoren auf etwas zeigen zu lassen, das etwas 
wohldefiniertes tut. Im Zweifel einfach ein IRET.

Da andererseits ein aktivierter Interrupt ohne die zugehörige ISR ein 
klarer Fehler ist, ist es zumindest in der Entwicklungsphase der 
Software besser, wenn man diesen Fehler klar diagnostizierbar macht.

von Dirk (Gast)


Lesenswert?

Matthias S. schrieb:
> Es geht hier ja nur um die unbenutzten IRQ Vektoren.
da gibt es wohl einige Missverständnisse um welche IRQ 'Vektoren' es 
geht.
Ich hab deinen relativen Bezugspunkt (Listing mit von Karl B 
programmierten 'Vektoren' /jmp's) erst übersehen und die Aussage
>Die benutzten Interrupts dann hier rausnehmen und behandeln
kann sehr interessant werden, wenn 'unbenutzte' Interrupts 
'normalerweise' (u.a. meine Gewohnheit) an Ort und Stelle (Addr 
0..max_vector_size) mit reti behandelt werden und während Karl B. erst 
mal alle IRQ 'raus'jmp und 'draußen' jeden IRQ individuell mit einem 
eigenen reti abschließt, aber innerhalb von draußen jeweils zwischen
label:
reti
eine vor Ort Behandlung programmieren könnte.
Es gibt da interessante Widersprüche, dass du glaubst Karl B wolle 
überhaupt reti sparen und ich vermutlich dachte dann kann man sich den 
jmp zum reti gleich ganz sparen (wäre eine Möglichkeit, aber ich hab nur 
den Bezug zum Listing nicht gesehen, aber nach dem Besuch des Listings 
vermutlich die Intention von Karl B. fehlerfreier gelesen)
(erstes) kurz: ca. zwei Programmierstile verursachen unterschiedliche 
IRQ-Vektoren die leichte Kompatibiltätsprobleme in einem Forum haben.

Programmierer sich häufig Menschen und da können sich Stile 
unterscheiden und wenn man etwas lernen will dann ist auch ganz 
interessant sich mehrere(!)Varianten anzuschauen (und auch Programmierer 
sprachliche Effekte dabei zu beachten):

Ein Interuptfester Programmierer, der an kontrollierte Interupt-Ursachen 
glaubt und sich dafür nicht dafür interessiert was der Teufel weiß wenn 
"so ein Interrupt [zufällig(?)] mal ausgelöst wird":
1
.org 0
2
jmp start
3
.org INT_VECTORS_SIZE; kann bei Glaube an vorher korrekte Reihenfolge entfallen
4
start:
5
;mit einem rausgeholten Interupt:
6
.org 0
7
jmp start
8
.org INT0addr
9
jmp prg_int0; Programmierer erwartet ex_int0 eingeschaltet zu haben und holt den passenden Interupt raus
10
start:
(Vorteil: sehr viel gespart, weder zu viel Speicher noch zu viel Text)

Programmierer der erst alle Interupts rausholt (Karl B)
1
org 0x0000        
2
rjmp RESET        ;"RESET vector"
3
.org 0x0002
4
rjmp INT0adr    ;Extern. Interrupt Request
5
...
6
.org 0x0038
7
rjmp SPMRadr    ;Store Program Memory Read
8
;
9
;Interrupt Service Routinen:
10
INT0adr:        ;Extern. Interrupt Request 0
11
 behandlungsplatz 1
12
reti
13
INT1adr:        ;Extern. Interrupt Request 1
14
reti
15
...
16
RESET:
(Vorteil: kann von Karl B. und anderen besser gelesen werden)

Programmierer der befürchtet Karl B wollte gar nicht so viele reti 
investieren
1
.org 0x0000        
2
rjmp RESET        ;"RESET vector"
3
.org 0x0002
4
rjmp INT0adr    ;Extern. Interrupt Request
5
...
6
.org 0x0038
7
rjmp SPMRadr    ;Store Program Memory Read
8
;
9
;Interrupt Service Routinen:
10
INT0adr:
11
INT1adr:        
12
...
13
reti
14
raus_geholt:
15
behandlung
16
reti
17
RESET:
18
...
(Vorteil: relativ zu Karl B. viele reti gespart, aber eins mehr als 
weiter oben verwendet)

Nach Tabellennorm programmierter Programmierer/Ausfüller, der 
nebenberuflich über man aufklärt ("Korrekt macht man das so, daß man 
immer die komplette Vektortabelle *ausfüllt*")
1
org 0
2
rjmp RESET
3
reti ;hier könnte ein anderer korrekter Vektor stehen
4
reti ;hier könnte ein anderer korrekter Vektor stehen
5
reti ;hier könnte ein anderer korrekter Vektor stehen
6
...
7
reti ;hier könnte ein anderer korrekter Vektor stehen
8
reti ;hier könnte ein anderer korrekter Vektor stehen
9
Reset:
(Vorteil: muss nicht denken und kann die gesparte Leistung zur 
Aufklärung von Abweichlern nutzen)

oder ein Programmierer der wirklich etwas knapp bei Speicher ist und 
ernsthaft reti 'sparen' will/muss (und kein Interesse an Teufel & Co 
hat)
1
.org 0
2
 anweisung 1; geht üblicherweise eh bei 0 los
3
 anweisung 2;
4
 ...
5
 jmp end_r_vec
6
.org 13
7
 jmp int13; der berühmte int 13 wird rausgeholt
8
end_r_vec:..;weiter im Programm
(Vorteil: der Sparwille ist leicht ablesbar und spart u.U. 20 Byte)

Neben der hoffentlich geklärten Frage warum int 13 bei größeren µC 
tabuisiert ist(weil nur gerade Adressen 32-bit-jmp sicher adressieren 
können)ist bei deinem Vorschlag eine gewisse Ähnlichkeit mit einem 
traditionellen NOP-Slide aus der PC-Heap-Sprayer-Szene zu erkennen (der 
Einsprung soll viele Möglichkeiten haben), praktisch ein NOP-Slide ohne 
nop. Nichts dramatisches, aber irgendwie anders als anders gewohnt.


Da ich gestern das Listing als Bezug übersehen hab und deinen  Vorschlag 
als Programmanfang gelesen hab, aber aktuell noch die Vorstellung 
interessant finde wenn dein Programm (ohne Karlsteil) von einem µC 
ausgeführt würde (aus geplantem Kommentar):
Der Programmablauf vom µC ausgeführt (an Adresse 0:reti):
- der µC erhält Strom
- Anweisung 'zurück' aus Interupt(reti)
- im Stack-Speicher könnte nach längerer Stromlosigkeit $ff $ff 
eventuell sicher sein
==>'Rück'sprung an Adresse $ffff
sicherlich auch interessant, wenn ein µC nach längerem ausschalten 
wahrscheinlicher einen sichereren Anfang am Ende des Programmspeichers 
vollzieht, aber mit Programmierung im traditionellen Sinne hätte das 
wenig zu tun.

Wahrscheinlich werden einige Programierstile bestimmte Fehler 
wahrscheinlicher beeinflussen, aber bevor ein Programmierer/Mensch den 
Teufel zur Erklärung benötigt kann ein offenerer Umgang mit Sprache auch 
Spass machen:
Nicht nur rausgeholte Interrupts, sondern auch der Vektorraum der in der 
Speichersparvariante mit ungewöhnlichen Aufgaben belegt wurde können 
missverstanden werden, aber funktionieren auf dem µC (häufig).


Disclaimer: die Moralprogrammierer-Version die über verlorene Seelen 
programmiert ("Ein ORG hat innerhalb der Tabelle nichts verloren. Da 
gehört nur ein einziges ORG an den Anfang der Tabelle.")habe ich 
vergessen, aber der gehörige Prediger sich sicher nichts dabei gedacht 
haben.

von Axel S. (a-za-z0-9)


Lesenswert?

Dirk schrieb:
> Ein Interuptfester Programmierer, der an kontrollierte Interupt-Ursachen
> glaubt und sich dafür nicht dafür interessiert was der Teufel weiß wenn
> "so ein Interrupt [zufällig(?)] mal ausgelöst wird"

Du hast meinen Punkt nicht mal annähernd verstanden. Es geht nicht 
darum, ob ein Programmierer "interruptfest" ist. Es geht darum, daß 
Programmierer Menschen sind und (deswegen?) Fehler machen.

Zum Beispiel könnte ein Programmierer zwar einen Interrupt aktivieren, 
dann aber vergessen, die ISR auch zu programmieren. Oder er benutzt den 
falschen Namen für die ISR (das kann in C recht leicht passieren). Oder 
er verschusselt den Namen eines Bits oder Registers und aktiviert so 
einen ganz anderen Interrupt als vorgesehen. Oder oder oder.

Und dann geht es darum, den Schaden zu begrenzen. Und den Fehler (der ja 
nicht offensichtlich sein muß) erkennbar zu machen. Der avr-gcc fügt 
z.B. für ungenutzte Vektoren einen Sprung zum Reset-Vektor ein. In so 
einem Fall würde der unbeabsichtigt ausgelöste Interrupt zum Neustart 
des Programms führen. Und ich erinnere mich an diverse Threads in diesem 
Forum, wo genau das passiert ist und der Anwender hanebüchene Theorien 
darüber aufstellte, was denn am Compiler oder am µC kaputt wäre, weil 
das Programm scheinbar "nichts tut".

In Produktionscode würde man ungenutzte Interrupts vermutlich am besten 
mit einem RETI terminieren. Zur Entwicklungszeit ist es besser, dafür 
eine Diagnosemöglichkeit vorzusehen. Sei es eine LED, die im Fehlerfall 
eingeschaltet wird. Oder eine Fehlermeldung auf einem Display oder über 
den UART ausgegeben. Was halt da ist und paßt.

Aber einfach nur zu sagen "das passiert mir nicht und deswegen brauche 
ich mir auch keine Gedanken darüber zu machen, was passieren könnte" ist 
einfach nur dämlich.


Ach, eins noch: deine Sätze sind zu lang. Dein Post ist sehr anstrengend 
zu lesen.

: Bearbeitet durch User
von Route_66 H. (route_66)


Lesenswert?

Axel S. schrieb:
> Ich hatte übrigens auch nicht
> genau genug geschaut. Matthias hat ja gar keine Tabelle gezeigt. Nur
> die Implementierung der Dummy-ISR.

Siehste!

Axel S. schrieb:
>>> Ein ORG hat innerhalb der Tabelle nichts verloren. Da gehört nur
>>> ein einziges ORG an den Anfang der Tabelle.
>>
>> Das ist nun wieder absoluter Blödsinn!
>
> Manieren!

Nein. Dogmen sind falsch!
Klar, ich verstehe deine Meinung. Es führt zu vielen 
Fehlermöglichkeiten. Man sollte diese Form vermeiden. Aber "...nichts 
verloren" ohne Erklärung ist Dogmatismus.

Axel S. schrieb:
> Und es ist zwar vielleicht nicht
> absolut zwingend, trotzdem aber höchst empfehlenswert, auch die
> ungenutzten Vektoren auf etwas zeigen zu lassen, das etwas
> wohldefiniertes tut. Im Zweifel einfach ein IRET.

Siehste...

Axel S. schrieb:
> Da andererseits ein aktivierter Interrupt ohne die zugehörige ISR ein
> klarer Fehler ist, ist es zumindest in der Entwicklungsphase der
> Software besser, wenn man diesen Fehler klar diagnostizierbar macht.

Richtig - aber nicht zwingend notwendig.

von Dirk (Gast)


Lesenswert?

Axel S. schrieb:
> Du hast meinen Punkt nicht mal annähernd verstanden.
das heißt du kannst nicht eigenständig antworten und musst wie ein Idiot 
glauben ich hätte "deinen Punkt" nicht verstanden.
Ich habe nicht deinen Punkt erwähnt, sondern deinen Text (praktisch das 
was du 'programmiert' hast)
Falls du eigenständig meinen Text lesen könntest
>>Wahrscheinlich werden einige Programierstile bestimmte Fehler wahrscheinlicher 
beeinflussen
und nicht von einem Abweichungsinterrupt zu deiner unsortierten Ausgabe 
gezwungen wärst, dann könntest du dich vorher in einen 
Konzentrationsmodus schalten und
>Zum Beispiel könnte ein Programmierer zwar einen Interrupt aktivieren,
den Namen des einen Interrupt nennen und die konkreten 
unterschiedlichen Fehlerwirkungen vergleichen. Deine Massenausgabe an 
unbestimmten Spekulationen ohne konkrete Inhalte dürfte deiner Teufel 
Nutzung sehr ähnlich sein.

> Aber einfach nur zu sagen "das passiert mir nicht und deswegen brauche
> ich mir auch keine Gedanken darüber zu machen, was passieren könnte" ist > 
einfach nur dämlich.
Wenn du festen Speicher verwenden würdest, dann müsstet du nicht 
dämlich Zitate einfach fühlen, sondern könntest eigenständig antworten

> Ach, eins noch: deine Sätze sind zu lang. Dein Post ist sehr anstrengend
> zu lesen.
du bist sicherlich überfordert längere Sätze zu lesen. Versuch doch 
einfach den Satz/die Sätze die dich belasten zu zitieren, damit der/die 
Fehler den du meinst auch nachlesbar sind.
Programmierer sind Menschen und machen Fehler, deswegen sollten bspw. zu 
lange Sätze offen beim Satz genannt werden, damit die fehlerhafte Länge 
korrigiert werden kann.

von Dieter W. (dds5)


Lesenswert?

Ein IRET allein ist aber nur die absolute Notbremse denn wenn das 
zugehörige I-Flag nicht gelöscht wird dann haut der INT permanent wieder 
rein und erzeugt ordentliche CPU Last.

: Bearbeitet durch User
von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
noch ein "Bockmist"-Beispiel.
Die .equ Anweisung ist zweifelsfrei per copy&paste vom def.inc-File 
blindfischmäßig reingesetzt worden.
Aber, was mich damals etwas verwunderte, sogar das "Renamen" der 
Interrupts wird akzeptiert.
Das entscheidendes Kriterium ist offensichtlich die korrekte vorgegebene 
Reihenfolge.
(Und dementsprechend natürlich auch die Angabe der ISRs.)

Aus diesem Fallbeispiel hatte ich endgültig meine Lehren gezogen und 
mache es jetzt wie oben schon gezeigt. Das ist zwar speicherfressend und 
"redundant", aber für Korrekturen irgendwie bequemer. Steht das Programm 
endgültig, kann es an die Feinstrukturierung gehen.

ciao
gustav

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

>Aus diesem Fallbeispiel hatte ich endgültig meine Lehren gezogen und
>mache es jetzt wie oben schon gezeigt.

Das ist aber auch Blödsinn, denn der Flash des Controllers ist größer 
als der mit rjmp erreichbare Speicherraum ist.

Bei mir geht das einfacher. Ich habe mir ein Delphi-Programm 
geschrieben, das aus den XML-Dateien des 4er Studios Code generiert. Der 
Anhang hat nur ein paar Sekunden gedauert.

MfG Spess

von Karl B. (gustav)


Lesenswert?

spess53 schrieb:
> denn der Flash des Controllers ist größer
> als der mit rjmp erreichbare Speicherraum ist.

Hi,
yep, klaro, aber:

"...JMP - Jump
Jump to an address within the entire 4M (words) program memory. See also 
RJMP.
This instruction is not available in all devices. Refer to the device 
specific instruction set summary...."

Targetspezifisch. Wurde oben - glaube ich - schon erwähnt.
Karl B. schrieb:
> Nur beim Target-Wechsel muss man wieder anpassen.

Das "extended" Prinzip haben beide "Varianten" aber gemeinsam:
Auflisten der Int Adr und
Auflisten der ISRs in der richtigen Reihenfolge mit Abschluss (jede für 
sich ein RETI spendiert. Und kein General RETI für alle.)
(Die .org's sind überflüssig (bis auf den Nuller vielleicht, das ist ja 
kein "echter" Interruptvektor))
Gefällt mir. Mach ich demnächst so.
Die Sache mit der Sprungweite des rjmp-Befehls kann bei  den "kleineren" 
AVRs schon Probs. bereiten. Erst recht bei den Megas etc. Habe letztens 
Routinen vom Ende näher in die Mitte des Progs. holen müssen, sonst 
liefen die nicht.

ciao
gustav

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>... und Auflisten der ISRs in der richtigen Reihenfolge mit Abschluss (jede >für 
sich ein RETI spendiert.

???

Für die ISRs muss keinerle Reihenfolge eingehalten werde. Die kann man 
hinschreiben wo man will. Bei AVRs mit <=4kWord Flash kann man mit rjmp 
jede Stelle des Flashs erreichen. Und die AVRs mit >4kWord haben pro 
IV-Tabelleneintrg Platz für jmp. Damit lassen sich 4 MWord adressieren.

Also verstehe ich deine Probleme nicht wirklich.

MfG Spess

von Karl (Gast)


Lesenswert?

Karl B. schrieb:
> Auflisten der ISRs in der richtigen Reihenfolge mit Abschluss (jede für
> sich ein RETI spendiert. Und kein General RETI für alle.)
> (Die .org's sind überflüssig (bis auf den Nuller vielleicht, das ist ja
> kein "echter" Interruptvektor)

Im Gegenteil sind die.orgs sehr nützlich, wenn man sie mit reti oder 
rjmp kombiniert. Also:

.org int1addr
reti
.org int2addr
rjmp isr_int2
.org int3addr
reti
...

Dann passiert nämlich Folgendes: Das reti oder rjmp inkrementiert den 
Adresscounter, das .org setzt den nächsten Befehl genau auf diese 
Addresse.

Kopiert man ein Programm für eine anderen Typ, oder baut man ein rjmp 
ein ohne das reti zu löschen, oder verwechselt man Interruptaddresse, 
dann meckert der Compiler, weil sich Addressen überschneiden. Löscht man 
aus Versehen ein reti, ohne ein rjmp einzufügen, stimmen nachfolgende 
Addressen trotzdem erstmal.

Das ist sehr sicher.

Andererseits, ich hab in 15+ Jahren Assembler auf dem Avr schon viel 
Mist gebaut. Auch Interrupts aktiviert und dann andere genutzt, zum 
Beispiel beim Txd Interrupt, UDR empty oder Data send. Aber rjmp ohne 
zugehörige Routine geht gar nicht, weil dann der Compiler wegen 
fehlendem Label meckert.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Karl schrieb:
> Du hast da was Grundlegendes übersehen. Die Adressen der
> Interrupteinsprünge sind sozusagen im Controller hartcodiert. Deine
> Labels interessieren den Controller einen Dreck. Die stehen in dem Fall
> alle an der gleichen Stelle, und zwar ganz vorn.

Es ist doch klar, das die Vektortabelle drin bleibt. Es geht nur um die 
Labels, die aus dieser angesprungen werden. Ich hatte die Vektortabelle 
in meinem Codefetzen nur nicht nochmal reingeschrieben und dachte, das 
wäre durch die Benutzung deiner Labelnamen klar geworden. Und diese 
Labels können alle auf das gleiche 'reti' zeigen - oder man behandelt 
hier auf Wunsch den 'Bad Interrupt'.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Matthias S. schrieb:
> Es ist doch klar, das die Vektortabelle drin bleibt. Es geht nur um die
> Labels, die aus dieser angesprungen werden. Ich hatte die Vektortabelle
> in meinem Codefetzen nur nicht nochmal reingeschrieben.

Ich hatte das sofort verstanden. Aber Du musst immer in Erwägung ziehen, 
dass es hier Leute gibt, die Deine Beiträge nur flüchtig lesen - 
entweder, weil sie generell immer nur querlesen oder weil sie einfach 
nicht genügend Zeit zum Lesen (und Verstehen) aufbringen wollen.

Dann kommt so etwas raus:

Route 6. schrieb:
> Der Codeauszug von Matthias S. ist vollkommener Blödsinn.

Karl schrieb:
> Du hast da was Grundlegendes übersehen. Die Adressen der
> Interrupteinsprünge sind sozusagen im Controller hartcodiert.

Ich hatte das aber hier schon klargestellt:

Frank M. schrieb:
> Du hast den Codeauszug von Matthias S. einfach fehlinterpretiert. Das
> soll keine Interrupt-Tabelle sein, sondern der Code, der aus der
> Interrupt-Tabelle per RJMP angesprungen wird.

Fazit:

Schreib's beim nächsten Mal etwas vollständiger, spart eine Menge 
unnötiger Antworten ;-)

: Bearbeitet durch Moderator
von Rolf M. (rmagnus)


Lesenswert?

Naja, irgendwie ist die Idee so auch eher sinnlos, finde ich.

Matthias S. schrieb:
> Du kannst dir die ganzen 'reti' sparen, es reicht ein einziges:

Dafür braucht man dann eine Reihe rjmp, die alle zu dem gemeinsamen reti 
springen. Gespart hat man damit also eigentlich nichts.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Karl schrieb:
> Im Gegenteil sind die.orgs sehr nützlich, wenn man sie mit reti oder
> rjmp kombiniert. Also:
>
> .org int1addr
> reti

Hi,
also doch wieder so, wie ich es im Beispiel am Anfang gemacht habe.
https://www.mikrocontroller.net/attachment/357533/Interruptvektoren_.asm
Zusatz laut Empfehlung von @spess53:
Wenn es nicht hinhaut, dann eben mit dem jmp-Befehl -> targetspezifisch.

spess53 schrieb:
> Für die ISRs muss keinerle Reihenfolge eingehalten werde. Die kann man
> hinschreiben, wo man will.

Die Reihenfolge bei mehreren ISRs "sollte" der Übersichtlichkeit halber 
der vorher oben angegebenen Int Vektoren- (jetzt mache ich nicht den 
Fehler und sage "Tabelle") Anordnung entsprechen.
Das war etwas unsauber formuliert von mir.
Sicherlich gibt es Situationen in der Strukturierung des Listings,
wo es sinnvoller ist, die funktionell zusammengehörigen Befehle 
hintereinander zu schreiben (mit Kommentar). Jetzt sklavisch dem einmal 
in Stein gemeißelten Schema zu gehorchen, ist natürlich wahlfrei.

Die Diskussion ist jetzt aber in eine andere Richtung abgedriftet:
Die Frage des TO war, wieso man im Hex-File nicht den OP-Code 1:1 
wiederfindet.
Stichwort "Big Endian" etc.
Janik schrieb:
> Ok, danke, ich les mich mal rein ^^ Und melde mich wieder ;)

spess53 schrieb:
> Also verstehe ich deine Probleme nicht wirklich.
Der Stein des Anstoßes war die ominöse Angabe von
.org 0x13 ganz oben

Diese Zeile wurde von mir als Angabe eines Interrups angesehen, den es 
laut Kommentar hier auch garnicht gibt. Bis jetzt habe ich die Bedeutung 
dieser Angabe immer noch nicht verstanden. Wäre für Aufklärung sehr 
dankbar.

ciao
gustav

von Axel S. (a-za-z0-9)


Lesenswert?

Rolf M. schrieb:
> Naja, irgendwie ist die Idee so auch eher sinnlos, finde ich.
>
> Matthias S. schrieb:
>> Du kannst dir die ganzen 'reti' sparen, es reicht ein einziges:
>
> Dafür braucht man dann eine Reihe rjmp, die alle zu dem gemeinsamen reti
> springen. Gespart hat man damit also eigentlich nichts.

Sparen ist hier auch fehl am Platz. Die Vektortabelle ist ohnehin da, an 
der kann man nichts einsparen [1]. Und ob da nun ein RJMP oder RETI an 
der entsprechenden Stelle steht, macht für die Codegröße keinen 
Unterschied.

Die einzige Stelle, wo man ein bißchen sparen kann, ist wenn man alle 
ungenutzten Interrupts auf das gleiche RETI umleitet. Das macht zwar das 
Kraut nicht fett, der Vorteil wird aber sofort sichtbar, wenn man statt 
RETI eine echte BAD-ISR Behandlung machen will.

Direkt RETI in die Vektortabelle zu schreiben, halte ich für unschön. 
Tatsächlich hadere ich schon mit der Entscheidung von AVR, die Tabelle 
überhaupt mit Code zu füllen, statt mit reinen Adressen. Aber gut, das 
ist jetzt im Silizium und muß so hingenommen werden.

Was aus meiner Sicht für JMP/RJMP spricht, ist daß AVR das so vorgesehen 
hat und die Länge der einzelnen Einträge genau darauf abgestimmt ist. Es 
ist nur ein glücklicher Zufall, daß der Opcode für RETI genauso lang ist 
wie der für den Sprung.


[1] Im Prinzip kann man schon etwas sparen. Wenn man z.B. keinen 
einzigen Interrupt benutzt, kann man das Programm direkt an 0x0000 
beginnen lassen. Oder wenn man nur ein paar Interrupts von Anfang der 
Tabelle braucht, kann man den Rest der Tabelle für Code nutzen. Ich 
halte das aber für üblen Pfusch.

von c-hater (Gast)


Lesenswert?

Axel S. schrieb:

> Sparen ist hier auch fehl am Platz. Die Vektortabelle ist ohnehin da, an
> der kann man nichts einsparen

Doch, natürlich. Grundsätzlich kann man alle ungenutzten Vektoren 
natürlich als ganz normalen Flashspace verwenden. Wenn man für ein 
konkretes Projekt gerade knapp beim Flash ist, ist das manchmal 
vielleicht ganz allgemein nützlich, weil es den Wechsel zum 
nächstgrößeren Controller spart (inbesondere, wenn es keinen 
nächstgrößeren Verwandten gibt).

Attraktiver wird die Sache aber noch, wenn man Anwendungen mit extrem 
häufig aufgerufenen ISRs hat. Dann ermöglicht das nämlich u.U. eine "in 
place"-ISR. Spart mindestens zwei Takte pro Aufruf durch den 
eingesparten rjmp.
Wenn der Nutzcode dieser ISR z.B. nur 8 Takte braucht, dann ist die 
Ersparnis durch so eine "in place"-ISR enorm, satte 20%. Das hat 
durchaus das Potential, der Diskriminator zwischen "geht" und "geht 
nicht" für eine Anwendung zu sein...

> Direkt RETI in die Vektortabelle zu schreiben, halte ich für unschön.

Warum?

> Tatsächlich hadere ich schon mit der Entscheidung von AVR, die Tabelle
> überhaupt mit Code zu füllen, statt mit reinen Adressen.

Weil du das Potential nicht wirklich begreifst. Einem Asm-Programmierer 
(also einem richtigen, nicht einem Anfänger wie dem TO) ist es hingegen 
sofort klar.

> [1] Im Prinzip kann man schon etwas sparen. Wenn man z.B. keinen
> einzigen Interrupt benutzt, kann man das Programm direkt an 0x0000
> beginnen lassen. Oder wenn man nur ein paar Interrupts von Anfang der
> Tabelle braucht, kann man den Rest der Tabelle für Code nutzen. Ich
> halte das aber für üblen Pfusch.

Weil du halt nur in den engen Kategorien deiner Fähigkeiten und der 
durch Hochsprachenkonventionen geprägten Denkmuster denken kannst. Du 
hast deinen Intellekt freiwillig selbst kastriert. Das einzige, was dich 
trösten kann: das hast du mit schätzungsweise 99,8 aller (noch) aktiven 
Programmierer gemeinsam..

Die anderen, die noch selber wussten was sie tun und keine 
Compiler-Nanny benötigten, sind überwiegend im Ruhestand oder sogar 
schon tot...

von Karl (Gast)


Lesenswert?

Frank M. schrieb:
> Ich hatte das sofort verstanden. Aber Du musst immer in Erwägung ziehen,

Ich würde eher in Erwägung ziehen, dass ein derart mißverständlicher 
Codeschnipsel - denn  im Begleittext steht noch sowas wie "braucht man 
nicht" - unter Garantie wieder im Forum aufschlägt: Hilfe! Ich hab das 
genauso gemacht wies da steht, aber mein Interrupt geht nicht.

Axel S. schrieb:
> Direkt RETI in die Vektortabelle zu schreiben, halte ich für unschön.

Tja, das sieht der Hersteller der Avrs anders, und schlägt genau das 
vor. Aber das ist ja nur der Hersteller, was weiss der schon...

von Ernst (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!
Man muss den Hex Code in Bin code umschreiben dann findet man in den 
Opcodes in der Liste für die AVR's.
das wird hier gut erklärt.


(http://www.rowalt.de/mc/index.htm     -     AVR Buch Vorschau

Buch 2.Ausgabe kann online gelesen werden Seite 12 und 13 wird das 
Problem sehr gut erklärt

von Peter D. (peda)


Lesenswert?


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.