50 Programmiertricks aus dem Ideenschrank

Martin Backschat, Michael Bernards, Arnd Beißner

Assembler

TIP 1

Bei vielen komplizierten Funktionen sollten Sie sich überlegen, diese zu berechnen und die Ergebnisse als Tabellen anzulegen. Ein Beispiel ist der Sinus. Hier empfiehlt es sich, anstatt aufwendigem Rechnen, den Wert schnell aus einer Tabelle auszulesen.

TIP 2

Stack reinigen: Benutzen Sie statt ADDA.L #Bytes,A7 (14,6) bei bis zu 8 Byte ADDQ.L #Bytes,A7 (8,2) sonst LEA Bytes(A7),A7 (8,4)

TIP 3

Umrechnen vom Intel- ins Motorola-Format. Wort steht in Dß:

ROR.W#8,D0.

Langwort steht in D0:

ROR.W#8,D0,SWAP D0, ROR.W#8 D0.

TIP 4

Die PC-Relative Adressierung ist 20 bis 30 Prozent schneller und um den selben Faktor kompakter als die direkte Adressierung.

TIP 5

Da man die PC-Relative Addressierung nicht im Zieloperanden verwenden kann, laden Sie bei vielen Zugriffen die Adresse in ein Adressregister und adressieren relativ.

TIP 6

PEA Adresse (20,6) 

ist schneller als MOVE #Adresse,-(A7) (24,6).

TIP 7

LEA Adresse, An (12,6)

ist schneller als MOVEA #Adresse,An (20,6).

TIP 8

Bei Sprüngen größer 32 KByte BRA und BSR statt JMP und JSR verwenden. Bei sehr kurzen Sprüngen (kleiner 128 Byte) BRA.S und BSR.S einsetzen.

TIP 9

Die Datenübergabe an Unterprogramme führen Sie schneller über Register statt über den Stack durch.

TIP 10

CMPI #0,<ea> ersetzen durch TST <ea>.

TIP 11

Datenbereiche, die nicht initialisiert werden müssen ( z.B. Sektorpuffer), sollten ins BSS-Segment gelegt werden. Dort benötigen sie zwar genausoviel Speicher, aber auf Diskette sind die Programme kürzer, lassen sich deshalb schneller laden und sparen Platz.

TIP 12

Die schnellste Speicherverschiebe-Routine bedient sich des MOVEM-Befehls. Bei 14 Registern lassen sich mit zwei Befehlen in 244 Taktzyklen so 56 Bytes verschieben. Die normale Routine benötigt dafür mehr als 400 Taktzyklen.

TIP 13

Vergleiche mit Konstanten kleiner gleich 8 Byte sind schneller mit einem SUBQ-Befehl (4,2) als mit CMPI (8,4).

TIP 14

Zahlen zwischen -128 und +127 lassen sich mit einem MOVEQ dreimal schneller in ein Datenregister laden als mit MOVE.

TIP 15

Um einen Wert zu einem Adreßregister zu zählen, verwenden Sie statt

add.l/sub.l #,Ax

für kleine Werte

addq.l/subq.l #,Ax

und für größere

lea.l #(Ax),Ax

TIP 16

Bei Aufrufen des TOS reicht es vollkommen aus, sich die Register D0,D1,A0,A1 zu merken. Der Rückgabewert wird immer in DO übergeben. Einen Fehler testen Sie folgendermaßen:

trap #.. ;TOS-Call
tst.l d0 
bmi AnError

TIP 17

Zum Löschen von Datenregistern verwenden Sie den Befehl

moveq #0,Dx 

statt clr.l Dx

GFA-Basic 3.0

TIP 18

Im Interpreter sollten Sie FOR-NEXT-Schleifen vermeiden und durch REPEAT-UNTIL oder WHILE-WEND-Konstrukte ersetzen. FOR-NEXT-Schleifen arbeitet der Interpreter langsamer ab, als die anderen Schleifenarten. Für den Compiler ist dies allerdings ohne Bedeutung.

TIP 19

Integer-Variablen sollten Sie immer benutzen, wenn keine Fließkommazahlen nötig sind. Es ist unwichtig, ob Wort-Integer (Suffix &) oder Langwort-Integer (Suffix %) verwendet werden, da kaum ein Unterschied besteht.

TIP 20

Die neue Version von GFA-Basic, 3.0, bietet spezielle Arithmetikbefehle für Integerzahlen (SUB,ADD,etc.). Diese sind erheblich schneller als die normalen Operanden (+,-,etc.).

TIP 21

