DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦a8b96c776⟧ TextFile

    Length: 19840 (0x4d80)
    Types: TextFile
    Names: »EXTBESKR«

Derivation

└─⟦832e7e234⟧ Bits:30003263 Butler systemdiskette
└─⟦832e7e234⟧ Bits:30004286 Butler systemdiskette
    └─ ⟦this⟧ »EXTBESKR« 
└─⟦ccbc2d84d⟧ Bits:30004597 Boot 60k CP/M (Butler)
    └─ ⟦this⟧ »EXTBESKR« 
└─⟦d823d3189⟧ Bits:30004365 Butler CP/M 2.2 systemdiskette fra LFU
    └─ ⟦this⟧ »EXTBESKR« 

TextFile

Et assemblerprogram, der definerer extensions, skal begynde med

	NAME('<navn>')

hvor <navn> er programmets navn.
Derefter skal indholdet af filen EXTDEFS.MAC komme. Derefter specifikationer
for de extensions, der er defineret i filen. 
Disse skal følge lige efter hinanden. Koden for dem kommer efter den sidste
af dem. De ser hver sådan ud:

	EXTENSION  <navn>Æ,<lokalt navn>Å
	<grænsefladeangivelse>
	ENDEXT	   <navn>Æ,<lokalt navn>Å

Her skal angives samme <navn> og evt. <lokalt navn> begge steder.
I den sidste specifikation skal ordet ENDEXT erstattes med ENDALLEXT.
<navn> er det navn, extension'en skal kaldes ved i COMAL-programmer,
excl. eventuelt $-tegn. <lokalt navn> er det navn, extension'en har
i assemblerfilen. Hvis det ikke er angivet, bruges <navn> i stedet.
Angivelse af <lokalt navn> kan være nyttig, hvis flere extensions
har navne, der falder sammen på de første 5 tegn eller indeholder 
underscore eller falder sammen med Z80 opcodes.

<grænsefladeangivelse> er forskellige for funktioner, sætninger
og operatorer.

For funktioner:
		
	FUNCTION  <returtype>
	<liste af parametre>
		     
hvor <returtype> (funktionens type) er INT, REAL eller STR .

For sætninger:

	STATEMENT 
	<liste af parametre>

<liste af parametre> er nul eller flere linier, hvor hver linie
specificerer een parameter på følgende måde:

	PARAMETER Æ<dimension>,Å<type>

Hvis <dimension>, udelades, har man angivet en værdioverført parameter.
Ellers referenceoverføres parameteren, og
<dimension> angiver parameterens dimensionalitet. 0 = simpel
variabel, 1=vektor osv. Her kan angives ANYDIM for <dimension> . Det
betyder at den aktuelle parameter kan have en hvilkensomhelst dimension
og at den referenceoverføres. Det er da op til extension'en at finde ud
af hvilken dimensionalitet, parameteren har, og gøre derefter.

<type> angiver parameterens type. Her kan angives INT, REAL, STR
med den oplagte betydning. Desuden kan angives ANYTYPE eller INTREAL.
ANYTYPE betyder at den aktuelle parameter kan have en hvilkensomhelst
type (altså INT, REAL eller STR), og INTREAL betyder at den aktuelle
parameter kan have type INT eller REAL. Der gør sig nogle særlige
forhold gældende i disse to tilfælde vedrørende den måde, hvorpå
parameteren overføres til extension'en - se nedenfor. 


For operatorer er <grænsefladeangivelsen> enten

	OPERATOR <returtype>,<venstre operands type>,<højre operands
		 type>,<prioritet>

eller

	OPERATOR <returtype>,<operandens type>,<prioritet>

