
;**********************************************************************;
;*                           A T O M   X M S                          *;
;*--------------------------------------------------------------------*;
;*    doel           : geeft de atom-in-pc de beschikking over        *;
;*                     het xms geheugen van de pc via INT61h          *;
;*--------------------------------------------------------------------*;
;*    auteur         : Roland Leurs                                   *;
;*                     The Atomic Development Studio                  *;
;*    ontwikkeld     : 1-12-95                                        *;
;*    laatste update :                                                *;
;*--------------------------------------------------------------------*;
;*    assembleren    : MASM XMS;                                      *;
;*                     LINK XMS;                                      *;
;*                     EXE2BIN XMS XMS.COM                            *;
;*--------------------------------------------------------------------*;
;*    oproep         : XMS [geheugengrootte]                          *;
;**********************************************************************;
          .286                    ;op xt is xms toch niet aanwezig ;-)

;== begin programma ====================================================

code      segment para 'CODE'     ;definitie code-segment
          org 100h
          assume cs:code, ds:code, es:code, ss:code

start:    jmp  xms_init           ;oproep initialiseringsroutine

;== data (blijven in het geheugen) =====================================

nieuwint  proc far

          jmp newint61
          db "NB"                 ;identificatie-bytes
xmspages  db 15                   ;default 16 pagina's van 16KB
xmshandle dw (?)                  ;handle voor xms geheugenblok
xmsdrv    equ this dword          ;startadres xms driver (himem.sys)
xmsofs    dw (?)                  ;offsetadres xms functies
xmsseg    dw (?)                  ;segmentadres xms functies
oudeint   equ this dword          ;oude interruptvector 61h
intoudofs dw (?)                  ;offsetadres interruptvector 61h
intoudseg dw (?)                  ;segmentadres interruptvector 61h
copytbl   dw 8 dup (?)            ;data tabel voor kopieerroutine
command   db (?)                  ;opslag voor atom commando
work      db 16 dup (?)           ;bestemd voor tijdelijke werkruimte

crlf      db 10,13,"$"
comerrm   db 10,13,"ATOM XMS: ongeldig commando #$"
invalpg   db 10,13,"ATOM XMS: ongeldig paginanummer #$"
invaloff  db 10,13,"ATOM XMS: ongeldige offset in page",10,13,"$"
xmserrm   db 10,13,"XMS foutcode #$"

;-----------------------------------------------------------------------
; int 61h interrupt service routine
;-----------------------------------------------------------------------

newint61: push ax                 ;alle registers die
          push bx                 ;veranderen, opslaan
          push cx
          push dx
          push di
          push si
          push es
          push ds
          push cs                ;CS naar stack
          pop  ds                ;als DS terughalen

leescom:  mov  ah,1              ;lees xms commando van Atom
          int  60h
          cmp  al,10h            ;test op geldig commando
          jae  com_err           ;spring indien ongeldig commando
          mov  command,al        ;sla commando op in werkruimte
          xor  ah,ah             ;bereken index voor commando tabel
          shl  ax,1
          mov  di,ax             ;zet offset in index register
          jmp  word ptr comtb[di];spring naar commando
com_err:  mov  dx,offset comerrm ;laadt foutmelding
          mov  ah,09h
          push ax                ;bewaar commando nummer
          int  21h
          pop  ax                ;haal commando nummer terug
          call prthex            ;druk af
          mov  dx,offset crlf    ;cursor naar volgende regel
          int  21h
terug:    pop  ds                ;registerwaarden
          pop  es                ;herstellen
          pop  si
          pop  di
          pop  dx
          pop  cx
          pop  bx
          pop  ax
          iret                   ;einde interrupt routine
nieuwint  endp

;-----------------------------------------------------------------------
; commando tabel
;-----------------------------------------------------------------------
                
comtb:    dw   xmsinfo,xmsldpg,xmsldpg,xmsldpg
          dw   xms_save,xms_load,com_err,com_err
          dw   com_err,com_err,com_err,com_err
          dw   com_err,com_err,com_err,com_err

;-----------------------------------------------------------------------
; subroutines voor commando's
;-----------------------------------------------------------------------

