Listing 1 von startlib.asm (rexxalert.library)

*       startlib.asm
*
*       startup-code für eine (ARexx-)Library
*       abgeguckt und verändert von Bob Malzan 1991
*
        include 'exec/types.i'
        include 'exec/libraries.i'
        include 'exec/nodes.i'
        include 'exec/resident.i'

RXALVERSION     equ     1
RXALPRI         equ     0

        cseg
        near    code
        far     data

        public  _RXALname
        public  _RXALid
        public  _RXALInitTab
        public  _RXALFuncTab
        public  _RXALRomTag

        public  _RXALOpen
        public  _RXALClose
        public  _RXALExpunge
        public  _Query

        public  _LibMain
        public  _StartLib
        public  _SysBase

        public  __H1_end
        public  __H2_org
        public  __H2_end

        public  .begin
        public  _geta4

        ds      0               ; auf Langwortgrenze

*       es folgt die RomTag-Struktur
_RXALRomTag:
        dc.w    RTC_MATCHWORD
        dc.l    _RXALRomTag
        dc.l    endtag
        dc.b    RTF_AUTOINIT
        dc.b    RXALVERSION
        dc.b    NT_LIBRARY
        dc.b    RXALPRI
        dc.l    _RXALname
        dc.l    _RXALid
        dc.l    _RXALInitTab
endtag:         ; Hilfslabel, um die Länge des Tags zu ermitteln

*       hier wird die Library aufgerufen
*       Library-Pointer befindet sich in D0
*       die Segmentliste in A0
.begin
_StartLib:
* alle Register retten
        movem.l d0/d2-d7/a2-a6,-(sp)

* Segmentliste (A0) von BPTR zu einem Zeiger (A4) umwandeln
        move.l  A0,A4
        add.l   a4,a4                   ; mal 2
        add.l   a4,a4                   ; mal 2: jetzt richtige Adresse

        move.l  (a4),a4                 ; Datensegment BPTR holen
        add.l   a4,a4
        add.l   a4,a4                   ; echte Adresse des Datenseg.

* jetzt Offset für Mitte des Datenseg. berechnen
        add.l   #32766+4,a4             ;Mitte plus 4 für Verkettungszeiger
* Register A4 in DatBase ablegen
        lea     DatBase,a1
        move.l  a4,(a1)

        lea     __H1_end,a1
        lea     __H2_org,a2
        cmp.l   a1,a2                   ;liegen BSS und DATA in einem Seg. ?
        bne     StartMain               ;nein, löschen überflüssig...
        move.w  #((__H2_end-__H2_org)/4)-1,d1
        bmi     StartMain               ;Größe d. Seg. <0
        move.l  #0,d2
ClearMem:
        move.l  d2,(a1)+                ;Segment löschen
        dbra    d1,ClearMem

StartMain:
        move.l  4,a6                    ;(Abs)ExecBase bzw. SysBase holen
        move.l  a6,_SysBase             ;und als Variable ablegen

* Aufruf der LibMain-Routine
* Stack = Library-Zeiger, Segment-Zeiger
        movem.l d0/a0,-(sp)
        jsr     _LibMain                ; der Funktionsaufruf
        addq.l  #8,sp                   ; Stack wiederherstellen

        movem.l (sp)+,d0/d2-d7/a2-a6    ; Register wiederherstellen
        rts                             ; FERTIG!

*       Ersatzroutine zum Laden von Register A4,
*       dem Basisregister für das Datensegment
*       beim ``small data model''
_geta4: move.l  DatBase,a4
        rts

* Makro rettet Register
INIT_CFUNC      macro
        movem.l d2-d7/a2-a6,-(sp)
* A4 wird für das ``small data model'' gebraucht...
        jsr     _geta4
        endm

* Makro holt ein Langwort vom Stack und stellt
* Register wieder her
END_CFUNC       macro
        addq.l  #4,sp
        movem.l (sp)+,d2-d7/a2-a6
        rts
        endm

* Es folgen die Einsprungpunkte für die Bibliotheks-
* funktionen
RXALopen:
        INIT_CFUNC
        move.l  a6,-(sp)
        jsr     _RXALOpen
        END_CFUNC

RXALclose:
        INIT_CFUNC
        move.l  a6,-(sp)
        jsr     _RXALClose
        END_CFUNC

RXALexpunge:
        INIT_CFUNC
        move.l  a6,-(sp)
        jsr     _RXALExpunge
        END_CFUNC

* Hier ist der Einsprungpunkt für die Routine, die für den
* Library-Programmierer von einziger Bedeutung ist: Unser Query()
RXALquery:
        INIT_CFUNC
        subq.l   #4,sp                  ; Trick: Variable auf dem
        move.l   sp,-(sp)               ; Stack erzeugen...
        move.l   a0,-(sp)               ; RexxMsg auf den Stack

        jsr      _Query                 ; Query-Aufruf
                                        ; D0 enthält Return-Code

        addq.l   #8,sp                  ; Stack wiederherstellen
        movea.l  (sp)+,a0               ; RESULT-Zeiger nach A0
        movem.l (sp)+,d2-d7/a2-a6       ; Register wiederherstellen
        rts                             ; Ende

* Beginn des Datensegments
        dseg
_SysBase        dc.l    0
DatBase         dc.l    0

* Die Liste der Sprungvektoren für die Library:
_RXALFuncTab:
        dc.l    RXALopen
        dc.l    RXALclose
        dc.l    RXALexpunge
        dc.l    $0000
        dc.l    RXALquery
        dc.l    $ffffffff

        end