hvor det første benyttes for dyadiske operatorer og det andet benyttes
for monadiske operatorer. <returtype> er som for funktioner enten
INT, REAL eller STR . <venstre operands type>, <højre operands type> og
<operandens type> kan være INT, REAL, STR, ANYTYPE eller INTREAL med samme
betydning som ovenfor beskrevet ved funktioner og sætninger. 
Parametre til operatorer kan kun være værdioverførte. <prioritet>
angiver hvilken prioritet i beregningen, operatoren skal have i 
forhold til andre operatorer, herunder standardoperatorer. Det angives
som navnet på en standardoperator, hvor det navn, som også benyttes
ved kald af matematikpakken, skal bruges. Operatoren vil da få samme
prioritet som denne standardoperator. Følgende navne kan bruges:
	POWER,	 
	TIMES, SLASH, DIV, MOD,
	PLUS, MINUS, CHS,
	LEQ, LSS, GEQ, GTR, EQL, NEQ, IN,
	B.NOT,
	B.AND,
	B.OR
			    


Efter linien med ENDALLEXT ....... kommer koden for de extensions,
der er specificeret. Hver rutine begynder med en label, som er 
det navn (eller lokalt navn), der er angivet i den tilsvarende
EXTENSION linie.

Når rutinen starter, er alle registre, som benyttes af COMAL, gemt
og kan benyttes frit. Parametrene ligger på en stak, som udpeges
af IX og som vokser nedad ligesom SP-stakken. Den
sidste parameter ligger øverst. 
For referenceoverførte parametre ligger et såkaldt referenceelement for
parameteren på stakken. Det beskrives nedenfor. Bemærk at hvis
den formelle parameter er af type ANYTYPE eller REALINT, må
extension'en selv finde ud af hvad typen på den aktuelle parameter
er, og indrette sig derefter. Typen fremgår af referenceelementet,
se beskrivelsen nedenfor.
For værdioverførte parametre ligger værdien på stakken. Hvordan
værdien er struktureret, beskrives nedenfor. Hvis den formelle
parameter er af type ANYTYPE eller REALINT, er der stakket endnu
en ekstra byte ovenpå værdien, og denne byte angiver værdiens type
på følgende måde: For ANYTYPE kan byten have værdien INT, REAL eller STR,
svarende til den aktuelle parameters type. For INTREAL vil en aktuel
parameter af type REAL altid blive konverteret (med afrunding)
til INT før extension'en
kaldes, men den ekstra byte vil angive om konverteringen gav anledning
til overløb (tallet for stort). Hvis dette var tilfældet, vil byten
være <>0 ; ellers er den =0. Hvis den aktuelle parameter er af type
INT, vil byten være =0. I tilfælde af overløb vil der stadig ligge
et heltal på stakken lige under den omtalte byte, men dets værdi er
uinteressant.

Desuden indeholder A- hhv. B-registeret den kørende COMAL-versions
versionsnummer hhv. underversionsnummer. For version 2.0 er under-
versionsnummeret 0, og versionsnummeret er 8+DB+OV , hvor
DB=0 for 7-ciffer-udgaven og DB=2 for 13-cifferudgaven, mens
OV=0 for den hele udgave og OV=1 for overlayudgaven.

Inden rutinen returnerer, skal alle parametrene afstakkes fra
IX-stakken. Hvis rutinen svarer til en funktion eller en operator,
skal returværdien stakkes på IX-stakken inden returhoppet.
Hvis der returneres med C-bitten sat (se nedenfor), er det dog ikke
nødvendigt at afstakke parametre eller stakke nogen returværdi. 
Der returneres v.hj.a. RET. Der skal ikke pilles ved SP-stakkens højde,
men den kan godt benyttes, da der er ca. 100 bytes fri plads.	      

Afhængigt af indholdet af AF-registret vil COMAL
afgive en fejlmelding når rutinen har returneret. Der er mulighed
for at få både fatale fejlmeldinger og ikke-fatale fejlmeldinger.
Hvis Z-bitten er sat, vil der ikke blive givet nogen fejlmelding.
Ellers vil der blive givet fejlmeldingen med det nummer, der ligger
i A-registret, dog således at der skal fratrækkes 50  fra numre, der
er større en 200. Hvis C-bitten er sat, vil fejlmeldingen være
fatal; ellers vil den være ikke-fatal, dvs. den vil ikke komme
hvis man kører med TRAP ERR-, men i stedet kan man få fejlnummeret
v.hj.a. ERR() .