prthex    proc near               ;drukt inhoud van AL hexadecimaal af
          push ax                 ;save registers
          push dx
          mov  dh,al
          mov  ah,2               ;dos functie : tekenuitvoer
          shr  al,4               ;zet hoge nibble in lage nibble
          cmp  al,10              ;test op hexadecimale digit
          jb   hogenibb           ;spring bij gewoon cijfer
          add  al,07              ;maak er een letter van
hogenibb: add  al,'0'             ;maak er een hex digit van
          mov  dl,al              ;zet karakter in dl
          int  21h                ;druk digit af
          mov  al,dh
          and  al,0FH             ;verwaarloos hoge nibble
          cmp  al,10              ;test op hexedecimale digit
          jb   lagenibb           ;spring bij gewoon cijfer
          add  al,07              ;maak er een letter van
lagenibb: add  al,'0'             ;maak er een hex digit van
          mov  dl,al              ;zet teken in dl
          int  21h                ;druk digit af
          pop  dx                 ;haal gebruikte registers terug
          pop  ax
          ret
prthex    endp

getpgnr   proc near               ;test of opgegeven pagina nummer geldig is
          mov  ah,01h             ;lees paginanummer van Atom
          int  60h
          cmp  xmspages,al        ;voer vergelijking uit
          jae  valpage            ;als geldig springen
          push ax                 ;bewaar paginanummer
          mov  ah,09h             ;ongeldige pagina gegeven
          mov  dx,offset invalpg  ;druk foutmelding af
          int  21h
          pop  ax                 ;haal paginanummer retour
          call prthex             ;druk hexadecimaal af
          mov  dx,offset crlf     ;cursor naar volgende regel
          mov  ah,09h
          int  21h
          stc                     ;zet carry, pagina is niet geldig
          jmp  short endtest      ;spring altijd
valpage:  clc                     ;wis carry, pagina is geldig
endtest:  ret                     ;einde routine
getpgnr   endp

adres     proc near               ;leest adres van Atom in bx register
          push ax                 ;save ax
          mov  ah,01h             ;lees lage byte van Atom
          int  60h
          mov  bl,al              ;zet in bl register
          int  60h                ;lees hoge byte van Atom
          mov  bh,al              ;zet in bh register
          sub  bx,4000h           ;offset alleen tussen 0-3FFFh toegestaan
          cmp  bx,4000h
          jb   adres1             ;spring indien offset geldig is
          lea  dx,invaloff        ;druk foutmelding af
          mov  ah,09h
          int  21h
          stc                     ;zet carry voor fout
          jmp  short adres2
adres1:   clc                     ;wis carry
adres2:   pop  ax                 ;haal ax terug
          ret                     ;einde routine met atom adres in bx
adres     endp

xmsadres  proc near               ;bereken adres in xms geheugen
          mov  dx,4000h           ;laadt dx met constante
          xor  ah,ah              ;ax = pagina nummer
          mul  dx                 ;dx:ax = 16k*paginanummer
          add  ax,bx              ;tel daar de offset bij
          ret
xmsadres  endp                    ;offset adres staat nu in dx:ax

xms2buf   proc near               ;kopieer pagina van xms naar buffer
          push ax                 ;save gebruikte registers
          push bx
          push dx
          mov  copytbl[0],4000h   ;zet bloklengte in datatabel
          mov  copytbl[2],0000h
          mov  dx,xmshandle       ;zet handle in datatabel
          mov  copytbl[4],dx
          xor  bx,bx              ;clear offset
          call xmsadres           ;bereken adres in dx:ax
          mov  copytbl[6],ax      ;zet adres in datatabel
          mov  copytbl[8],dx
          mov  copytbl[10],0      ;copy naar conventioneel geheugen
          mov  dx,offset buffer   ;zet buffer adres in tabel
          mov  copytbl[12],dx
          mov  copytbl[14],ds
          mov  ah,0Bh             ;laadt functienummer
          lea  si,copytbl         ;laadt pointer naar tabel
          call dword ptr [xmsdrv] ;voer opdracht uit
          cmp  ax,1               ;functie goed uitgevoerd?
          je   x2bok              ;ja, dan springen
          mov  dx,offset xmserrm  ;nee, dan foutmelding afdrukken
          mov  ah,09h
          int  21h
          mov  ax,bx              ;foutcode naar al
          call prthex             ;druk foutcode af
          mov  dx,offset crlf     ;cursor naar volgende regel
          mov  ah,09h
          int  21h
