; dpmitest.asm
;
; a simple DPMI test facility
;
; written on 20 April 1996 by Edward J. Beroset
;
        .MODEL small
        .STACK 400h
        .386
        .DATA
errmsg1 db      "ERROR: No DPMI host was not found.",13,10,'$'
errmsg2 db      "ERROR: Unable to allocate DOS memory.",13,10,'$'
errmsg3 db      "ERROR: Unable to switch to prot mode.",13,10,'$'
errmsg4 db      "ERROR: DPMI memory allocation failed.",13,10,'$'
ok_msg  db      "Everything worked just fine.",13,10,'$'

DPMI_vector     dd      ?

MEM_BLOCK_SIZE  = 16 * 1024 * 1024      ; try to allocate 16M of memory

DPMI_MEM_ALLOC  = 0501h     ; allocate a block of memory
DPMI_MEM_FREE   = 0502h     ; free allocated block of memory

DPMI_Int macro function
        mov     ax,function
        int     31h
endm

DOS_MEM_ALLOC   = 048h
DOS_WRITE_TTY   = 009h

DOS_Int macro function, subfunction
        ifnb <subfunction>
        mov     ax,(function SHL 8) OR (subfunction AND 0ffh)
        else
        mov     ah,function
        endif
        int     21h
endm

        .CODE
Start proc
        .STARTUP
        mov     ax,1687h                ; DPMI installation check
        int     2fh                     ;  via int 2Fh
        or      ax,ax                   ; Q: is DPMI installed?
        mov     dx,offset errmsg1       ;
        jnz     Exit                    ;   N: exit with error message
        mov     WORD PTR [DPMI_Vector],di   ; DPMI vector returned in es:di
        mov     WORD PTR [DPMI_Vector+2],es ;
        test    si,si                   ; Q: need memory for DPMI?
        jz      GoProtNow               ;   N: skip allocation
        mov     bx,si                   ; ask for just the amount it needs
        DOS_Int <DOS_MEM_ALLOC>         ; do the request
        mov     dx,offset errmsg2       ;
        jc      Exit                    ; skip out on error
        mov     es,ax                   ; otherwise, save block's segment
GoProtNow:                              ;
        xor     ax,ax                   ; 16-bit DPMI
        call    [DPMI_Vector]           ; do a call (effectively)
        mov     dx,offset errmsg3       ;
        jc      Exit                    ; if it fails, bail out
        ;
        ; we're now in protected mode...
        ;
        mov     bx,MEM_BLOCK_SIZE SHR 16     ; try to grab some memory
        mov     cx,MEM_BLOCK_SIZE AND 0FFFFh ; BX:CX = size in bytes
        DPMI_Int <DPMI_MEM_ALLOC>       ; try to allocate a block
        mov     dx,offset errmsg4       ;
        jc      Exit                    ; if call failed, bail out
        DPMI_Int <DPMI_MEM_FREE>        ; now free the memory block
        mov     dx,offset ok_msg        ; we're done
Exit:
        DOS_Int <DOS_WRITE_TTY>         ;
        .EXIT 0
Start endp
        END
