Ein ganz kurzes Accessory

“Wäre doch gelacht, wenn ich da nicht noch ein paar Bytes rauskitzeln könnte”, dachte ich mir, als ich mir vornahm, ein bis aufs letzte Byte optimiertes Accessorys zu schreiben, das mir den noch verbleibenden freien Speicherplatz anzeigen sollte.

Irgendwo gab's mal ein RAM-FREE-Programm, das auch nur den freien Restspeicher anzeigte, jedoch eine Länge von 2560 Bytes aufwies und führende Nullen nicht unterdrückte. Das geht besser, dachte ich. Mit ca. 600 Bytes war die erste Version lauffähig, aber bei weitem noch nicht fertig; nun fing die Kleinarbeit erst an:

Datenregister, wenn möglich, mit MOVEQ, Adreßregister mit LEA füllen, Unterroutinen so schieben, daß Kurzadressierung möglich wird (BSRS). Quellen PC-relativ adressieren und Ziele adreßregisterindirekt ansprechen, dabei möglichst auf nicht veränderte Register zurückgreifen. Diese und einige andere auch schon in Ausgabe 7/8 1989 im Artikel Assembler-Optimierung gemachte Möglichkeiten führten dann nach langen Sitzungen zu dem Programm, was Sie unten sehen können. Hinzu kommt die Ausnutzung des Umstandes, daß nicht alle Register bei Systemaufrufen verändert werden. Aber Vorsicht, das gleicht einem Tanz auf dem flochseil und muß bei neueren TOS-Versionen nicht so bleiben.

Interessant dürfte jedoch die Art der Initialisierung sein, wie der Aufruf des AES automatisch die drei Register D7/A5/A6 mit Werten belegt, so daß die Parameter für CONTRL auf effektiv(st)e Weise übergeben werden können. Die Variante mit MOVEP (siehe 1.) zieht hierbei den Kürzeren, funktioniert leider auch nicht auf dem sonst recht guten GFA-Assembler, der hierbei falsche Adreß-Offsets berechnet. Na, und die Dezimalroutine kann sich auch sehen lassen. Sie können sie für eigene Projekte weiterverwenden.

Literatur:

Assembleroptimierung, ST-Computer 7/8 1989

M68000-Familie, W. Hilf / A. Nausch, TeWi Verlag, ISBN 3-921803-16-0

; ******************************
; Ein ganz kurzes Accessory 
; 7/89 Jürgen Stessun 
; (c) MAXON Computer GmbH
; zeigt freien Speicherplatz an 
; ******************************
; Initialisierungsteil fürs ACC 
; ******************************
        lea     STACK(pc),sp ; der Stapel für's ACC 
        bsr.s   FILA6        ; a6 und a5 =CONTRL, d7=1
        move.w  #10,(a5)+    ; 10 Opcode Appl_Init
        move.l  d7,(a5)+     ; 0*Intin 1*Intout (d7=1) 
        clr.w   (a5)+        ; 0*Addrin
        bsr.s   AES          ; AES-Aufruf, Register setzen
        move.w  INTOUT(pc),APPID-CONTRL(a6) ; Appl.-Nummer merken 
        move.w  #35,(a5)+    ; 35 Menu_Register
        move.w  d7,(a5)+     ; 1*Intin(d7=1)
        move.w  d7,(a5)+     ; 1*Intout
        move.w  d7,(a5)+     ; 1*Addrin
        move.w  APPID(pc),INTIN-CONTRL(a6)  ; Applikationsnummer 
        move.l  #ACCNAME,ADDRIN-CONTRL(a6)  ; der ACC-Name 
        bsr.s   AES          ; AES aufrufen
        move.w  INTOUT(pc),ACCID-CONTRL(a6) ; die ACC-Nummer

LOOP:   bsr.s   MEVENT       ; auf Ereignis warten
        cmpi.w  #40,MSGBUFF-CONTRL(a6)      ; ACC Open?
        bne.s   LOOP         ; nein, weiter warten
        move.w  MSGBUFF+8(pc),d0            ; die ACC-Nummer 
        cmp.w   ACCID(pc),d0 ; bin ich gemeint? 
        bne.s   LOOP         ; nein, weiter warten 
        bsr.s   MAIN         ; ja, Hauptroutine abarbeiten
        bra.s   LOOP         ; und danach wieder warten

MEVENT: move.w  #23,(a5)+    ; 23 Evnt_Mesag
        move.l  d1,(a5)+     ; 0*Intin 1*Intout (d7=1)
        move.w  d7,(a5)+     ; 1*Addrin
        move.l  #MSGBUFF,ADDRIN-CONTRL(a6)  ; Message-Puffer

; ******************************
; AES aufrufen 
; ******************************
AES:    move.l  #AESPB,d1    ; Zeiger auf Adressliste
        clr.w   (a5)+        ; 0*Addrout
        move.w  #$c8,d0      ; Wert für AES
        trap    #2           ; aufrufen
FILA6:  lea     CONTRL(pc),a6 ; Zeiger für A6
        movea.l a6,a5        ; und A5
        moveq.l #1,d7        ; d7 auf 1 setzen
        rts                  ; fertig mit AES
; ***************************
; Der eigentliche Aktionsteil 
; ***************************
MAIN:   moveq.l #-1,d0       ; Restspeicher erfragen
        move.l  d0,-(sp)     ; -1.L auf Stack
        move.w  #$48,-(sp)   ; MALLOC
        trap    #1           ; Gemdos
        addq.l  #6,sp        ; in D0 Restspeicher
        lea     NUMMER(pc),a4 ; Stringadresse in Alert