x2bok:    pop  dx                 ;gebruikte registers terughalen
          pop  bx
          pop  ax
          ret                     ;einde routine
xms2buf   endp

buf2xms   proc near               ;kopieer pagina van buffer naar xms
          push ax                 ;save gebruikte registers
          push bx
          push dx
          mov  copytbl[0],4000h   ;zet bloklengte in datatabel
          mov  copytbl[2],0000h
          mov  copytbl[4],0       ;copy naar xms geheugen
          mov  dx,offset buffer   ;zet buffer adres in tabel
          mov  copytbl[6],dx
          mov  copytbl[8],ds
          mov  dx,xmshandle       ;zet handle in datatabel
          mov  copytbl[10],dx
          xor  bx,bx              ;clear offset
          call xmsadres           ;bereken adres in dx:ax
          mov  copytbl[12],ax      ;zet adres in datatabel
          mov  copytbl[14],dx
          mov  ah,0Bh             ;laadt functienummer
          lea  si,copytbl         ;laadt pointer naar tabel
          call dword ptr [xmsdrv] ;voer opdracht uit
          cmp  ax,1               ;functie goed uitgevoerd?
          je   b2xok              ;ja, dan springen
          mov  dx,offset xmserrm  ;nee, dan foutmelding afdrukken
          mov  ah,09h
          int  21h
          mov  ax,bx              ;foutcode naar al
          call prthex             ;druk foutcode af
          mov  dx,offset crlf     ;cursor naar volgende regel
          mov  ah,09h
          int  21h
b2xok:    pop  dx                 ;gebruikte registers terughalen
          pop  bx
          pop  ax
          ret                     ;einde routine
buf2xms   endp

xmsat2pc  proc near               ;leest xms buffer van Atom
          push ax                 ;save registers
          push di
          mov  ah,01h             ;laadt lees-commando
          mov  di,0000h           ;reset pointer
atom2pc:  int  60h                ;lees byte
          mov  buffer[di],al      ;zet data in buffer
          inc  di                 ;verhoog pointer
          cmp  di,4000h           ;alles gelezen
          jne  atom2pc            ;nee, dan volgende byte
          pop  di                 ;herstel registers
          pop  ax
          ret                     ;einde routine
xmsat2pc  endp

xmspc2at  proc near               ;schrijft xms buffer naar Atom
          push ax                 ;save registers
          push si
          mov  ah,00h             ;laadt schrijf commando
          mov  si,0000h           ;reset pointer
pc2atom:  mov  al,buffer[si]      ;zet data in buffer
          int  60h
          inc  si                 ;verhoog pointer
          cmp  si,4000h           ;alles gelezen
          jne  pc2atom            ;nee, dan volgende byte
          pop  si                 ;herstel registers
          pop  ax
          ret                     ;einde routine
xmspc2at  endp

filename  proc near               ;lees filenaam van atom
          lea  di,buffer          ;laad bufferadres
          push di                 ;bewaar op stack
          mov  ah,01h             ;laad int 60 functienummer
filen1:   int  60h                ;lees byte van Atom
          cmp  al,0Dh             ;einde string
          je   filen2
          cmp  al,00h             ;mag ook eindigen met 0-byte
          je   filen2
          mov  [di],al            ;zet in werkruimte
          inc  di                 ;verhoog pointer
          jmp  short filen1       ;ga volgend karakter lezen
filen2:   mov  byte ptr [di],0    ;sluit filenaam af
          pop  dx                 ;bufferadres terughalen in dx register
          ret                     ;einde routine
filename  endp
                              

