Forum: Mikrocontroller und Digitale Elektronik Wie bindet man Unterprogramme in asm ein?


von Moschder (Gast)


Lesenswert?

Hallo zusammen,

ich habe mir in asm ein Programm geschrieben, das für ein 16x2 Display 
sämtliche Routinen enthält.
Wie kann ich dieses Programm in mein eigentliches Hauptprogramm 
einfügen?

Habe es so versucht: mein Hauptprogramm heißt
messung.asm, dort habe ich an den Anfang .include "LCD_routins.asm"
geschrieben, so heißt mein Programm für die LCD Routinen.
Das Programm Messung habe ich im AVR Studio als entry file markiert.
wenn ich das Ganze nun im Debugger laufen lasse beginnt das Programm
mit dem abarbeiten des LCD_routins.asm und das obwohl
es nicht als entry file gekennzeichnet ist. das wiederum bringt den 
Fehler
dass der Stack überläuft, da dieser im messung.asm initialisiert wird 
und nicht im Messung.asm.
Wenn ich nun beide Programme zusammen in ein Fenster schreibe läuft es 
im
Debugger sowie auf meinem ATMEGA8 problemlos.
Also, wie mache ich das wenn ich mehrere Programme zu einem großen
zusammenbauen möchte ohne alles in ein Fenster zu schreiben?


Gruß
Moschder

von spess53 (Gast)


Lesenswert?

Hi

Die Include-Anweisung muss ans Ende vom Hauptprogramm. An den Anfang 
kann man  nur Include-Dateien setzen, die KEINEN Programmcode enthalten.

MfG Spess

von Moschder (Gast)


Lesenswert?

besten Dank :), nun funktionierts.
Du hast mir den Weg zu größerem Code geöffnet.

von spess53 (Gast)


Lesenswert?

Hi

Noch ein Hinweis: Include-Dateien sollten keine .org-Anweisungen haben.

MfG Spess

von 6641 (Gast)


Lesenswert?

Man kann die ASM anweisungen und die includes mischen. Ich hab zuerst 
die Interrupt tabelle, und dann kommen gleich die Includes. Und dann die 
Makros.

von Moschder (Gast)


Lesenswert?

ok, ist bei mir nicht der Fall, habe überhaupt keine org Anweisungen 
drin,
wie setzte ich die denn sinnvollerweise ein?

von spess53 (Gast)


Lesenswert?

Hi

.org-Anweisungen bewirken, das der nachfolgende Programmcode (in cseg) 
bzw. die Speicherstellen (dseg/eseg) an der Adresse beginnen, die in der 
Org-Anweisung steht.

Noch mal zur Include-Anweisung: Beim Assemblieren wird der Code,der in 
der Include-Datei steht, an dieser Stelle eingefügt. Das geht an jeder 
Stelle (hat 6641 natürlich Recht), wo das nicht stört. Ich bevorzuge das 
Ende des Hauptprogramms.

Erläuterungen findest du auch in der AVR-Studio-Hilfe: 
Assembler->Directives

MfG Spess

von Moschder (Gast)


Lesenswert?

wenn ich nun an der ersten möglichen Speicherstelle mit meinem Code 
beginnen will, wie muß dann dir org anweisung lauten? Und wann macht es 
sinn eben nicht an der ersten Stelle zu beginnen?

Gruß
Moschder

von 6641 (Gast)


Lesenswert?

Wo man die Includes einfuegt haengt natuerlich sehr mit deren Inhalt 
zusammen. Der ASM ist ein Einpass Assembler. Daher kann man nichts 
baruchen was nicht voerher deklariert wurde. Wenn man nun library 
funktionalitaet zur Verfuegung stellen will, die spaeter gebraucht 
werden kann, dann fuegt man die oben ein, zB HexToByte, ByteToHex, Einen 
generischen Algorithmus, der vorher parametrisiert wird, kommt am Ende 
hin. Ich hab das main() jeweils unten.

von spess53 (Gast)


Lesenswert?

Hi

Der Assembler beginnt automatisch an der Speicherstelle 0. Dort muss der 
Sprung zum Anfang des Programms stehen. Der µC fängt nämlich nach jedem 
Reset an dieser Stelle an. Zu deiner Frage: '.org 0'. Schadet zwar 
nicht, ist aber unnötig.

MfG Spess

von 6641 (Gast)


Lesenswert?

Ein Bootloader beginnt zB nicht an der Stelle Null. Mit ORG kann man 
auch Variablen an eine Adresse setzen.  Sei das nun im RAM oder im 
EEPROM.

von spess53 (Gast)