Struktur af parametre
=====================

Nedenfor gennemgås den måde, hvorpå parametre, dvs. værdier og
referenceelementer, repræsenteres af COMAL:

Heltal repræsenteres som maskinen gør det. Bitmønsteret 8000H 
betyder "udefineret" og vil ikke blive leveret som parameter.
Det bør ej heller returneres som returværdi eller tildeles nogen
parameter. Hvis en referenceoverført parameter har denne værdi,
betyder det at variablen aldrig er blevet tildelt nogen værdi.
Dette bør checkes først hvis værdien benyttes. Dette gøres
implicit af matematikpakkens funktion LDVAL.

Reelle tal fylder 4 bytes for 7-cifferversionen og 8 bytes for
13-cifferversionen. Første byte = 80H og sidste byte lig 00H
betyder "udefineret". Bemærkningerne ovenfor gælder også her. 

Strenge består af to dele: først 2 bytes (et heltal) der fortæller
hvor lang strengen er, og dernæst, i rækkefølge mod højere adresser,
det således angivne antal bytes, som hver indeholder et tegn, således
at den byte, der følger lige efter længden, indeholder det første tegn,
den næste det andet tegn osv.

Referenceelementer angiver variable af alle slags, både simple
variable, herunder strengvariable, arrays og delstrenge.
Formatet for referencelementer for delstrenge er specielt og
beskrives senere. Alle andre referenceelementer 
fylder 4 bytes og består af to pointere: først en pointer til
en beskrivelse af variablen og derefter en pointer til variablens
dataområde. 

Variabelbeskrivelsen er af variabel størrelse og vokser mod lavere
adresser (NB!) . For simple variable består den af en byte med
værdi -INT, -REAL eller -STR, svarende til de tre typer. Hvis det
er -STR, følges denne byte af strengvariablens maksimale længde
(et heltal i 2 bytes).

For arrays er der først et antal index-felter, svarende til antallet
af indices. Hvert indexfelt består af det følgende:
	antal indexfelter efter dette  (1 byte)
	lav grænse for dette index     (heltal 2 bytes)
	høj grænse for dette index     (heltal 2 bytes)
	størrelse af hver delarrays eller elements data (heltal 2 bytes)

Eksempel: variabelbeskrivelsen for en array dimensioneret med
	DIM A$(-2:5, 1:10) OF 20
er
	1    (1 byte)
	-2   (2 bytes)
	5    (2 bytes)
	220  (2 bytes)

	0    (1 byte)
	1    (2 bytes)
	10   (2 bytes)
	22   (2 bytes)	  (2 for aktuel længde + 20 til selve tegnene) 

	-STR (1 byte)
	20   (2 bytes)

Referenceelementer for delstrenge begynder også med en pointer
til en variabelbeskrivelse, der i dette tilfælde er 
en enkelt byte med værdien enten
	-STR-1	 eller	 -STR-2
Derefter følger en pointer til datafeltet for den strengvariabel, delstrengen
er en del af. Efter denne følger
   den maksimale (dimensionerede) længde for den pågældende strengvariabel,
   2. index (til-værdi), og
   1. index (fra-værdi),
som er anvendt ved specifikationen af delstrengen.
Eksempler på 2. og 1. index : ved A$(8:17) er 2.index = 17 og 1.index = 8.
Ved A$(10) er både 2.index og 1.index = 10.  
Alle tre værdier er heltal (2 bytes).
	   
Datafeltet for en simple variabel er struktureret som en værdi, se ovenfor.
Datafeltet for en array er blot en række simple datafelter efter hinanden, et
for hvert af elementerne. For strengarrays er der afsat plads til at hvert
element kan vokse til sin maksimale længde.  
			

Matematikpakken
===============