;-----------------------------------------------------------------------
; commando's
;-----------------------------------------------------------------------
; functie 0: versie opvragen                            xmsinfo
;   -invoer:  geen
;   -uitvoer: versienummer
;             releasenummer
;             aantal xms pagina's
;
; functie 1: pagina voorzetten                          xmsldpg
;   -invoer:  nieuw paginanummer
;   -uitvoer: 16 kb data
; opmerking: bij dit commando wordt de huidige
;            pagina niet opgeslagen in xmsgeheugen
;
; functie 2: pagina voorzetten                          xmsldpg
;   -invoer:  huidig paginanummer
;             16 kb data
;   -uitvoer: geen
; opmerking: bij dit commando wordt de nieuwe
;            pagina niet gelezen in het atomgeheugen
;
; functie 3: pagina voorzetten                          xmsldpg
;   -invoer:  huidig paginanummer
;             16 kb data
;             nieuw paginanummer
;   -uitvoer: 16 kb data
; opmerking: de huidige pagina wordt opgeslagen in
;            het xms geheugen en de nieuwe pagina
;            wordt in het atomgeheugen gelezen
;
; functie 4: XMS geheugen naar bestand schrijven        xms_save
;   -invoer:  huidig paginanummer
;             16 kb data
;             beginadres: paginanummer, offset
;             eindadres:  paginanummer, offset
;             filenaam incl pad+drive
;   -uitvoer: errorcode
;
; functie 5: XMS geheugen uit bestand lezen             xms_load
;   -invoer:  huidig paginanummer
;             16 kb data
;             loadadres: paginanummer, offset
;             filenaam incl pad+drive
;   -uitvoer: errorcode
;             16 kb data indien errorcode 0
;-----------------------------------------------------------------------

xmsinfo:  mov  ax,01h             ;al=versienummer
          int  60h                ;stuur naar Atom
          mov  al,00h             ;al=release nummer
          int  60h
          mov  al,xmspages        ;al=hoogste beschikbare paginanummer
          int  60h
          jmp  terug              ;einde commando 0

xmsldpg:  mov  al,command         ;laadt commandonummer
          test al,00000001b       ;moet pagina geschreven worden?
          jz   xmsld1             ;nee, dan overslaan
          call getpgnr            ;lees paginanummer
          jc   xmsld2             ;spring als fout
          call xmsat2pc           ;lees pagina in buffer
          call buf2xms            ;kopieer buffer naar xms geheugen
xmsld1:   mov  al,command         ;laadt commandonummer nogmaals
          test al,00000010b       ;moet pagina gelezen worden?
          jz   xmsld2             ;nee, dan overslaan
          call getpgnr            ;lees paginanummer
          jc   xmsld2             ;spring als fout
          call xms2buf            ;kopieer xms geheugen naar buffer
          call xmspc2at           ;stuur buffer naar Atom
xmsld2:   jmp  terug              ;einde commando 1

xms_save: call getpgnr            ;lees paginanummer
          jc   xmsld2             ;spring als fout
          call xmsat2pc           ;lees pagina in buffer
          call buf2xms            ;kopieer buffer naar xms geheugen
          call getpgnr            ;lees beginadres voor save
          jc   xmsld2             ;spring als fout paginanummer
          call adres
          jc   xmsld2             ;spring als fout offset adres
          call xmsadres           ;bereken offset in xms geheugen
          mov  word ptr work[0],ax;zet in werkruimte
          mov  word ptr work[2],dx
          call getpgnr            ;lees eindadres voor save
          jc   xmsld2             ;spring als fout paginanummer
          call adres
          jc   xmsld2             ;spring als fout offset adres
          call xmsadres           ;bereken offset in xms geheugen
          mov  word ptr work[4],ax;berg op in werkruimte
          mov  word ptr work[6],dx
          mov  work[9],00h        ;reset foutcode
          call filename           ;lees filenaam van Atom
          mov  ax,3D01h           ;dos functie: bestand openen
          int  21h
          jnc  save1              ;spring indien geen foutmelding gegeven
          mov  work[9],al         ;zet foutcode
          jmp  save_end
save1:    mov  bx,ax              ;handle naar bx register
          lea  di,buffer          ;laad adres voor header
          mov  ax,00FFh           ;laad header data
          mov  cx,8               ;laad teller
save2:    mov  [di],al            ;plaats data in header
          mov  [di+8],ah
          inc  di                 ;verhoog pointer
          loop save2
          mov  cx,16              ;laad header lengte
          lea  dx,buffer          ;laad adres van buffer
          mov  ah,40h             ;dos functie: bestand schrijven
          int  21h                ;schrijf header naar disk
          jnc  save3              ;spring indien alles goed
          mov  work[9],al         ;zet foutcode
          jmp  save_end
