Hallo zusammen, ich hätte da mal einige Frage. Habe hier ein Programm
mit dem ich mich auseinender setzen muss jedoch verstehe ich nicht was
genau das codesegment ist und für was dieser in dem Programm genutzt
wird. CSEG AT 0 sagt mir auch nicht viel und was macht der Befehl Org
und warum wird die hexazahl 50h gewählt?
Danke im vorraus
;*****************************
; Segmentierung von Speicher *
;*****************************
stack_seg SEGMENT IDATA ;Deklaration Stack segment indirekt
adressierbarer, internes RAM zb Stack
code_seg SEGMENT CODE ;Deklaration Code Segment,
Programmspeicher ROM
;*****************************
;* Stack-Initialisierung *****
;*****************************
RSEG stack_seg ; RAM-Speicher wird ausgewählt unser Stack
init: DS 10 ; 10 Byte Stack wird reserviert, damit Daten
gesichert werden nach LIFO
CSEG AT 0 ; Anfangsadresse für Progstart ist 0, Absolutes
Codesegment für Programmstart bei 0
JMP main
org 0Bh ; Adresse für die ISR von Timer0 festlegen der
nachfolgende Code wird ab Adresse 0B im Programmspeicher abgelegt
JMP timer_0 ; Läuft Timer 0 ab, verzweigt der Controller
zur Adresse 0Bh zur Interruptbehandlungsroutine
org 50h ; Anfangsadresse/Einsprungstelle für die
BCD-Tabelle wird festgelegt
JMP bcd ; Tabelle an Adresse 50h
Hey danke für die Antwort.
also ist die 0Bh vordefiniert in dieser Tabelle
die 50h habe ich jedoch nicht gefunden und kann mir vil einer genau
erklären was genau cseg macht. Ich habe es so verstenden dass nachdem
cseg immer das Programm beginnt ist das so richtig?
Es gibt CSEG = CODE Segment = hier steht Programmcode, in Stein
gemeisselt. Dann DSEG = DATEN Segment = hier kommen Daten hin, hier kann
der Prozessor auch schreiben. Bei anderen Prozessoren findest du noch
SSEG = Stack, ESEG = Extra usw.
Die Segment Angaben helfen dem Linker/Locater, zueinander passende
Programmteile aus verschiedenen Modulen zu verheiraten.
Und was bedeutet das at bei cseg
Und ist es mit Absicht dass direkt drunter jmp Main steht ?
Warum steht da org 50h und direkt dahinter jmp bcd hat das einen
Zusammenhang ,
Jürgi schrieb:> Und was bedeutet das at bei cseg
At ist der Befehl, das Segment für Code ab der genannten Adresse
anzulegen.
Org heisst, das folgende Programm soll ab der genannten Adresse
gespeichert werden.
Da die meisten Prozessoren nach Reset an Adresse 0 starten, muss daher
das CSEG bei 0 beginnen und zwar mit dem Befehl, der per ORG an der
Adresse 0 assembliert wird.
Führt z.B. ein Interrupt laut Manual an die Adresse 00xy, so muss die
Interruptroutine logischerweise mit ORG 00xy vor dem ersten Befehl
programmiert werden und das innerhalb CSEG. Dann befördert der Linker
die Routine in den Programmspeicher an der Adresse 00xy.
Natürlich dürfen sich die Programme nicht ins Gehege kommen, der Code,
der ab 0 ausgeführt wird, darf z.B. nur bis vor die Adresse xy reichen,
sonst meldet das Assemblerprogramm einen Fehler.
Gruss Reinhard
Es wurde ja gesagt dass die ersten 50 Adressen vordefiniert sind heißt
das von 0 bis 49h sind die vordefinierten und die 50h ist die erste
freie Adresse ?
JÜRGI schrieb:> was sind jedoch die 50h?
Dort hat jemand den Teil bcd hin verlegt, weil der das praktikabel fand.
050h liegt kurz hinter den Interruptvektoren. Denn der 8051 hat mehrere
Interruptvektoren, nicht nur den 0Bh, die bis etwa in die Gegend um 40h
herum reichen. Die überspringt man, und läßt sie reserviert, wenn man
sonst genug Codespeicher hat. Man könnte die nicht benutzten
Interruptvektoren jedoch auch als normalen Codebereich verwenden, bspw.
wenn der Speicher mal voll wird, und man dringend noch ein paar Bytes
irgendwo zusammen kratzen muß.
Es kann sein, daß der Linker main noch vor bcd legt, oder eben dahinter,
je nach dem, wie groß beide Codesegmente sind.
Danke , eine letzte frage habe ich noch . Warum werden org und jmp
zusammen verwendet heißt es dass wenn ein interrupt kommt soll er an
diese Adresse springen . Aber was heißt für die bcd Tabelle jmp bcd und
org ?
Org = Origin legt fest, wo im aktuellen Segment der nun folgende Code
liegen soll. Jeder Interrupt hat einen speziellen Vektor, fängt an einer
vorgegebenen Adresse an. Diese Vektoren liegen i.A. sehr eng
beieinander, so dass zwischen zwei Vektoren nicht genug Platz ist für
den Code, der im Interrupt ausgeführt werden soll. Also ist der erste
Befehl meist ein Sprungbefehl zu der ersten "echten" Instruktion des
Interrupts.
Jürgi schrieb:> Warum werden org und jmp> zusammen verwendet
Muss ja nicht sein. Aber die Adressen, an die der Prozessor durch einen
Interrupt springt, folgen meist dicht aufeinander, daher muss ein
längeres Programm zur IRQ-Bearbeitung irgendwo anders stehen, und da
führt dann eben ein JMP hin (bzw. LJMP). Genausogut kann aber an der
IRQ-Service-Adresse ein RETI stehen, wenn dieser spezielle Interrupt
keine Bearbeitung braucht.
Die 50H, nach denen du schon mehrfach gefragt hast, sind auch nicht in
Stein gemeisselt, sondern von der Hardware abhängig, je nach Zahl der
Interruptquellen, beim 80535 gibt es z.B. eine IRQ 6BH. Da wäre der
nächste freie Speicherplatz also nicht 50H, sondern 70H. Ich habe immer
gleich 100H als ersten freien Programmspeicher gesetzt.
Gruss Reinhard
Danke Reinhardt ,
Wenn ein interrupt kommt wird das Programm also unterbrochen und springt
in die interrupt Routine die an der vordefinierten Adresse 0bh steht .
Die bcd Tabelle wurde vom Nutzer an die Adresse 50h gespeichert.
Habe ich das richtig verstanden ?
JÜRGI schrieb:> danke für die antwort, was sind jedoch die 50h?
Du scheinst ein bissel schwer in die Gänge zu kommen, gelle?
also:
Es gibt unterschiedliche Rechnerarchitekturen, gelle?
Bei manchen sind Daten (sowohl konstante als auch variable) und der
Befehlscode im gleichen Adreßraum angeordnet. Bei anderen jedoch nicht.
Es gibt sogar Architekturen, wo der Code, die variablen Daten und die
In- und Out- Verbindungen zur Außenwelt in jeweils unterschiedlichen
Adreßräumen angeordnet sind.
Hier haben wir es nur mit 2 Adreßräumen zu tun: dem Code im
ROM/EPROM/FLASHROM und den variablen Daten im RAM. Jeder Adreßraum hat
seine Adressen und was im RAM auf Adresse 50h steht, ist dem ROM auf
seiner Adresse 50h völlig wurscht.
Also gibt es im Assembler sogenannte Pseudobefehle oder
Organisationsanweisungen, die keinem Maschinencode entsprechen, sondern
dem Assembler sagen, was der Programmierer in den nächsten Zeilen
eigentlich meint.
Oft trifft man sowas an:
SEG CODE
oder
SEG DATA
was dem Assembler sagt, daß alles, was danach kommt, in den Code (bzw.
ROM) kommt oder eben in den Datenbereich, also den RAM.
Klar bisher?
Nun will man als Assemblerprogrammierer ja gelegentlich irgendetwas an
genau eine bestimmte Stelle im jeweiligen Segment plazieren. Dazu dient
dann
ORG 50h
womit alles was man danach schreibt, ab der Adresse 50h plaziert wird.
Zumeist ist es so, daß der Assembler aus purer Menschenfreundlichkeit
bei seinem Start die ORG-Zähler für alle Segmente, die es so geben mag,
auf 0 setzt. Deshalb landet der allererste Befehl nach dem allerersten
SEG CODE auf Null, aber man sollte sich darauf nicht verlassen und
lieber selbst nach einer Segmentanweisung eine ORG anweisung schreiben,
WENN (!!!) man das Folgende auf einer bestimmten Adresse haben will.
Es geht nämlich auch verschachtelt:
SEG RAM
ORG 15
MyLovelyByte: DS 1 ;reservierung eines Bytes im RAM
SEG Code
ORG 0
JMP MyStartup
Manifest:
DEFB "My lovely Program",0
SEG RAM
MyFollowingByte: DS 1 ; noch ein Byte resevieren
SEG Code
MyStartup:
.. hier nun Befehle nach deinem Gusto..
Dabei landen MyLovelyByte auf Adresse 15 im RAM, MyFollowingByte auf
Adresse 16 im RAM und MyStartup landet direkt hinter dem Manifest, also
hinter dessen abschließendem Nullbyte.
hast du's nun?
W.S.
Hallo,
zum tieferen Verständnis: bei jedem Prozessor kann man jeden Platz im
Programmspeicher per JMP/LJMP erreichen (sonst bräuchte man den Speicher
ja nicht einbauen oder anschliessen), also kann ein bestimmter
Programmcode an jeder beliebigen Adresse stehen, mit einigen Ausnahmen:
Nach einem Reset wird an eine bestimmte Stelle gesprungen, weit
verbreitet dafür ist die Adresse 0 - das nennt man dann Reset-Vektor.
Der muss fest sein, denn von irgendetwas muss man ausgehen können,
sozusagen der Fixpunkt im Code-Universum. Also ist das für den
Programmierer der Punkt an dem sein Programm startet.
Bei den meisten heutigen Prozessoren sind auch die Interruptvektoren
festgelegt, d.h. beim Empfang eines Bytes im UART springt der Prozessor
an eine bestimmte Adresse, die man aus dem Manual erfährt. Also muss der
Code zur Bearbeitung des Interrupts an dieser Adresse anfangen, aber
weil das meistens eine ganze Tabelle von Adressen ist, reicht dort der
Platz nicht für viel mehr als einen Sprung dahin, wo die
Interruptroutine wirklich steht.
Früher waren die Interruptadressen oft noch programmierbar (Z80), aber
das ändert prinzipiell nichts und bringt kaum Vorteile (dafür viele
Fehlermöglichkeiten), deshalb sind sie in moderneren Architekturen
einfach fix.
Der Linker schafft Codeteile dahin, wo noch keine sind, meistens in der
Reihenfolge wie sie im Makefile aufgeführt sind, daher muss man im bei
solchen fest addressierten Codeabschnitten mitteilen, dass er sie
gefälligst an einer bestimmten Adresse unterzubringen hat - das genau
ist die ORG-Anweisung.
Gruss Reinhard