home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
disks
/
disk437.lzh
/
CLIwindow
/
CLIwindow.ass
< prev
next >
Wrap
Text File
|
1991-01-16
|
22KB
|
690 lines
;
;
;
; CLIwindow V1.00
;
;
;
;
; Copyright 12/1990 by Roger Fischlin
; Steigerwaldweg 6
; 6450 Hanau 7
; Germany
;
;
;
; This program may be freely distributed if you don't gain any
; profit by using and/or distributing it.
;
;
; This program is pc relative and 100% PURE (set P flag)
;
incdir "ram:include/"
include "exec/exec_lib.i"
include "exec/memory.i"
include "intuition/intuition_Lib.i"
include "intuition/intuition.i"
include "libraries/dos.i"
include "libraries/dos_lib.i"
include "libraries/dosextens.i"
;
; Macros
;
DOS macro ; die alten Macros müssen ersetzt
move.l Var_DOS(a5),a6 ; werden, da ja die Library-Bases
jsr _LVO\1(a6) ; an anderer Stelle vermerkt werden.
endm
INT macro
move.l Var_INT(a5),a6
jsr _LVO\1(a6)
endm
;
; Variablen
;
rsreset
Var_DOS rs.l 1 ; DOSBase
Var_INT rs.l 1 ; IntuitionBase
Var_Parameter rs.l 1 ; Zeiger auf Paramterstring
Var_X rs.w 1 ; X-Ordinate
Var_Y rs.w 1 ; Y-Ordinate
Var_Width rs.w 1 ; Breite
Var_Height rs.w 1 ; Höhe
Var_Window rs.l 1 ; Zeiger aufs Window
Var_SIZEOF rs.b 0
;
; Variablenspeicherplatz belegen
;
; Diese Routine belegt den Speicherplatz für die zuvor bestimmte
; Variablenliste. Bei einem Fehler wird das anschließende Haupt-
; programm nicht gestartet.
;
_main clr.b -1(a0,d0) ; Paramterstring mit $00 terminieren
move.l a0,a4
moveq.l #Var_SIZEOF,d0 ; Variablenspeicher
move.l #MEMF_CLEAR+MEMF_PUBLIC,d1 ; belegen
CALLEXEC AllocMem
tst.l d0
beq.s .Fehler ; Fehler !
move.l d0,a5
move.l a4,Var_Parameter(a5)
bsr .Programm : ins Hauptprogramm
.Label1 move.l d0,-(sp)
move.l a5,a1
moveq.l #Var_SIZEOF,d0
CALLEXEC FreeMem ; Variablenspeicher freigeben
move.l (sp)+,d0
rts
.Fehler moveq.l #20,d0 ; fataler Fehler !
bra.s .Label1
.Programm
;
; Hauptprogramm
;
MAIN bsr GetLibs ; DOS- und Intuition-Library öffnen
tst.l d0 ; Fehler
beq .Fehler
bsr CLIWindow ; Zeiger auf CLI-Window
lea.l .Text1(pc),a0
tst.l d0
beq .PrintText
move.l d0,Var_Window(a5) ; Zeiger merken
move.l d0,a0
move.w wd_LeftEdge(a0),Var_X(a5) ; aktuelle Windowerte als Voreinstellung
move.w wd_TopEdge(a0),Var_Y(a5) ; kopieren
move.w wd_Width(a0),Var_Width(a5)
move.w wd_Height(a0),Var_Height(a5)
move.l Var_Parameter(a5),a0 ; X-Ordinate holen
move.l a0,a1
cmp.b #"?",(a0)
beq .INFO ; Info-String ausgeben
cmp.b #"*",(a1)+ ; aktuellen Wert übernehmen ?
beq.s .Label1
subq.l #1,a1 ; A0 wieder um eins vermindern
bsr GetLong
move.l a0,a1 ; Zeiger auf nächstes Argument
lea.l .Text2(pc),a0
tst.l d1 ; Fehler ?
bne .PrintText ; Fehlermeldung ausgeben
move.w d0,Var_X(a5)
.Label1 cmp.b #"/",(a1)+ ; "/"-Zeichen ?
bne .PrintText
move.l a1,a0 ; Y-Ordinate holen
cmp.b #"*",(a1)+ ; aktuellen Wert übernehmen ?
beq.s .Label2
subq.l #1,a1 ; A0 wieder um eins vermindern
bsr GetLong
move.l a0,a1 ; Zeiger auf nächstes Argument
lea.l .Text2(pc),a0
tst.l d1 ; Fehler ?
bne .PrintText ; Fehlermeldung ausgeben
move.w d0,Var_Y(a5)
.Label2 cmp.b #"/",(a1)+ ; "/"-Zeichen ?
bne .PrintText
move.l a1,a0 ; Breite holen
cmp.b #"*",(a1)+ ; aktuellen Wert übernehmen ?
beq.s .Label3
subq.l #1,a1 ; A0 wieder um eins vermindern
bsr GetLong
move.l a0,a1 ; Zeiger auf nächstes Argument
lea.l .Text2(pc),a0
tst.l d1 ; Fehler ?
bne .PrintText ; Fehlermeldung ausgeben
move.w d0,Var_Width(a5)
.Label3 cmp.b #"/",(a1)+ ; "/"-Zeichen ?
bne .PrintText
move.l a1,a0 ; Höhe holen
cmp.b #"*",(a1)+ ; aktuellen Wert übernehmen ?
beq.s .Label12
subq.l #1,a1 ; A0 wieder um eins vermindern
bsr GetLong
move.l a0,a1 ; Zeiger auf nächstes Argument
lea.l .Text2(pc),a0
tst.l d1 ; Fehler ?
bne .PrintText ; Fehlermeldung ausgeben
move.w d0,Var_Height(a5)
.Label12 CALLEXEC Forbid ; kein anderer Task darf das Window jetzt verschieben !
move.l Var_Window(a5),a0 ; Window-Zeiger
move.l wd_WScreen(a0),a1 ; Screen-Zeiger
move.w Var_Width(a5),d0
cmp.w #0,d0 ; Ist die Breite >0 ?
bgt.s .Label10 ; wenn ja, verzweige
add.w sc_Width(a1),d0 ; sonst : echte Breite = Breite + Screen_Breite - Window_X
sub.w Var_X(a5),d0
move.w d0,Var_Width(a5)
.Label10 move.w Var_Height(a5),d0
cmp.w #0,d0 ; Ist die Höhe >0 ?
bgt.s .Label11 ; wenn ja, verzweige
add.w sc_Height(a1),d0 ; sonst : echte Höhe = Höhe + Screen_Höhe - Window_Y
sub.w Var_Y(a5),d0
move.w d0,Var_Height(a5)
.Label11
move.w Var_Width(a5),d0
cmp.w wd_MaxWidth(a0),d0 ; Gewünschte Breite größer als erlaubte ?
bls.s .Label6
move.w wd_MaxWidth(a0),d0 ; erlaubte Breite
.Label6 cmp.w wd_MinWidth(a0),d0 ; Gewünschte Breite kleiner als erlaubte ?
bhi.s .Label7
move.w wd_MinWidth(a0),d0 ; erlaubte Breite
.Label7 move.w d0,Var_Width(a5)
move.w Var_Height(a5),d0
cmp.w wd_MaxHeight(a0),d0 ; Gewünschte Höhe größer als erlaubte ?
bls.s .Label8
move.w wd_MaxHeight(a0),d0
.Label8 cmp.w wd_MinHeight(a0),d0 ; Gewünschte Höhe kleiner als erlaubte ?
bhi.s .Label9
move.w wd_MinHeight(a0),d0 ; erlaubte Höhe
.Label9 move.w d0,Var_Height(a5)
move.l wd_WScreen(a0),a0 ; Zeiger auf zugehörigen Screen
move.w Var_X(a5),d0 ; X2 bestimmen
add.w Var_Width(a5),d0
move.w Var_Y(a5),d1 ; Y2 bestimmen
add.w Var_Height(a5),d1
cmp.w sc_Width(a0),d0 ; X2> Windowbreite ?
bls.s .Label4
CALLEXEC Permit ; Fehler !
lea.l .Text3(pc),a0
bra .PrintText
.Label4 cmp.w sc_Height(a0),d1 ; Y2> Windowhöhe ?
bls.s .Label5
CALLEXEC Permit ; Fehler !
lea.l .Text3(pc),a0
bra .PrintText
.Label5 move.l Var_Window(a5),a0 ; zunächst Window-Position verändern
move.w Var_X(a5),d0 ; DeltaX = neue_X_Ordinate - X_Ordinate_Window
move.w Var_Y(a5),d1 ; DeltaY = neue_Y_Ordinate - Y_Ordinate_Window
sub.w wd_LeftEdge(a0),d0
sub.w wd_TopEdge(a0),d1
INT MoveWindow
move.l Var_Window(a5),a0 ; jetzt die Window-Größe verändern
move.w Var_Width(a5),d0 ; DeltaX = neue_Breite - alte_Breite
move.w Var_Height(a5),d1 ; DeltaY = neue_Höhe - alte_Höhe
sub.w wd_Width(a0),d0
sub.w wd_Height(a0),d1
INT SizeWindow
CALLEXEC Permit ; das war's !
lea.l .NewSize(pc),a0 ; das CLI/die SHELL soll die neuen Ausmaße übernehmen !
bsr CLIText
bsr CloseLibs ; zuvor geöffnete Libraries schließen
moveq.l #0,d0 ; kein Fehler !
rts
.Fehler bsr CloseLibs ; zuvor geöffnete Libraries schließen
moveq.l #20,d0 ; fataler Fehler !
rts
.PrintText bsr CLIText ; Fehlermeldung ausgeben
bsr CloseLibs ; zuvor geöffnete Libraries schließen
moveq.l #0,d0
rts
.INFO lea.l .InfoString(pc),a0 ; "?"-Funktion
bra.s .PrintText
.Text1 dc.b "Can't get window pointer !",10,0
even
.Text2 dc.b "Sytax error !",10,0
even
.Text3 dc.b "Check screen size !",10,0
even
.NewSize dc.b $9b,"t",$9b,"u",0
even
.InfoString dc.b 10," ",$9b,"4m"
dc.b " CLIwindow V1.00 © 12/1990 Roger Fischlin "
dc.b $9b,"0m",10,10
dc.b " CLIwindow may be freely distributed if you don't gain an profit",10
dc.b " by using and/or distributing it.CLIwindow will move this CLI window",10
dc.b " and change its size.",10,10
dc.b " Usage : CLIwindow x/y/width/height",10,10
dc.b " use '*' for current data. CLIwindow will check MinWidth & MinHeight",10
dc.b " and MaxWidth & MaxHeight. It also takes care of the screen size.",10
dc.b " You may use hexadecimal numbers, too. If Width od Height are bellow",10
dc.b " 1 then they are taken as X2 oder Y2 relative to the screen size .",10
dc.b " For example 'CLIwindow 0/0/0/0' will use the whole screen size or",10
dc.b " 'CLIwindow 0/0/-10/0' will leave ten rows free.",10
dc.b 10,0
;
; GetLibs
;
; GetLibs öffnet die DOS- und die Intuition-Library ab Kick-
; start 1.2 . Tritt ein Fehler auf, so enthält D0 0.
;
GetLibs lea.l IntName(pc),a1 ; Intuition-Library
moveq.l #33,d0 ; ab Kickstart 1.2
CALLEXEC OpenLibrary ; öffnen
move.l d0,Var_INT(a5)
beq.s .Error
lea.l DosName(pc),a1 ; DOS-Library
moveq.l #33,d0 ; ab Kickstart 1.2
CALLEXEC OpenLibrary ; öffnen
move.l d0,Var_DOS(a5)
.Error rts
IntName INTNAME ; Library-Namen
DosName DOSNAME
;
; CloseLibs
;
; CloseLibs schließt die von OpenLibs geöffneten Libraries, nicht
; geöffnete Libraries werden abgefangen.
;
CloseLibs move.l d2,-(sp) ; D2 retten
moveq.l #0,d2 ; D2 als $0000000-Vergleich
move.l Var_INT(a5),a1 ; Intuition-Library schließen
cmp.l a0,d2 ; Wurde sie überhaupt geöffnet ?
beq.s .Skip1
CALLEXEC CloseLibrary
.Skip1 move.l Var_DOS(a5),a1 ; DOS-Library schließen
cmp.l a0,d2 ; Wurde sie überhaupt geöffnet ?
beq.s .Skip2
CALLEXEC CloseLibrary
.Skip2 move.l (sp)+,d2
rts
;
; CLIWindow
;
; CLIWindow ermittelt den Zeiger auf das Fenster des CLIs, bzw.
; liefet 0 bei einem Fehler.
;
CLIWindow movem.l a2-a5,-(sp) ; Register retten
sub.l a1,a1
CALLEXEC FindTask ; Zeiger auf eigenen Task
move.l d0,a0
move.l pr_ConsoleTask(a0),a2 ; ID der zugehörigen Console
sub.l a0,a0 ; Reply-Port erzeugen
moveq.l #0,d0
bsr CreatePort
tst.l d0 ; Fehler ?
beq .Label1
move.l d0,a3 ; Zeiger auf Reply-Port retten
bsr CreatePacket ; StandardPacket erzeugen
tst.l d0 ; Fehler ?
beq.s .Label2
move.l d0,a4
move.l a3,sp_Pkt+dp_Port(a4) ; Reply-Port eintragen
moveq.l #id_SIZEOF,d0 ; Speicher für InfoData reservieren
move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
CALLEXEC AllocMem
tst.l d0
beq.s .Label3
move.l d0,a5
lsr.l #2,d0 ; id-Zeiger in BCPL-Zeiger umwandeln
move.l d0,sp_Pkt+dp_Arg1(a4) ; und ins DosPacket eintragen
move.l #ACTION_DISK_INFO,sp_Pkt+dp_Type(a4)
move.l a4,a1 ; Zeiger auf Packet
move.l a2,a0 ; Zeiger auf Port
CALLEXEC PutMsg
.Label5 move.l a3,a0 ; auf Reply warten
CALLEXEC WaitPort
move.l a3,a0 ; Reply-Message holen
CALLEXEC GetMsg
tst.l d0 ; doch keine Message ?
beq.s .Label5
move.l id_VolumeNode(a5),d0 ; WindowPointer !
.Label4 move.l d0,-(sp)
move.l a5,a1 ; Speicher für InfoData
moveq.l #id_SIZEOF,d0 ; freigeben
CALLEXEC FreeMem
move.l (sp)+,d0
.Label3 move.l d0,-(sp)
move.l a4,a0
bsr DeletePacket ; Standard-Packet löschen
move.l (sp)+,d0
.Label2 move.l d0,-(sp)
move.l a3,a0
bsr DeletePort ; Reply-Port löschen
move.l (sp)+,d0
.Label1 movem.l (sp)+,a2-a5
rts
;
; CreatePacket
;
; CreatePacket erzeugt ein StandardPacket,Message- und DosPacket-
; Teil werden verbunden. In d0/a0 wird er Zeiger zurückgeben,bzw.
; 0 bei einen Fehler.
;
CreatePacket moveq.l #sp_SIZEOF,d0 ; Speicher für StandardPacket reservieren
move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
CALLEXEC AllocMem
tst.l d0
beq.s .Label1
move.l d0,a0
lea.l sp_Pkt(a0),a1 ; Zeiger auf Packet-Teil
move.l a1,sp_Msg+LN_NAME(a0) ; Node-Namen muß auf Packet-Teil zeigen
move.l a0,sp_Pkt+dp_Link(a0) ; DosPacket-Link muß auf Message-Teil zeigen
.Label1 rts
;
; DeletePacket
;
; DeletePacket löscht ein zuvor mit CreatePacket erzeugtes
; StandardPacket. Als Parameter wird in A0 der Zeiger auf das
; StandardPacket erwartet.
;
DeletePacket moveq.l #0,d0
cmp.l d0,a0 ; 0-Zeiger abfangen !
beq.s .NIL
move.l a0,a1
moveq.l #sp_SIZEOF,d0 ; Speicher freigeben
CALLEXEC FreeMem
.NIL rts
;
; CreatePort
;
; CreatePort erzeugt einen funktionsfähigen Msg-Port des Typs
; PA_SIGNAL mit der Priorität von D0.A0 zeigt auf den Port-Namen,
; der nicht kopiert wird. Falls A0 0 ist, wird er nicht in die
; Liste öffentlicher Ports aufgenommen. Als SigTask wird der
; eigene eingetragen. Der Funktionswert in D0 ist der Zeiger auf
; auf den Port oder bei einem Fehler 0 .
;
CreatePort move.l a2,-(sp)
movem.l d0/a0,-(sp) ; retten
moveq.l #MP_SIZE,d0 ; Speicher für Port reservieren
move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
CALLEXEC AllocMem
tst.l d0
beq.s .NoMem
move.l d0,a2
moveq.l #-1,d0 ; Signal belegen
CALLEXEC AllocSignal
move.b d0,MP_SIGBIT(a2)
bmi.s .FreeMem ; kein Signal
movem.l (sp)+,d0/a0
move.b d0,MP+LN_PRI(a2) ; Priorität eintragen
move.b #NT_MSGPORT,LN_TYPE(a2)
move.l a0,MP+LN_NAME(a2) ; Name
sub.l a1,a1
CALLEXEC FindTask
move.l d0,MP_SIGTASK(a2) ; eigener Task als Signal-Empfänger
lea.l MP_MSGLIST(a2),a0
move.b #NT_MESSAGE,LH_TYPE(a0) ; Messages werden verwaltet
bsr NewList
tst.l MP+LN_NAME(a2) ; öffentlicher Port ?
beq.s .Private
move.l a2,a1
CALLEXEC AddPort ; Port in allgemeine Liste eintragen
.Private move.l a2,d0
move.l (sp)+,a2
rts
.FreeMem move.l a2,a1
moveq.l #MP_SIZE,d0 ; Speicher freigeben
CALLEXEC FreeMem
.NoMem addq.l #8,sp
move.l (sp)+,a2
moveq.l #0,d0 ; Fehler !
rts
;
; NewList
;
; NewList initialisiert eine LIST-Struktur, A0 muß auf die LIST-
; Struktur zeigen.
;
NewList move.l a0,LH_HEAD(a0) ; LH_HEAD muß auf LH_TAIL zeigen
addq.l #LH_TAIL,(a0)
clr.l LH_TAIL(a0) ; LH_TAIL muß auf 0 zeigen
move.l a0,LH_TAILPRED(a0)
rts
;
; DeletePort
;
; DeletePort löscht einen zuvor mit CreatePort erzeugten MsgPort.
; Als Parameter wird in A0 der Zeiger auf den Port erwartet.Noch
; ausstehende Messages werden zuvor reply-t.
;
DeletePort move.l a2,-(sp)
move.l a0,a2 ; Zeiger retten
CALLEXEC Forbid ; Multitasking unterbinden
.Loop move.l a2,a0
CALLEXEC GetMsg ; Msg holen
tst.l d0 ; keine (weitere) Message mehr
beq.s .AllReplied
move.l d0,a1
CALLEXEC ReplyMsg ; Message reply-en
bra.s .Loop
.AllReplied move.l MP+LN_NAME(a2),d0 ; öffentlicher Port ?
beq.s .Private
move.l a2,a1
CALLEXEC RemPort ; entfernen
.Private move.b MP_SIGBIT(a2),d0
CALLEXEC FreeSignal ; Signal freigeben
move.l a2,a1 ; Speicher freigeben
moveq.l #MP_SIZE,d0
CALLEXEC FreeMem
CALLEXEC Permit ; Multitasking wieder erlauben
move.l (sp)+,a2
rts
;
; CLIText
;
; CLIText gibt den mit einem $00-Byte abgeschlossen Text (Zeiger
; in A0) im CLI-Window aus.
;
CLIText movem.l d2/d3,-(sp) ; Register retten
move.l a0,d2 ; Zeiger nach D2
moveq.l #-1,d3 ; Länge ermitteln
.Label addq.l #1,d3
tst.b (a0)+
bne.s .Label
DOS Output ; Handle fürs CLI-Fenster
move.l d0,d1
DOS Write ; Text ausgeben
movem.l (sp)+,d2/d3
rts
;
; GetLong
;
; GetLong übersetzt den ASCII-String (Zeiger in A0) in ein Long-
; Word, welches in D0 zurückgeben wird. Anschließend zeigt A0 auf
; das erste Zeichen nach der Zalh im String. Enthält D1 0, trat
; kein Fehler auf. 1 signalisiert einen Überlauf, -1 zeigt einen
; Fehler im Aufbau an. Unterstützt werden das dezimale und das
; hexadezimale ("$") Zahlensystem.
;
GetLong movem.l d3-d3/a1-a3,-(sp) ; Register retten
bsr.s .Main
movem.l (sp)+,d3-d3/a1-a3
rts
.Main moveq.l #0,d0 ; Register löschen
moveq.l #0,d1
moveq.l #0,d2
.Label1 move.b (a0)+,d3 ; Spaces und Tabs überlesen
cmp.b #" ",d3
beq.s .Label1
cmp.b #9,d3
beq.s .Label1
cmp.b #"$",d3 ; hexadezimal ?
beq .Hex
cmp.b #"-",d3 ; negativ ?
beq.s .Negativ
cmp.b #"9",d3 ; Ziffer ?
bhi .Fehler
cmp.b #"0"-1,d3
bhi .Dezimal
.Fehler subq.l #1,a0 ; ^Fehler
moveq.l #-1,d1 ; Fehlercode
rts
.Negativ tst.b d2 ; teste,ob bereits ein "-"
bne.s .Fehler
moveq.l #1,d2 ; Flag für negativ seten
bra .Label1
.Dezimal subq.l #1,a0 ; A0 auf erste Ziffer setzen
move.l a0,a1 ; A1 ^erstes Ziffer
.Label_D2 move.b (a0)+,d3 ; nächste Zeiffer holen
cmp.b #"9",d3 ; wiederhole, bis Zahlenende
bhi.s .Label_D3 ; erreicht wird.
cmp.b #"0"-1,d3
bhi.s .Label_D2
.Label_D3 lea.l .Data10(pc),a2 ; Zeiger auf 10'er-Potenzen
subq.l #1,a0 ; A0 ^letzte Ziffer+1
move.l a0,a3 ; A3 ^letzte Ziffer+1
.Label_D5 move.l (a2)+,d4 ; Stellenzahl holen
beq.s .Overflow ; Longwordgrenze überschritten ?
moveq.l #0,d3 ; D3 löschen
move.b -(a3),d3 ; vorherige Ziffer holen
sub.b #"0"+1,d3 ; und in Zahl umwandeln (1 abziehen wegen DBRA-Schleife)
bmi.s .D_Zero ; Ziffer "0" abfangen
.Label_D4 add.l d4,d0 ; Stellenzahl so oft wie Ziffer addieren
dbra d3,.Label_D4
.D_Zero cmp.l a3,a1 ; Zahlenanfang erreicht ?
bne.s .Label_D5
.Vorzeichen tst.b d2 ; negatives Vorzeichen ?
beq.s .NotNegative
tst.l d0 ; Ist die Zahl größer als ein Longint ?
bmi .Overflow
neg.l d0 ; negativieren
.NotNegative moveq.l #0,d1 ; keine Fehler
rts
.Data10 dc.l 1
dc.l 10
dc.l 100
dc.l 1000
dc.l 10000
dc.l 100000
dc.l 1000000
dc.l 10000000
dc.l 100000000
dc.l 1000000000
dc.l 0
.Overflow moveq.l #1,d1 ; Überfluß (Zahl zu groß !)
rts
.Hex move.b (a0)+,d3 ; erste Stelle OK ?
bsr.s .Nibble
bmi .Fehler ; Fehler !
lea.l -1(a0),a1 ; A1 ^ erste Ziffer
.Label_H2 move.b (a0)+,d3
bsr.s .Nibble ; in Hexa-Ziffer übersetzen
bpl.s .Label_H2
subq.l #1,a0 ; A0 ^letzte Ziffer+1
move.l a0,a2 ; A2 ^letzte Ziffer+1
moveq.l #0,d1
.Label_H3 move.b -(a2),d3 ; vorherige Ziffer
bsr .Nibble
lsl.l d1,d4 ; Nibble an richtige Position schieben
add.l d4,d0 ; zum Ergebnis addieren
addq.l #4,d1
cmp.b #32,d1 ; 32. Bit erreicht ?
bhi .Overflow ; wenn ja, Overflow !
cmp.l a2,a1 ; Zahlenanfang erreicht ?
bne.s .Label_H3
bra .Vorzeichen
.Nibble moveq.l #0,d4
cmp.b #"a"-1,d3 ; Ziffer d3 -> Zahl d4
bls.s .N1 ; Upcase
cmp.b #"f",d3
bhi.s .N_Error
sub.b #"a"-"A",d3
.N1 sub.b #"0",d3
cmp.b #9,d3 ; Ziffer ?
bls.s .Ziffer
sub.b #"@"-"9",d3 ; Buchstabe
cmp.b #$f,d3
bhi.s .N_Error
.Ziffer move.b d3,d4
rts
.N_Error moveq.l #-1,d4 ; Fehler !
rts