save3:    cmp  ax,16              ;test of alles geschreven is
          je   save4
          mov  work[9],0FFh       ;zet foutcode want disk is vol
          jmp  save_end
save4:    mov  di,bx              ;bewaar handle in hulpregister
sa_while: mov  ax,word ptr work[4];test of eindadres>beginadres
          mov  dx,word ptr work[6]
          sub  ax,word ptr work[0]
          sbb  dx,word ptr work[2]
          jnc  save4a             ;als begin>eind dan niets meer saven
          jmp  save_end
save4a:   sub  ax,4000h           ;compleet blok van 16kb ?
          sbb  dx,0000h
          jc   sa_copy            ;spring indien minder dan 16kb wegschrijven
          mov  ax,4000h           ;meer dan 16kb -> max blokgrootte laden
          xor  dx,dx
sa_copy:  push ax                 ;bewaar ax (blokgrootte)
          mov  copytbl[0],ax      ;zet in kopieertabel
          mov  copytbl[2],dx
          mov  ax,xmshandle       ;zet xms handle in kopieertabel
          mov  copytbl[4],ax
          mov  ax,word ptr work[0];zet xms offset in kopieertabel
          mov  copytbl[6],ax
          mov  ax,word ptr work[2]
          mov  copytbl[8],ax
          mov  copytbl[10],0      ;doelhandle is 0
          lea  ax,buffer          ;adres van buffer in kopieertabel zetten
          mov  copytbl[12],ax
          mov  ax,cs
          mov  copytbl[14],ax
          push bx                 ;bx (filehandle) bewaren
          lea  si,copytbl         ;adres van kopieertabel laden
          mov  ah,0Bh             ;functienummer laden
          call dword ptr [xmsdrv] ;voer opdracht uit
          cmp  ax,1               ;functie goed uitgevoerd?
          je   save5              ;ja, dan springen
          mov  dx,offset xmserrm  ;nee, dan foutmelding afdrukken
          mov  ah,09h
          int  21h
          mov  ax,bx              ;foutcode naar al
          call prthex             ;druk foutcode af
          mov  dx,offset crlf     ;cursor naar volgende regel
          mov  ah,09h
          int  21h
save5:    pop  bx                 ;haal filehandle terug
          pop  cx                 ;haal bloklengte terug in cx
          lea  dx,buffer
          mov  ah,40h
          int  21h                ;schrijf blok naar file
          jnc  save6              ;spring indien goed gegaan
          mov  work[9],al         ;foutcode wegzetten
          jmp  save_end
save6:    cmp  ax,cx              ;test of alle bytes geschreven zijn
          je   save7
          mov  work[9],0FFh       ;nee, dan foutcode 'disk vol'
          jmp  save_end
save7:    mov  ax,word ptr work   ;verhoog beginadres
          mov  dx,word ptr work[2]
          add  ax,4000h           ;door er 4000h bij op te tellen
          adc  dx,0000h
          mov  word ptr work,ax   ;resultaat wegschrijven
          mov  word ptr work[2],dx
          jmp  sa_while           ;spring naar begin van lus
save_end: mov  ah,3Eh             ;file sluiten
          int  21h
          mov  al,work[9]         ;status doorsturen naar Atom
          mov  ah,00h
          int  60h
          jmp  terug

load_err: jmp  terug

xms_load: call getpgnr            ;lees paginanummer
          jc   load_err           ;spring als fout
          call xmsat2pc           ;lees pagina in buffer
          call buf2xms            ;kopieer buffer naar xms geheugen
          call getpgnr            ;lees beginadres voor save
          jc   load_err           ;spring als fout paginanummer
          call adres
          jc   load_err           ;spring als offset adres ongeldig is
          call xmsadres           ;bereken offset in xms geheugen
          mov  word ptr work[0],ax;berg op in werkruimte
          mov  word ptr work[2],dx
          mov  work[9],00h        ;reset foutcode
          call filename           ;lees filenaam van Atom
          mov  ax,3D00h           ;dos functie: bestand openen
          int  21h
          jnc  load1              ;spring indien geen foutmelding gegeven
          mov  work[9],al         ;zet foutcode
          jmp  short load_end
          ; ......
load1:
load_end:


;-----------------------------------------------------------------------
; 16 kb xms buffer voor uitwisseling van data met xms geheugen
;-----------------------------------------------------------------------

          nop                     ;nopjes om buffer goed te zetten
          nop
          nop

buffer    equ this byte

;-----------------------------------------------------------------------
; Initialisering en de‹nstallatie routine
;-----------------------------------------------------------------------

;== data ===============================================================

installm1 db 13,10,"ATOM XMS v1.00f door Roland Leurs",13,10
          db "(c) 1995 Atomic Development Studio",13,10,10
          db "Driver is ge‹nstalleerd. Geheugengrootte: $"
installm2 db " kb.",13,10,"Opnieuw oproepen om te de‹nstalleren.",13,10,"$"
gedeinst  db 13,10,"ATOM XMS gede‹nstalleerd.",13,10,"$"
geenxms   db 13,10,"ATOM XMS is niet ge‹nstalleerd omdat er geen of een",13,10
          db "te oude driver (bijv. himem.sys) geladen is.",13,10,"$"
parerror  db 13,10,"Ongeldige waarde voor XMS grootte.",13,10,"$"
xmserror  db 13,10,"XMS error",13,10,"$"

;-- start en initialiseringsroutine ------------------------------------

xms_init  proc near

          mov  ax,3561h           ;inhoud interruptvector 61 halen
          int  21h                ;DOS-functie oproepen
          cmp  word ptr es:[bx+3],"BN" ;testen op XMS
          jne  install            ;nog niet ge‹nst. --> installeren

          ;-- ATOM XMS de‹nstalleren ------------------------------------

          mov  dx,es:intoudofs    ;offsetadres interrupt 61h
          mov  ax,es:intoudseg    ;segmentadres interrupt 61h
          mov  ds,ax              ;naar DS
          mov  ax,2561h           ;inhoud interruptvector 61h
          int  21h                ;weer naar oude routine verleggen
          mov  ah,49h             ;conventioneel geheugen oude ATOM XMS
          int  21h                ;weer vrijgeven
          mov  ah,0Ah             ;xms geheugen vrijgeven
          mov  dx,es:[bx+6]       ;lees xms-handle
          call dword ptr es:[bx+8];roep xms driver aan
          push cs                 ;CS op stack opslaan
          pop  ds                 ;als DS terughalen
          mov  dx,offset gedeinst ;melding: programma gede‹nstalleerd
          mov  ah,9               ;functienummer: string uitvoeren
          int  21h                ;DOS-functie oproepen
          mov  ax,4C00h           ;code: prog. correct uitgevoerd
          int  21h                ;programma be‰indigen met return-code

          ;-- ATOM XMS installeren -------------------------------------

install:  mov  intoudseg,es       ;segment-/offsetadres
          mov  intoudofs,bx       ;interruptvector 61h opslaan
          mov  ax,4300h           ;test of himem.sys geladen is 
          int  2fh
          cmp  al,80h             ;als himem niet geladen is
          je   himem              ;verder gaan
nohimem:  mov  dx,offset geenxms  ;foutmelding
          mov  ah,9               ;functienummer:string uitvoeren
          int  21h                ;DOS-functie oproepen
          mov  ax,4C01h           ;programma be‰indigen met foutcode 1
          int  21h

invalid:  mov  dx,offset parerror ;foutmelding
          mov  ah,9               ;functienummer:string uitvoeren
          int  21h                ;DOS-functie oproepen
          mov  ax,4C02h           ;programma be‰indigen met foutcode 2
          int  21h

himem:    mov  ax,4310h           ;adres voor xms functies opvragen
          int  2fh
          mov  xmsofs,bx          ;berg adres xms functies op
          mov  xmsseg,es
          mov  ah,00              ;xms versienummer opvragen
          call dword ptr [xmsdrv]
          cmp  ah,2               ;test op versie 2 of hoger
          jb   nohimem            ;lager mag niet => foutmelding

          mov  bx,80h             ;zet pointer op begin van commandline
skipspc:  call leescmd            ;lees karakter
          cmp  al,' '             ;negeer spatie
          je   skipspc
          xor  dx,dx              ;parameter komt in dx
          xor  ah,ah