I EXTDEFS.MAC er defineret alt, hvad der skal bruges for at man kan
benytte matematikpakken. Man kalder matematikpakken ved at benytte
makroen
	EXPR
hvorefter følger kommandoer til matematikpakken. Der afsluttes med
	EXPREND
Kommandoerne udføres en efter en i den rækkefølge de står. De
tager (for det meste) deres argumenter fra IX-stakken og
gemmer deres resultater på  
denne stak. Man kan opfatte kommandoerne som et program til en
stakorienteret maskine. Kommandoerne er i virkeligheden makroer,
som er defineret i EXTDEFS.MAC . Hver makro expanderer til en
eller flere bytes med parametre til kaldet af matematikpakken,
som fortolker disse parametre og opererer på IX-stakken.

Man kan benytte følgende kommandoer:

De følgende kommandoer svarer til COMALs standardfunktioner, men
alle kommandoer kræver argumenter af en bestemt type og leverer
et resultat af en bestemt type, som angivet. Hvor der er angivet
INTREAL, betyder dette, at argumentet skal være af heltalstype,
men at det er i orden, hvis dette er fremkommet ved at kald af
REALINT umiddelbart før kommandoen.

navn	argument(ers)  type	resultats type
ATN	REAL			REAL
COS	REAL			REAL
SIN	REAL			REAL
TAN	REAL			REAL
LOG	REAL			REAL
EXP	REAL			REAL
SQR	REAL			REAL
ESC	-			INT
ERR	-			INT
EOD	-			INT
EOF	REALINT 		INT
LEN	ref. elem.		INT	(ref.elem. skal være streng)
ORD	STR			INT
IVAL	STR			INT
VAL	STR			REAL 
INT	REAL			REAL
FRAC	REAL			REAL
TRUNC	REAL			INT
ROUND	REAL			INT
POS	STR, STR		INT
BVAL	STR			INT
CHR	REALINT 		STR
STR	REAL			STR    (svarer begge til STR$, men
I.STR	INT			STR    taget af reelt tal hhv. heltal)
ERRTEXT REALINT 		STR
SGN	REAL			INT    (svarer begge til SGN, men 
I.SGN	INT			INT    taget af reelt tal hhv. heltal)
ABS	REAL			REAL   (svarer begge til ABS, men
I.ABS	INT			INT    taget af reelt tal hhv. heltal)
RND0	-			REAL   (RND uden parametre)
RND2	REALINT, REALINT	INT    (RND med 2 parametre)
SPC	REALINT 		STR
PEEK	REAL			INT
INP	REALINT 		INT
BSTR	REALINT 		STR
VARPTR	ref.elem.		REAL
FREEST	-			INT    (FREESTORE)


				
Diverse konverteringer:

CONV	konverterer det øverste stakelement fra INT til REAL.
CONV1	konverterer det næstøverste stakelement fra INT til REAL.
	Det forudsættes at det øverste stakelement er af type REAL.
REALINT konverterer det øverste stakelement fra REAL til INT med
	afrunding. Hvis det tallet er udenfor heltalsområdet,
	bliver det øverste stakelement udefineret, men der sættes
	desuden et særligt overløbsflag, som de standardfunktioner,
	der ovenfor er angivet REALINT ved, reagerer passende på.
RLBL	konverterer det øverste stakelement fra REAL til INT således
	at hvis tallet er <> 0 bliver resultatet 1, ellers 0.
	Benyttes i forbindelse med de boolske operatorer.
RLBL1	konverterer det næstøverste stakelement fra REAL til INT
	på samme måde som RLBL. Det forudsættes at det øverste
	stakelement er af type INT.



COMALs standardoperatorer har følgende navne i denne sammenhæng:

navn	COMALs navn	argument(er)s	resultats 
			    type	  type

CHS	-  (monadisk)	REAL		REAL

POWER	^		)
TIMES	*		)
SLASH	/		)
DIV	DIV		)->REAL, REAL	REAL 
MOD	MOD		)
PLUS	+		)
MINUS	-   (dyadisk)	)

