;-------------------------
; isprot.asm by Yousuf Khan

comment *

        Purpose: To detect whether a processor is running protected
        mode, and to display what DOS extender standards it conforms to.

        Author: Yousuf Khan, donated to public domain

        Version: 1.0

        *

.model tiny
.data
        memflags        record  dpmi:1,vcpi:1,ems:1,xms:1,prot:1
        types_found     memflags <0,0,0,0,0>    ;what types were found?
        emm_name        db      'EMMXXXX0', 0   ;EMM handle name
        copyright       db      'ISPROT 1.0: Protected mode analyzer, '
                        db      '(c) 1994, Yousuf J. Khan',13,10,'$'
        protmsg         db      'Protected mode: $'
        xmsmsg          db      'XMS driver: $'
        emsmsg          db      'EMS driver: $'
        vcpimsg         db      'VCPI driver: $'
        dpmimsg         db      'DPMI driver: $'
        found           db      'yes',13,10,'$'
        notfound        db      'no',13,10,'$'
.code
        org     100h
start:
        ;first test for protected mode
        .386p
        smsw    ax
        and     ax, 1
        cmp     ax, 1
        jne     not_prot
        or      types_found, mask prot
not_prot:
        ;now test for XMS
        mov     ax, 4300h
        int     2fh
        cmp     al, 80h
        jne     no_xms
        or      types_found, mask xms
no_xms:
        ;now test for EMS
        lea     dx, emm_name    ;"EMMXXXX0" name of handle to open
        mov     ax, 3d00h
        int     21h             ;open file handle
        jc      short no_ems    ;handle not found, must be no EMS
        mov     bx, ax          ;store file handle # in BX
        mov     ax, 4400h       ;IOCTL: get device info
        int     21h
        jc      short no_ems    ;error occurred, must be no EMS
        test    dx, 80h         ;if 7th bit clear, file handle must
        jz      short no_ems    ; be a file, but not dev drvr
        mov     ax, 4407h
        int     21h
        push    ax              ;store result of fnct.
        mov     ah, 3eh
        int     21h             ;close file handle
        pop     ax
        cmp     al, 0ffh        ;EMS device ready? If yes, AL=0FFh.
        jne     short no_ems
        or      types_found, mask ems
no_ems:
        ;now test for VCPI
        mov     ah, types_found
        and     ah, mask ems   ;if no EMS, then no VCPI
        cmp     ah, 0
        je      no_vcpi
        ;test for 386+
        pushf
        xor     ax, ax
        push    ax
        popf
        pushf
        pop     ax
        test    ax, 0f000h
        je      short not_386   ;upper four bits of FLAG register not
                                ;settable, must be less than a 386
        popf
        jmp     short keep_checking
not_386:
        popf                    ;No 386? Can't have VCPI either
        jmp     no_vcpi
keep_checking:                  ;keep checking for VCPI
        ;
        ;Now we found EMS & 386. But is it VCPI?
        ;
        mov     bx, 1           ;# of pages to allocate
        mov     ah, 43h         ;get EMS handle and allocate
        int     67h             ; memory
        cmp     ah, 0           ;fnct completed successfully if 0
        jne     short no_vcpi
        push    dx              ;save EMS handle
        mov     ax, 0de00h      ;VCPI installation check
        int     67h
        pop     dx              ;retrieve EMS handle
        push    ax              ;save VCPI detection flag
        mov     ah, 45h
        int     67h             ;release EMS handle
        pop     ax
        cmp     ah, 0
        jne     short no_vcpi   ;if AH<>0, no VCPI
        or      types_found, mask vcpi
no_vcpi:
        ;now test for DPMI
        mov     ax, 1687h
        int     2fh
        cmp     ax, 0
        jne     no_dpmi
        or      types_found, mask dpmi
no_dpmi:
        ;now let's start displaying what we found
        mov     dx, offset copyright
        mov     ah, 9
        int     21h
        mov     dx, offset protmsg
        mov     ah, 9
        int     21h
        mov     ah, types_found
        and     ah, mask prot
        cmp     ah, 0
        je      @1
        call    foundmsg
        jmp     @2
@1:
        call    notfoundmsg
@2:
        mov     dx, offset xmsmsg
        mov     ah, 9
        int     21h
        mov     ah, types_found
        and     ah, mask xms
        cmp     ah, 0
        je      @3
        call    foundmsg
        jmp     @4
@3:
        call    notfoundmsg
@4:
        mov     dx, offset emsmsg
        mov     ah, 9
        int     21h
        mov     ah, types_found
        and     ah, mask ems
        cmp     ah, 0
        je      @5
        call    foundmsg
        jmp     @6
@5:
        call    notfoundmsg
@6:
        mov     dx, offset vcpimsg
        mov     ah, 9
        int     21h

        mov     ah, types_found
        and     ah, mask vcpi
        cmp     ah, 0
        je      @7
        call    foundmsg
        jmp     @8
@7:
        call    notfoundmsg
@8:
        mov     dx, offset dpmimsg
        mov     ah, 9
        int     21h
        mov     ah, types_found
        and     ah, mask dpmi
        cmp     ah, 0
        je      @9
        call    foundmsg
        jmp     @a
@9:
        call    notfoundmsg
@a:
        mov     al, types_found         ;use flags as exit errorlevel
        mov     ah, 4ch         ;end program
        int     21h


foundmsg        proc
        mov     dx, offset found
        mov     ah, 9
        int     21h
        ret
        endp

notfoundmsg     proc
        mov     dx, offset notfound
        mov     ah, 9
        int     21h
        ret
        endp

        end     start