Lesenswert?

Hi

>Wo man die Includes einfuegt haengt natuerlich sehr mit deren Inhalt
>zusammen. Der ASM ist ein Einpass Assembler. Daher kann man nichts
>baruchen was nicht voerher deklariert wurde. Wenn man nun library...

Über diese Brücke würde ich nicht gehen. Man kann problemlos auf 
Unterprogramme zugreifen, die hinter dem Aufruf stehen. Der 
AVR-Assembler (mit Sicherheit KEIN Ein-Pass-Assembler) benötigt keine 
Forward-Deklarationen. Und eine main() kennt er schon gar nicht. Ich 
glaube da bringst du etwas durcheinander.

MfG Spess

von Michael U. (amiga)


Lesenswert?

Hallo,

@6641:
>Der ASM ist ein Einpass Assembler.

Das bezweifle ich.

Ansonsten:
Der Assembler beginnt mit Programmspeicheradresse 0, wenn man ihm nicht 
mit .org was anderes sagt.

Der AVR beginnt beim Reset an Adresse 0. Dort steht üblicherweise ein 
Sprung zum eigentliche Programmbeginn. Das ist sinnvoll, weil danach 
unmittelbar die IRQ-Vektoren kommen und wenn die nutzen will, muß man 
sie sozusagen freilassen.

Eine (bei AVR) für mich allgemeingültige Methode:
1
; ATiny2313
2
3
; 09.03.2008 M'Soft Berlin
4
5
.include "tn2313def.inc"  ; erstmal die Prozessordefinition includen
6
7
.include "Definitionen.inc" ; jetzt meine Definitionen, Konstanten, Registernamen, Bitnamen usw. usw
8
9
;**** Verktor-Liste ********
10
11
.CSEG ; Begin Codesegment, Adresse ist 0 für den Assembler, weil nichts anderes angegebn
12
  rjmp    reset ; Sprung zum Programmbegin
13
14
.org  OVF1addr     ; benutzter IRQ-Vector
15
  rjmp  irq_overflow
16
17
.org  OC0Aaddr
18
  rjmp  irq_timer
19
20
;***** Programm-Beginn ******
21
22
;****************************
23
;  Initialisierungsroutine
24
;****************************
25
26
; Hardware initialisieren
27
28
.org  INT_VECTORS_SIZE ; ist in allen AVR-Definitionen definiert und zeigt auf die erste Adresse hinter der IRQ-Vectorliste
29
30
reset:
31
    ldi  TEMP_0,low(RAMEND) ; Stack an das interne Ram-Ende
32
    out  SPL,TEMP_0
33
34
; Port B ********************* nur als Beispiel!!!
35
36
    ldi   TEMP_0,(1<<KEY_MODE)|(1<<KEY_CAL) ; PullUp ein Tasten
37
   out     PORTB,TEMP_0                
38
    ldi    TEMP_0,(1<<LCD_RS)|(1<<LCD_E)|(1<<LCD_D4)|(1<<LCD_D5)|(1<<LCD_D6)|(1<<LCD_D7)
39
    out     DDRB,TEMP_0  ; LCD Ausgang
40
41
usw. usw.
42
43
;************************ 
44
; Software initialisieren
45
46
   clr  MENU
47
   clr  FLAGS
48
49
usw. usw
50
51
   sei
52
53
;************************
54
;  Main-Loop
55
;************************
56
main:          
57
   tst  KEY_CODE ; Taste?
58
   breq  main_end ; nein
59
60
usw. usw
61
62
;************************
63
;  Main-End
64
;************************
65
66
.include "IRQ.inc"
67
.include "LCD.inc"
68
.include "Subroutinen.inc"
69
.include "Funktionen.inc"
70
71
.include "Tabellen.inc"

Die leere Struktur benutze ich eigentlich für jedes Programm, die 
Reihenfolge der Includes ist egal, die Tabellen (Texte im Flash usw) 
lasse ich an Ende.

Es kann nur passieren, daß beim Assemblieren die Meckermeldung kommt, 
daß die Sprungweite eines RCALL überschritten wurde, Erste Lösung ist 
dann für mich, die Reihenfolge der Includes umzusortieren, der Abstand 
hängt ja nur davon ab, welche Routine aus welchem Includen was aufruft. 
Oft reicht das schon oder umsortieren der Funktionen innerhalb der 
Includes hilft.

Das sind dann alles nur reine Copy-Paste mit etwas überlegung, das 
kostet nichtmal Zeit.

Vielleicht hilft das ja jemandem.

Gruß aus Berlin
Michael

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.