Zum Speichern und Laden von ASCII—Texten empfehlen sich die Befehle STORE und RECALL. Sie sind um ein Vielfaches schneller als die Befehle PRINT# und INPUT#.

TIP 22

In der neuen Version des GFA-Basic gibt es zum schnellen Zeichnen von Bezierkurven den »Curve«-Befehl. Dieser nimmt vier Punktkoordinaten als Parameter.
Für die anderen Sprachen finden Sie einen schnellen Algorithmus von Bezierkurven im Expertenforum der kommenden Ausgabe.

GEMDOS, BIOS, XBIOS, GEM

TIP 23

Statt eine Datei in kleinen Stücken zu laden, nehmen Sie größere Blöcke, die Sie im Speicher trennen, denn Dateizugriffe sind allgemein sehr langsam.

TIP 24

Wenn in eine Datei häufiger geschrieben oder aus ihr gelesen werden muß (z.B. Adressverwaltung) ist es besser, die Datei zu Beginn größer zu dimensionieren, um dann in die vorhandene Datei zu schreiben. Das GEMDOS vor der TOS-Version 1.4 sucht sehr lange nach freien Sektoren.

TIP 25

Wenn bei einem Fenster—Redraw Slider oder Pfeile betätigt werden, zeichnet man nicht das ganze Fenster neu, sondern verschiebt es mit der Copy-Raster—Funktion und zeichnet dann nur die neuerscheinenden Bereiche. Bei Fenstern, die viele Objekte enthalten, ist der Geschwindigkeitsgewinn beträchtlich.

TIP 26

Beim Lesen und Schreiben von Sektoren (Rwabs, Floprd, Flopwr) sparen Sie Zeit indem Sie darauf achten, daß die Pufferadresse gerade ist.

TIP 27

Die Zeichenausgabe unter BIOS (Bconout) ist erheblich schneller als die entsprechenden Routinen des GEMDOS (Cconout). Nachteil: Die BIOS—Routinen lassen sich nicht auf andere Geräte umleiten und erfordern deshalb eventuell mehr Programmieraufwand.

TIP 28

Gibt man Zeichenketten auf den Bildschirm aus, die ASCII-Code 0 enthalten, benutzt man Fwrite mit Handle 1, da Cconws bei dem Auftreten von ASCII 0 abbricht.

TIP 29

Um die schnellstmöglichen Grafikroutinen für die Grundfunktionen wie Linien, Kreise, Füllen, Speicherverschiebungen und Textausgaben zu nutzen, greifen Sie auf die Line—A-Routinen des Betriebsystems zu, statt über GDOS und dem VDI zu arbeiten. Bibliotheken zum Ansprechen der Routinen sollten für jede Sprache zur Verfügung stehen.

ST-Basic

TIP 30

Am besten eine andere Sprache benutzen.

C

TIP 31

Um eine Struktur mit vielen Flags kleiner und handlicher zu gestalten, bietet es sich an, mit Bitfeldern zu arbeiten.

struct beispiel {
    char flag1,flag2,flag3;
    int color;
/* Werte 0-7 */ }; 

kann auch als

struct beispiel 
{
    unsigned int flag1 : 1;
                 flag2 : 1; 
                 flag3 : 1;
    unsigned int color : 3;
};

geschrieben werden und belegt nur noch 2 statt vorher 5 Byte.

TIP 32

Variablen, Strukturen, Zeiger etc., die gedanklich zusammengehören, können Sie der Übersicht halber als Struktur zusammenfassen. Dies hat einen Riesenvorteil: Das Kopieren aller Komponenten an eine andere Stelle geschieht mit einem Befehl und wird vom Compiler höchst optimiert:

int datensatz_nr; 
char *datensatz_text; 
long seriennummer; 

fassen Sie zusammen zu:

struct Datensatz
{   int datensatz_nr;
    char *datensatz_text;
    long seriennummer}; 

und können nun diese Struktur mit «datensatz2 = datensatz1» kopieren.

TIP 33

Wenn nicht unbedingt nötigt, auf PRINTF, SCANF und deren Verwandten verzichten, da die meisten Compiler bei diesen Routinen eine große Library in das Programm binden und die Routinen langsamer sind als die des TOS.

TIP 34

Bei einigen C-Compilern (z.B. Megamax 1.1) lohnt es sich, Bibliotheksroutinen, die zwar miteingebunden, aber nicht benötigt werden, durch Dummies zu ersetzen.

TIP 35

Verwendet man bei C die Standard-Dateiroutinen wie FOPEN, nimmt der Code um einiges an Umfang zu. Die Systemroutinen FOPEN etc. reichen oft aus.

TIP 36