LEQ	<=		)
LSS	<		)
GEQ	>=		)->REAL, REAL	INT
GTR	>		)		(værdi 0 eller 1)
EQL	=		)
NEQ	<>		)

I.CHS	-		INT		INT

I.TIMES *		)
I.DIV	DIV		)
I.MOD	MOD		)->INT, INT	INT
I.PLUS	+		)
I.MINUS -		)

I.LEQ	<=		)
I.LSS	<		)
I.GEQ	>=		)->INT, INT	INT
I.GTR	>		)		(værdi 0 eller 1)
I.EQL	=		)
I.NEQ	<>		)

S.PLUS	+		STR, STR	STR

S.LEQ	<=		)
S.LSS	<		)
S.GEQ	>=		)->STR, STR	INT
S.GTR	>		)		(værdi 0 eller 1)
S.EQL	=		)
S.NEQ	<>		)

IN	IN		STR, STR	)
B.AND	AND		INT, INT	)->INT
B.OR	OR		INT, INT	)  (værdi 0 eller 1)
B.NOT	NOT		INT		)
	  

Herudover er der følgende kommandoer:

INX	forventer et tal og dernæst et referenceelement for en array
	eller en strengvariabel
	på stakkens top. Foretager indicering, dvs. afstakker
	disse to og stakker i stedet et referenceelement for
	det valgte element i den angivne array eller den angivne
	delstreng. 
	Tallet kan være et heltal eller et reelt tal. I det sidste
	tilfælde konverteres tallet automatisk til heltal med
	afrunding. Tallets type (INT eller REAL) skal angives
	efter INX f.eks. sådan:
		INX  REAL

LDVAL	forventer et referenceelement på stakkens top. Afstakker
	dette og stakker i stedet værdien af den tilsvarende
	variabel. Kan også bruges efter INX. Det checkes at
	variabelen ikke er "udefineret", dvs. har den specielle
	værdi, der betyder, at der ikke er blevet tildelt nogen
	værdi til den.
			 
STVAL	forventer et referenceelement og dernæst en værdi på
	stakkens top. Begge afstakkes og værdien gemmes i den
	variabel, der er angivet af referenceelementet.
	Værdiens type og typen af den variabel, der angives
	af referenceelementet, skal stemme overens. Kan benyttes
	efter INX.

LOAD	forventer en adresse (2 bytes) på stakkens top. Afstakker
	denne og stakker i stedet den værdi/det referenceelement,
	der ligger på den adresse. Det skal angives, hvilken
	type, værdien har, eller at det er et referenceelement.
	Dette gøres på samme linie efter LOAD, f.eks. således:
		LOAD  INT

STORE	forventer en adresse (2 bytes) og dernæst en værdi
	eller et referenceelement på stakkens top. Begge afstakkes
	og værdien/referencelementet gemmes på den
	angivne adresse. Det skal, ligesom ved LOAD, angives
	hvilken type, værdien har, eller at det er et reference-
	element. Dette gøres ligesom ved LOAD, f.eks.:
		STORE  REF

INTCON	stakker et heltal eller en adresse (2 bytes) på stakken.
	Heltallet/adressen skal angives på den samme linie efter
	INTCON. f.eks. således:
		INTCON	 47

STRCON	stakker en strengværdi på stakken. Strengværdien skal
	angives på den samme linie efter STRCON, f.eks. således:
		STRCON	'Strengen skal i enkelt anførselstegn'

UROUND	forventer et reelt tal på stakken. Dette afstakkes,
	konverteres til et fortegnsløst heltal i området
	0 til 65535 og stakkes.

SYSVAR	stakker værdien af en af systemvariablene som et heltal.
	Det skal angives hvilken af systemvariablene, man er
	interesseret i; dette gøres på samme linie efter SYSVAR,
	f.eks. således:
		SYSVAR	PAGEWI
	Systemvariablenes navne er lidt forkortede her:

	COMALs navn	Her kaldes den
	ZONE		ZONE
	INDENTION	INDENT
	PAGEWIDTH	PAGEWI
	PAGELENGTH	PAGELE
	KEYWORDLOWER	KWLOWER
	IDENTIFIERLOWER IDLOWER