digit:    cmp  al,0Dh             ;test op einde invoer
          je   asc2bin            ;spring bij einde regel
          cmp  al,' '             ;spatie is ook einde invoer
          je   asc2bin            ;dan dus ook springen
          cmp  al,'0'             ;test op geldig digit
          jb   invalid            ;spring indien ongeldig teken
          cmp  al,'9'
          ja   invalid
          sub  al,'0'             ;converteer al naar binaire waarde
          imul dx,10              ;dx=dx*10+al
          add  dx,ax
          call leescmd            ;lees volgende digit
          jmp  short digit
asc2bin:  cmp  dx,1000h           ;test op ongeldige waarde
          ja   invalid            ;spring indien te groot
          shr  dx,4               ;bereken aantal pagina's van 16 kb
          cmp  dx,0               ;test resultaat
          je   resxms             ;parameter te klein, gebruik default waarde
          dec  dx                 ;bepaal hoogste pagina nummer
          mov  xmspages,dl        ;berg resultaat op

resxms:   mov  dl,xmspages        ;laadt aantal gewenste pagina's
          inc  dx                 ;tel er 1 bij op
          shl  dx,4               ;maak er het aantal kb van
          mov  ah,09h             ;laadt xms functienummer
          call dword ptr [xmsdrv] ;probeer geheugen te reserveren
          cmp  ax,0001h           ;test resultaat
          je   succes             ;spring indien het geheugen gereserveerd is
          dec  xmspages           ;geheugen niet beschikbaar
          cmp  xmspages,0ffh      ;probeer kleinere hoeveelheid
          jne  resxms             ;maar ooit houdt het op
          push bx                 ;bewaar errorcode
          mov  dx,offset xmserrm  ;geheugen niet gereserveerd
          mov  ah,09h             ;dos functie
          int  21h                ;string afdrukken
          pop  bx                 ;haal errorcode van stack
          mov  al,bl              ;zet in al
          call prthex             ;druk foutnummer af
          mov  dx,offset crlf     ;cursor naar volgende regel
          int  21h
          mov  ax,4303h           ;programma be‰indigen met foutcode 3
          int  21h

succes:   mov  xmshandle,dx       ;berg handle op
          mov  dx,offset nieuwint ;offsetadres nieuwe interrupt-routine
          mov  ax,2561h           ;inhoud interruptvector 61 naar
          int  21h                ;eigen routine verleggen
          mov  dx,offset installm1;melding: programma ge‹nstalleerd
          mov  ah,9               ;functienummer: string uitvoeren
          int  21h                ;DOS-functie oproepen
          xor  ah,ah              ;ah effe 0 maken
          mov  al,xmspages        ;bereken aantal MB xms geheugen
          inc  ax
          shl  ax,4               ;vermenigvuldig met 16
          lea  bx,buffer+5        ;laadt bx met tijdelijke buffer
          mov  byte ptr [bx],'$'  ;is einde van de string
          mov  si,10              ;laadt si om later door 10 te delen
deel:     xor  dx,dx              ;maak meest sign. bits van deeltal 0
          div  si                 ;deel ax door 10
          add  dx,'0'             ;converteer de rest naar ascii code
          dec  bx                 ;verlaag pointer
          mov  [bx],dl            ;zet ascii code in string
          or   ax,ax              ;alles gedaan?
          jnz  deel               ;nee, dan volgende digit omzetten
          mov  dx,bx              ;zet begin van den buffer in dx
          mov  ah,09h             ;druk string af
          int  21h
          mov  dx,offset installm2;druk laatste stuk tekst af
          mov  ah,09h             ;druk string af
          int  21h

          ;-- alleen het PSP, de nieuwe interrupt-routine en de -------
          ;-- bijbehorende data hoeven resident te blijven ------------

          lea  dx,buffer          ;aantal paragraphs van 16 bytes
          add  dx,4000h
          mov  cl,4               ;berekenen, dat gereserveerd
          shr  dx,cl              ;moet blijven
          inc  dx
          mov  ax,3100h           ;programma met return-code 0 (o.k)
          int  21h                ;be‰indigen, maar resident blijven
xms_init  endp

leescmd   proc near
          inc  bx                 ;verhoog geheugenpointer
          mov  al,[bx]            ;lees karakter
          ret                     ;einde routine
leescmd   endp


;== einde ==============================================================

code      ends                    ;einde code-segment
          end  start