Um bei einer Float—Integer-Wandlung den Rundungsfehler zu minimieren, gibt es einen Trick: »Aint = (int) (Afloat+0.5)«

TIP 37

In Kopierschleifen ersetzen Sic die Array Index-Adressierung (carray[i] = darray[j]) durch die direkte Adressierung (*carray++ = *darray++).

TIP 38

Um einen größeren Speicherblock in C zu verschieben, bietet es sich an, Strukturen zu kopieren. Dabei optimiert der C-Compiler automatisch. 1000*4 Byte lassen sich etwa folgendermaßen kopieren:

struct BYTE4000
{ long long4[1000]	};
*src_block,*dest_block; 
src_block =...; 
dest_block = ...;
*dest_block = *src_block;

TIP 39

Bei zeitkritischen Routinen benutzen Sie Registervariable. Hierbei werden die C-Variablen in den Prozessorregistem abgelegt. Beispiel:

register char *adr_pointer; 
register long long_value;

TIP 40

Um Kopierschleifen mit komplizierten Arrays zu optimieren, kopieren Sie statt mit den Arrays mit Zeigern auf diese. Beispiel:

src_ptr= &src_array[i][0]; 
dest_ptr = &dest_array[j][0];
*src_ptr++ =*dest_ptr++;

TIP 41

Bei vielen Zugriffen auf eine Datei verwenden Sie die gepufferten Dateifunktionen »fopen«, »fclose«, »fseek«, »fread«, »fwrite« und »fflush« etc. Damit wird Ihre Datei im Speicher gepuffert. Die Puffergröße stellen Sie mit der Funktion »setbuf« ein.

TIP 42

Zum schnellen Datensortieren verwenden Sie die Bibliotheksroutine »qsort«. Sie basiert auf dem schnellen Quicksort-Algorithmus.

TIP 43

Der Multiplikationsbefehl »mulu« benötigt viel Zeit. Multiplikationen mit kleinen Werten optimieren Sie durch »add« und »lsl«. Beispiele:

D0 x 2: lsl.l  #1,d0 
D0 x 3: move.l d0,d1 
        add.l  d1,d1
        add.l  d1,d0 
D0 x 4: lsl.l  #2,d0 
D0 x 5: move.l d0,d1 
        lsl.l  #2,d1
add.l   d1,d0

TIP 44

Um auch ohne die langsamen Gleitkommazahlen schnell aber genau zu rechnen, teilen Sie ein Langwort (32 Bit) in zwei 16 Bit-Worte auf (Hi- und Lo-Wort). Das Hi-Wort deklarieren Sie dabei als Vorkomma— und das Lo-Wort als Nachkommawert. Zwei Zahlen (1.0 und 5.5) addieren Sie beispielsweise folgendermaßen:

move.l #$00010000,d0 ; 1.0 
add.l  #$00058000,d0 ; +5.5 

Runden können Sie die Zahl mit

add.l #$00008000,d0 ; +0.5 
clr.w d0
swap d0	; Vorkomma

TIP 45

Um eine Zahl durch eine Zweierpotenz zu dividieren, benutzen Sie die Bitschiebebefehle:

D0 / 2: lsr.l   #1,d0
D0 / 4: lsr.l   #2,d0
D0 / (2 ^ 17):  clr.w d0
swap d0
lsr.w 01, d0

TIP 46

Um Routinen im Supervisor auszuführen, eignet sich die XBIOS—Routine »Supexec(void *prgptr)«. Damit sparen Sie sich den lästigen Moduswechsel mit »Super(stack)« und Zeit.

TIP 47

Bei verschachtelten FOR-NEXT-Schleifen plazieren Sie die größte Schleife als die innerste Schleife.

TIP 48

Um die Geschwindigkeit bei Berechnungen zu beschleunigen, sperren Sie mit »or.w #$700,sr« in Assembler oder »IPL 6« in Omikron-Basic alle Interrupts.

TIP 49

In Omikron-Basic ist die Integer-Division vorzuziehen (»\« statt»/«). Diese teilt zwei Integerwerte extrem schnell.

TIP 50

Bestimmte Rechenfunktionen bewirken automatisch, daß die gesamte Berechnung mit Fließkommazahlen durchgeführt wird. Um in das Integer-Format zurückzukehren, verwenden Sie den Befehl CINT. Beispiel:

A=CINT (SQR(I))+J-I*3 

Ohne CINT würde die komplette Formel mit Fließkommazahlen berechnet und mehr Rechenzeit beanspruchen.



Aus: ST-Magazin 10 / 1989, Seite 20

Links

Copyright-Bestimmungen: siehe Über diese Seite