TRUE	stakker et heltal 1

FALSE	stakker et heltal 0


Der er naturligvis mulighed for at der opstår fejl ved brug
af matematikpakken: overløb, indexfejl, forskellige funktioner
får argumenter, der er ude af definitionsområdet osv.
Der skelnes mellem fatale og ikke-fatale fejl. Fejl, der er
fatale under normal COMAL-afvikling, der fatale her; fejl, der
ikke er fatale under normal COMAL-afvikling, dvs. kan slås fra
v.hj.a. TRAP ERR-, er ikke fatale her. Hvis en ikke-fatal
fejl opstår, gemmes dens fejlnummer blot og der fortsættes
med udførelse af kommandoer. Fejlnummeret vil da stå i
A-registret, når der vendes tilbage til extension'en efter
ENDEXPR, og carry-bitten vil være 0, mens Z=1.
Hvis der opstår en fatal fejl, vil resten af kommandoerne
blive sprunget over, IX sættes tilbage til dens værdi ved
indgangen til matematikpakken, der vendes tilbage til
extension'en efter ENDEXPR med fejlnummeret i A-registret,
carry=1 og Z=1. Hvis der ikke opstår nogen fejl overhovedet,
er A=0 og Z=0 når der vendes tilbage til extension'en efter
ENDEXPR. Ønsker man således at checke om der opstår en fejl
ved udførelsen af en bestemt kommando, kan man blot indføje
	ENDEXPR
	JP	NZ,FEJLBEHANDLING
	EXPR
efter denne kommando. 
Bemærk, at disse konventioner for indholdet af A, CY, Z
svarer til konventionerne for rapportering af fejl tilbage
til det kaldende COMAL-program.



Format for .EXT -filer
======================


Den fil, der læses op af COMAL når man bruger EXTENSION-kommandoen,
skal have et bestemt format. Dette er et særlig simpelt relokerbart
format. Assemblerprogrammet, hvis form er beskrevet i den første afsnit,
kan oversættes af Microsofts M80 makroassembler til eet relokerbart
format. Andre assemblere benytter andre relokerbare formater (og
nogle af dem vil også kræve at definitioner i EXTDEFS.MAC omskrives).
COMALen definerer sit eget relokerbare format, som er som følger:

Filen starter med et heltal på 2 bytes, som fortæller hvor meget
kode, filen indeholder, talt i bytes. Dette er ikke det samme som
filens længde, da filen udover koden indeholder information om,
hvilke dele af koden, der skal relokeres.

Resten af filen består af et antal blokke med samme format. Hver
blok består af 9 bytes, hvoraf de 8 indeholder kode, og den
niende indeholder relokeringsinformation for de 8 bytes.
Hvis det tal, filen starter med, er L, vil der være 
(L + 7) DIV 8 blokke. Hvis L ikke er et multiplum af 8,
er der overskydende plads i den sidste blok. Denne overskydende
plads indeholder blot noget nonsens. 
Koden, som er indeholdt i blokkene, udgør logisk een lang følge af
kodebytes. Koden for to blokke efter hinanden vil altså ligge
lige efter hinanden når filen er blevet læst op af COMALen.
Byten med relokeringsinformation indeholder een bit for hver
af de 8 kodebytes, således at bit 0 svarer til den første byte,
osv. op til bit 7, der svarer til den ottende og sidste kodebyte.
Hvis en sådan bit er 1, betyder det, at den adresse, som ligger
i den pågældende byte og den foregående, skal relokeres.
Hvis bitten er 0, skal de to byte ikke relokeres.

Programmet CONVERT kan lave en relokerbar fil i Microsoft format om
til den tilsvarende fil i COMALs format. Benytter man en assembler,
der bruger et andet format, må man selv lave et program, der kan
lave den relokerbare fil om til COMALs format.

«eof»