PRLONG: bsr.s   LONGNUM      ; in Dezimal wandeln
        move.l  #ALTEXT,ADDRIN-CONTRL(a6) ; Text für Alarmbox

ALERT:  move.w  #52,(a5)+    ; 52 Form Alert
        move.w  d7,(a5)+     ; 1*Intin(d7=l)
        move.w  d7,(a5)+     ; 1*Intout
        move.w  d7,(a5)+     ; 1*Addrin
        move.w  d7,INTIN-CONTRL(a6) ; Default Button = 1
        bra.s   AES

; ******************************
; Die Dezimal-Umwandlungsroutine 
; ******************************

LONGNUM: moveq.l #7,d4       ; insgesamt 7 Stellen
         move.l  #1000,d1    ; zuerst 4-stellig 
         moveq.l #(' '-'0'),d2 ; Space erlaubt
         divu.w  d1,d0       ; durch 1000
         bsr.s   D4TODEZ     ; umwandeln
         swap.w  d0          ; Rest in d0.w
         moveq.l #100,d1     ; dann 3-stellig

D4TODEZ: move.w  d0,d3       ; Zahl retten
W1:      ext.l   d3          ; auf Lang erweitern
         subq.w  #1,d4       ; schon letzte Ziffer?
         bne.s   W2          ; nein
         clr.w   d2          ; sonst kein Space erlaubt
W2:      divu.w  d1,d3       ; Rest durch Teiler
         beq.s   DEZPR1      ; ergab schon 0
         clr.w   d2          ; kein Space erlaubt
DEZPR1:  add.b   d2,d3       ; Offset zu Space addieren
         addi.b  #'0',d3     ; Offset für ASCII
         move.b  d3,(a4)+    ; ablegen in String
         swap.w  d3          ; Rest der Division
         divu.w  #10,d1      ; nächster Teiler
         bne.s   W1          ; wenn ungleich 0
         rts                 ; sonst fertig

         .DATA

ACCNAME: .DC.b '  Memory',0 ; 2 Spaces vor 'Me...'
ALTEXT:  .DC.b '[0][Memory:'
NUMMER:  .DC.b '        Bytes ' ; 8 Spaces vor 'By...'
         .DC.b '][Ok]',0 
         .EVEN
AESPB:   .DC.l CONTRL,GLOBAL,INTIN,INTOUT,ADDRIN,ADDROUT

         .BSS
APPID:   .DS.w 1    ; die Applikationsnummer
ACCID:   .DS.w 1    ; die ACC-Nummer
MSGBUFF: .DS.b 16   ; der Nachrichtenpuffer

CONTRL:  .DS.w 1    ; Opcode der AES-Funktion
         .DS.w 1    ; Anzahl der Intin-Einträge
         .DS.w 1    ; Anzahl der Intout-Ausgaben
         .DS.w 1    ; Anzahl der Addrin-Einträge
         .DS.w 1    ; Anzahl der Addrout-Ausgaben
GLOBAL:  .DS.w 15
INTIN:   .DS.w 2    ; Wort-Eingaben
INTOUT:  .DS.w 2    ; Wort-Ausgaben
ADDRIN:  .DS.1 2    ; Adreß-Eingaben
ADDROUT: .DS.l 2    ; Adreß-Ausgaben
         .DS.b 100  ; Platz für Stapel
STACK:
.END
a$=SPACE$(320) 
adr%=VARPTR(a$)
RESTORE daten 
CLR pruef%
FOR n%=0 TO 79 
    READ b$
    wert%=VAL("&H"+b$)
    LPOKE adr%+4*n%,wert%
    pruef%=pruef% XOR (wert%)
NEXT n%
IF pruef%<>&H73DF00B4
    ALERT 1," Daten nicht korrekt | Bitte überprüfen",1,"OK",dummy%
ELSE
    BSAVE "MEMORY.ACC",adr%,318 
    ALERT 1," Alles Ok ",1,"Ende",dummy% 
ENDIF 
EDIT 
daten:
DATA 601A0000,D40000,400000,B80000,0,0,0,4FFA01CA,61663AFC
DATA A2AC7,425D614E,3D7A0142,FFEC3AFC,233AC7,3AC73AC7
DATA 3D7A00F2,282D7C,D4,30612E,3D7A0122,FFEE6116,C6E0028 
DATA FFF066F6,303A00DE,B07A00D0,66EC612A,60E83AFC,172AC7 
DATA 3AC72D7C,118,30223C,FC,425D303C,C84E42,4DFA00BA,2A4E7E01 
DATA 4E7570FF,2F003F3C,484E41,5C8F49FA,646118,2D7C0000,DD0030
DATA 3AFC0034,3AC73AC7,3AC73D47,2860BE,7807223C,3E8,74F080C1
DATA 61044840,72643600,48C35344,66024242,86C16702,4242D602 
DATA 6030030,18C34843,82FC000A,66E24E75,20204D65,6D6F7279,5B305D 
DATA 5B4D656D,6F72793A,20202020,20202020,42797465,73205D5B 
DATA 4F6B5D00,128,132,150,154,158,160,28,30082A72,4040404 
DATA 4000000        ! 320 Bytes=80 Data

Jürgen Stessun
Aus: ST-Computer 10 / 1989, Seite 78

Links

Copyright-Bestimmungen: siehe Über diese Seite