Guten Morgen!
Ich kenne mich in der Makroprogrammierung nicht aus deshalb hoffe hier
auf Unterstützung.
Ich programmier 8051 derivate d.h. wenn jemand Macros Bsp. in AVR
postet werd ichs wohl nicht verstehen.
Ich wollte die Steuerung der Cursorpositon am LCD in Assembler
vereinfachen und da dachte ich an Macros.
Ich würde es gerne in dieser form haben wollen: cursor(x,y).
Ich hab mich zwar schon etwas belesen aber ich komm damit nicht klar
(Macro anlegen, parameterübergabe usw.).
Das nächste problem ist das ich es gerne in andere Module verwenden
möchte z.B. über PUBLIC bekannt geben.
Kann mir jemand ganz einfach erklären wie ich so was realisieren kann?
Worauf man achten soll usw.
Gruss Norad
sowas sollte man nicht unbedingt als Makro programmieren, da es dann bei
jedem Aufruf in der vollen Grösse mit verschiedenen Parametern ins
Programm eingebunden wird. D.h., wenn du in deinem Programm 10x
gotoxy(x,y) verwendest, steht auch der Code dafür 10mal in nur leicht
abgewandelter Form in deinem Speicher. Das ist nicht effektiv und kann
ganz schnell dazu führen, dass dir der Programmspeicher ausgeht.
Dafür benutzt man Funktionen.
Wie machst du das nun?
Erstmal schreibst du ein Unterprogramm, das wird mit call aufgerufen
und mit ret beendet. Bleibt die Frage der Parameterübergabe, dafür
gibts etliche Varianten, alle mit Vor- und Nachteilen.
-globale Variablen (feste Speicherplätze), meist von Anfängern benutzt,
kaum Konfliktpotential, aber nicht sehr effektiv in der RAM-Nutzung
-in deinem Fall mit nur 2 Byte in A und B
-in den Registern, evtl. mit Registerbankwechsel
-über den Stack (da muss man ziemlich aufpassen, aber otimale
Ramnutzung)
-einen Speicherbereich, adressiert über den DPTR
Mit 8051-ASsemblerbeispielen kann ich dir nicht dienen, das ist zu
lange her und würde wohl mehr Fehler als nutzbare Infos enthalten :-)
@crazy horse
Vielen Dank für deine Infos!
Also so vorteilhaft scheinen Makros doch nicht zusein, da bläst man
seinen Code unnötig auf.
Die Idee werd ich mal ganz schnell wieder verwerfen und werde mal das
mit den Registern A und B versuchen oder über Stack.
Nochmal vielen Dank
Gruß Norad
Ich würde an deiner Stelle lieber mit den Registern arbeiten. Zumindest
A wirst du ja im Unterprogramm wieder benötigen.
mov R0, #10 //x-pos
mov R1, #2 //y-pos
acall cursor
moin moin,
;-------------------------
mov R0, #10 //x-pos
mov R1, #2 //y-pos
acall cursor
;-------------------------
das dann bitte aber auch als macro, bin nämlich schreibfaul.
Je nach verwendetem Assembler sieht das dann so aus:
PosXY macro x,y //die Definition
mov R0, #x //x-pos
mov R1, #y //y-pos
acall cursor //auf Pos stellen
EndM
;--------------------------
; Nutzung als
PosXY 1,10
Bei festen POS-Angaben ist das macro vorteilhaft. Welche Register
genommen werden ist in der Macrodefinition und im UP Cursor festgelegt.
Soll da was geändert werden, braucht nicht der ganze Quelltext
durchgesucht werden.
Ausserdem wird die Quelle übersichtlicher, bei mir stecken ganze
Berechnungen in Macros. Sieht dann aus wie Hochsprache.
Mit Gruß
Pieter
Hallo Pieter!
Genau sowas brauch ich aber bläst das nicht den code auf oder belegt
den Speicher unötig wenn mans zu oft aufruft? sowie crazy horse
meinte.
Oder stimmt dass nicht? Wenn ichs richtig begriffen habe macht ein
Macro so etwas wie ne Textersetzung.
gruß norad
Das Makro von Pieter erleichtert dir einfach nur die Schreibarbeit.
Alles, was in dem Makro definiert wird, müsstest du sowieso im
Programmcode schreiben.
Würdest du jetzt das acall cursor durch die Funktion selbst ersetzen,
würde das natürlich den Programmcode unnötig aufblähen.
Es erhöht dabei auch die Übersichtlichkeit.
Wie crazy horse schon schrieb, wird das, was in dem Makro steht (vom
Compiler) in den Quellcode kopiert. Du sparst also Tipparbeit...
moin moin,
im laufe der Zeit habe ich eine Macro.INC-Datei zusammengeschrieben.
Da gibt es u.a:
;--------------------------------------
;Compare And Jump Equal
CJE MACRO Register, Value, Target
CJNE Register, Value, @@1
JMP Target
@@1: ENDM
;--------------------------------------
;Compare And Jump Less
CJL MACRO Register, Value, Target
CJNE Register, Value, @@1
@@1: JC Target
ENDM
;--------------------------------------
;Compare And Jump Less Or Equal
CJLE MACRO Register, Value, Target
CJNE Register, Value, @@1
SETB C
@@1: JC Target
ENDM
;--------------------------------------
;Compare And Jump Greater
CJG MACRO Register, Value, Target
CJNE Register, Value, @@1
SETB C
JNC Target
@@1: ENDM
;--------------------------------------
;Compare And Jump Greater Or Equal
CJGE MACRO Register, Value, Target
CJNE Register, Value, @@1
@@1: JNC Target
ENDM
;--------------------------------------
als Ergänzug zum OP-Code die "fehlenden" bedingten Sprünge. Diese
können nicht als Unterprogramm verwendet werden.
Der Syntac ist mit CJNE identisch.
Es geht bei Macros nicht vorrangig darum Code zu sparen, sondern um die
Lesbarkeit einer Quelle.
Mit Gruß
Pieter
@Pieter
Kann man ein Makro auch mit Public für andere Module sichtbar machen
d.h. kann man ein Makro auch in einem anderem Modul nutzen?
Hast Du dafür vielleicht ein Beispiel?