Category : Assembly Language Source Code
Archive   : PROTEC.ZIP
Filename : EN.ASM

 
Output of file : EN.ASM contained in archive : PROTEC.ZIP
;******************************************************************
;program: en.asm by Shirley Her and Sen-Cuo Ro, NexGen Micro Sys.
;reviewed and supplemented by: R. Richardson
;purpose: This program shows the way to enter and leave
; the protected mode from DOS real-address mode.
; From chapter 4: "i386/i486 ADVANCED PROGRAMMING"
; copyright (c) 1993 by Van Nostrand Reinhold
; ISBN 0-442-01377-9 from Compubooks: (800) 880-6818
;******************************************************************

.386p ;p=enable highest privilege

INCLUDE STRUCT
INCLUDE MACRO1
INCLUDE MACRO2 ;Steps 0,1,2,3,4 in MACRO2
INCLUDE MACRO3 ;Step 5 - all DS segment
INCLUDE MACRO4 ;Steps 6, 7, 8

;-------------------------------
; STEP 8A
; CODE Segment
;-------------------------------

code segment para public use16 'code'
assume cs:code,ds:gdata
main proc far

st_art:
push ds ;first 10 instructions tell
mov ax,0 ;EDMOD where to return
mov ds,ax
mov di,300h
mov ax,cs
mov [di],ax
mov di,382h
mov al,'E' ;E = .exe file C = .com file
mov [di],al
pop ds
db 15 dup(90h) ;nops for EDMOD's return
be_gin: ;restart here
call flopof ;floppy motor off IF on
call zero_empty ;zero out unused code segment
call new_chars
call cursof ;cursor off
mov ax,gdata
mov ds,ax ;put in DS
cmp byte ptr savdh,2
jz sav_file
cmp byte ptr savdh,3
jz res_file
cmp byte ptr savdh,4
jz unpakw4
jmp init

;-------------------------------------------------
; STEP 8B:
; save or restore `typed.dat` file from C:\PROTECT
;-------------------------------------------------

sav_file: mov ah,3ch
mov cx,0 ;read/write
mov dx,ty_ped ;file name
int 21h ;open/create file
mov bx,ax ;file hnadle
nop
mov ah,40h
mov cx,4000
mov dx,hold_video
int 21h ;write file
nop
mov ah,3eh
int 21h ;close file
mov byte ptr savdh,2
jmp init

res_file: mov ax,3d00h ;open read
mov dx,ty_ped ;file name
int 21h
mov bx,ax ;file handle
nop
mov ah,3fh
mov cx,4000
mov dx,hold_video
int 21h ;read file
nop
mov ah,3eh
int 21h ;close file
mov byte ptr savdh,3

;-----------------------------------------
; STEP 9:
; initialize Interrupt Descriptor Table
;-----------------------------------------

init: mov ax,IDT ;get IDT segment address
mov es,ax ;put in ES
mov di,offset idt_tab ;get IDT offset address
mov ax,offset int_entry ;get interrupt service address
mov cx,INTNO ;get interrupt number
fillidt:
mov es:[di],ax ;put entry address in IDT
add di,DSCPSIZE ;adjust address in IDT
add ax,INTSIZE ;adjust interrupt service addrs
;the size of each routine is
;defined in INTSIZE
loop fillidt ;keep filling

;--------------------------------------
; STEP 10:
; get GDT/IDT limit & linear address
;--------------------------------------

mov ax,offset gdt_limit ;get GDT segment limit
mov pGDT_limit,ax ;put in pGDT_limit
xor eax,eax ;clear eax
mov ax,GDT ;get GDT segment address
shl eax,4 ;convert to 32 bit linear addrez
mov pGDT_addr,eax ;put in pGDT_addr

mov ax,offset idt_limit ;get IDT segment limit
mov pIDT_limit,ax ;put in pGDT_limit
xor eax,eax ;clear eax
mov ax,idt ;get IDT segment address
shl eax,4 ;convert to 32 bit linear addrez
mov pIDT_addr,eax ;put in pIDT_addr

;---------------------------------------------------
; STEP 11:
; base on gdt_phys_tab to set linear base address
; for each corresponding descriptor
;---------------------------------------------------

mov ax,GDT ;get gdt segment address
mov es,ax ;put in ES
mov si,offset gdt_phys_tab ;get address of gdt_phys_tab
mov cx,gdt_tab_size ;get gdt_phys_tab size
bdt1:
lodsw ;get descriptor number
mov bx,ax ;put in BX
and bx,0fff8h ;mask off TI bit and RPL
lodsw ;get corresponding seg address
;for the above descriptor
push ax ;save it
shl ax,4 ;get lower 4 bytes offset
mov es:[bx][d_base1],ax ;save it in descriptor base1
pop ax ;restore segment address
shr ax,12 ;get the highest byte
mov es:[bx][d_base2],al ;save it in descriptor base2
loop bdt1 ;continue

;----------------------------
; STEP 12:
; switch to protected mode
;----------------------------

cli ;clear interrupts
lgdt [pGDT] ;load GDT address+limit in GDTR
lidt [pIDT] ;load IDT address+limit in IDTR
mov eax,cr0 ;get cr0 register
or al,prot_enable ;set protected mode enable
mov cr0,eax ;restore cr0

jmp dword ptr cs:[enter_prot] ;far jump flush instruct. queue

enter_prot:
dw offset now_in_prot ;EIP
dw code_selec ;code segment selector

;------------------------------
; STEP 13:
; execute in portected mode,
; set LDTR,SS,SP,DS,ES,FS,GS
;------------------------------

now_in_prot:
xor ax,ax ;clear ax
lldt ax ;load NULL seclector to LDTR
mov ax,stk0_selec ;get stack segment selector
mov ss,ax ;put in SS
mov sp,offset stk0_limit ;set stack pointer
mov ax,gdata_selec ;get data segment selector
mov ds,ax ;put in DS
mov ax,video_selec
mov es,ax ;put in ES
mov ax,fsseg_selec
mov fs,ax ;put in FS
mov ax,gsseg_selec
mov gs,ax ;put in GS

;-------------------------------------
; STEP 14:
; display message in protected mode
;-------------------------------------

cmp byte ptr saval,1
jz skip_it ;skip introduction two pages

mov si,offset frame3 ;diz intro page only 1st time
mov di,0
call disp_it
call pr_ess ;wait key pressed
call re_lease ;wait key released
mov byte ptr saval,1
jmp rsto

skip_it: cmp byte ptr savdh,1 ;after reset FS seg continue
jz int_table
cmp byte ptr savdh,2
jz fyx
cmp byte ptr savdh,3
jz ole_file
ski: call cls
call frame_it ;draw rectangle
mov si,offset in_protected ;protected mode message address
mov di,172 ;display address
call disp_it ;call display procedure
mov si,he_lp ;help message
mov di,32 ;display address
call disp_it ;display help message
mov ax,ds:[savax] ;is fseg set to 0000 ?
cmp ax,0
jnz ri2 ;if not, don`t diz message
mov di,offset this_fs ;diz `this is real mode segment
mov si,246h ;zero diz in protected mode`
ri1: mov al,[di]
cmp al,0
jz ri2
inc di
mov fs:[si],al ;fs seg intialized at 0000
inc si
jmp ri1
ri2: nop

;---------------------------------------------
; STEP 14A:
; keyboard input decode - press Esc to exit
;---------------------------------------------

call dizsp ;display stack pointer
mov di,[savdi] ;video line on
cmp di,0 ;0 on initialize
jnz tz1 ;if not ignore
mov di,656 ;if so
mov [savdi],di ;set begin
mov byte ptr es:[di],5fh ;and display cursor
tz1: mov bp,0 ;initialize
mov ax,ds:line ;position on video line
cmp ax,0 ;if so, cursor already set
jz bb0
shl ax,1 ;times 2
add di,ax
mov word ptr es:[di],075fh ;cursor underline on video
bb0: call dizsp
call kybd1 ;KISS protect mode kybd decode
call key_delay
jmp bb0

;------------------------------
; STEP 15:
; load TSS to TR
;------------------------------

bb4: ;begin exit protected mode
mov ax,task0_TSS_selec ;TSS selector for current task
; ltr ax ;load into task register

;-----------------------------------
; STEP 16:
; switch back to real mode
;-----------------------------------

int 20 ;= int 14h

;--------------------------------------
; STEP 17:
; Interrupt Service Routine
;--------------------------------------

int_entry: ;entry point for interrupt service routine

REPT INTNO ;number interrupts
call disp ;diz exit interrupt message
iret ;note
ENDM

;----------------------------------------
; STEP 18:
; get interrupt number and display it
;----------------------------------------

disp:
pop ax ;get return address from stack
cmp bp,3
jb is1
jmp go_exit
is1: sub ax,offset int_entry ;offset from interrupt entry
shr ax,TWO ;divide by 4 to get int. number
mov si,offset int_num ;get ascii code address
mov cx,TWO ;convert to 2 ascii code
call htoa ;call convert procedure
mov si,offset int_msg ;get interrupt message address
mov di,332 ;get display address
call disp_it ;call display procedrue
cmp word ptr [int_num],3431h ;int 14h ?
jz go_exit
mov si,offset ex_cept ;exception message
mov di,360
call disp_it ;display it
mov si,offset in_real ;diz now in real mode
mov di,172
call disp_it
mov word ptr savdi,0
mov word ptr line,0
call cls1 ;clear hold_video

;-----------------------------------
; STEP 19:
; Return to real mode
;-----------------------------------

go_exit:
mov ax,dmy_selec ;dummy selector
mov es,ax ;reset segment registers
mov ds,ax
mov fs,ax
mov gs,ax
mov ss,ax

mov eax,cr0 ;get CR0
and eax,not prot_enable ;disable protected mode
mov cr0,eax ;update it

db 0eah ;far jump to flush instruction queue
dw offset next_instruction ;new EIP
dw code ;new CS

;----------------------------------
; STEP 20:
; execute in real mode,
; set DS,SS and SP.
;----------------------------------
next_instruction:
mov ax,Gdata ;get data segment address
mov ds,ax ;put in DS
mov ax,stk0 ;get stack segment address
mov ss,ax ;put in SS
mov sp,offset stk0_limit ;set stack pointer

;-----------------------------------
; STEP 21:
; set IDTR to DOS interrupt table
;-----------------------------------

lidt [pold] ;load DOS interrupt vector table to IDTR
sti ;enable maskable interrupts

;------------------------------------------------
; STEP 22:
; N = terminate this process go to DOS> prompt
; Y = go to EDMOD
; Enter = return to protected mode
; your choice
;------------------------------------------------

push cs ;calls not allowed here
pop ds ;as stack buggered up
cmp bp,3
jz ed_mod ;fast go to edmod
cmp bp,4
jae be_gin ;millisec reset protected mode

mov ah,2
mov bh,0
mov dx,180ch
int 10h ;set cursor bottom line

mov ah,9
mov dx,ss2
int 21h ;diz instructions bottom line

wait_key: mov ah,0
int 16h
cmp ah,15h ;Y --> EDMOD
jz ed_mod
cmp ah,31h ;N --> diz DOS> prompt
jz ss0
cmp ah,1ch ;Enter --> start over
jz be_gin
jmp wait_key

ed_mod: mov eax,90008011h ;9000h:8011h
mov dword ptr [farproc],eax ;edmod.obj jmp far address
push ds ;[farproc] up high out of way
mov ax,0
mov ds,ax
mov di,246h
mov cx,26
wp: mov [di],ax
add di,2
loop wp ;wipe out this protected msg
mov ax,9000h
mov ds,ax
mov di,8000h
mov al,[di] ;edmod's 1st two bytes
cmp al,0e9h
pop ds
jnz ed_mod2 ;not there, so load it
jmp farproc ;ok it is there, so far jump

ed_mod2: mov ax,3d02h ;open read/write
lea dx,offset ss1 ;edmod.obj ASCIIZ string
int 21h ;OPEN edmod.obj
jc beep ;beep if not in C:\PROTECT
mov bx,ax

push ax
mov ax,9000h
mov ds,ax ;load edmod.obj to 9000h:8000h
pop ax
mov ah,3fh ;read
mov cx,28000 ;length
mov dx,8000h
int 21h ;READ edmod.obj
jc beep ;bad read

mov ah,3eh
int 21h ;CLOSE edmod.obj
jc beep ;bad close

push cs
pop ds
jmp farproc ;jmp far 9000h:8011h to EDMOD

beep: mov ah,2
mov dl,7
int 21h ;2 beeps if bad read EDMOD.OBJ
mov ah,2
mov dl,7
int 21h

ss0: mov ax,3
int 10h ;cls
call curson ;cursor on
mov ax,4c00h ;go to DOS>
int 21h ;exit

ss1: db 'C:\PROTECT\EDMOD.OBJ',0 ;must be here to read it
ss2: db 'press Y for EDMOD - N for DOS> prompt - Enter to restart$'

main endp

;--------------------------------------------------------
; procedure: disp_it
; display string in protected mode
; input: ds:si -> string address + di -> video address
; the end of the string must be 0
;--------------------------------------------------------

disp_it proc near
mov ax,video_selec ;get video segment selector
mov es,ax ;put in ES
mov ah,attribute ;display attribute
mov [savdi1],di ;save video line
disp_it1:
lodsb ;get display character
cmp al,0dh ;carriage return
jz dis2 ;start next line down
cmp al,0 ;end of display character ?
jz dis1 ;all done
stosw ;put it on video screen
jmp disp_it1 ;continue
dis1: ret ;so return
dis2: mov di,[savdi1] ;set next line down
add di,160
mov [savdi1],di
jmp disp_it1

disp_it endp

;------------------------------------------
; procedure: htoa
; Convert hexdecimal code to ASCII code
; input: si--> address to put ASCII code
; cx--> hexdecimal code size
; eax--> hexdecimal code
;------------------------------------------

htoa_tab db '0123456789ABCDEF'

htoa proc near
xor ebx,ebx ;clear EBX
add si,cx ;adjust target address
dec si ;fix it
htoa1:
mov bl,al ;get hexdecimal code
and bl,0fh ;distinguish it
mov bl,cs:[htoa_tab][ebx] ;get indexed ascii character
mov byte ptr [esi],bl ;place in target address
dec esi ;adjust target address
shr eax,4 ;get rid of this hex code
loop htoa1 ;continue
ret ;return
htoa endp

;-------------------------------------------------
; procedure: kybd_in (mini-KISS kybd decoder)
; Test kybd input via ports 64h and 60h
; If valid convert and display
; at -->es:[di] + inc/dec video on-line counter
;-------------------------------------------------

kybd_in proc near

ky1: ret ;if so, ignore - ret BB0 +

ky2: mov bp,0 ;lower case pointer
jmp kybd1

ky3: mov bp,1 ;UPPER case pointer

kybd1: in al,64h ;8042 keyboard controller status register
test al,1 ;output-buffer full bit
jz kybd1 ;wait till full
in al,60h ;keyboard data output buffer

cmp al,170 ;left shift key released
jz ky2 ;set bp,0 = lower case
cmp al,182 ;right shift key released
jz ky2 ;set bp,0 = lower case
cmp al,80h ;release key code bit 7 set
jae ky1 ;ignore
cmp al,42 ;left shift key pressed
jz ky3 ;set bp,1 = UPPER case
cmp al,54 ;right shift key pressed
jz ky3 ;set bp,1 = UPPER case
cmp ds:[las_one],al ;previous keyboard character
jnz kybd2
cmp byte ptr ds:[count1],1 ;initial delay already done
jz kybd3
call re_peat ;1/2 sec delay before normal
jmp kybd3 ;(typematic like) repeat
kybd2: mov byte ptr ds:[count1],0 ;not dupe so reset
kybd3: cmp al,56 ;Alt key
jz dizupper ;do extended ASCII 0 to 255
cmp al,1 ;Esc key
jz ky9 ;begin exit to DOS> real mode
cmp al,28 ;enter key
jz ky20 ;move down begin next line
cmp al,81 ;PgDn key
jz ky8 ;bottom line
cmp al,83 ;delete key
jz ky1 ;ignore Del key
cmp al,58 ;Caps Lock key
jz ky1 ;ignore
cmp al,55 ;Print Screen
jz prt_scn
cmp bp,1 ;upper case pointer
jz up_fkey ;if z check shift F1-F12 +

cmp al,59 ;F1 key
jz diz_hlp1
cmp al,60 ;F2 key
jz diz_hlp2
cmp al,61 ;F3 key
jz diz_hlp3
cmp al,62 ;F4 key
jz diz_hlp4
cmp al,63 ;F5 key
jz diz_hlp5
cmp al,64 ;F6 key
jz diz_hlp6
cmp al,65 ;F7 key
jz diz_hlp7
cmp al,66 ;F8 key
jz sim_edmod ;display CS DS ES FS GS segs
cmp al,67 ;F9 key
jz diz_hlp9 ;change FS/GS seg start adrez
cmp al,68 ;F10 key
jz diz_hlp10 ;diz control-debug-flags regs
cmp al,87 ;F11 key
jz diz_hlp11 ;shift F1 thru shift F11 menu
cmp al,88 ;F12 key
jz diz_int ;diz interrupt vectors

up_fkey:
cmp al,59 ;shift F1
jz dizhi ;diz 256 characters
cmp al,60 ;shift F2
jz tezgs ;test memory size segment gs
cmp al,61 ;shift F3
jz save_file ;save `typed in page' file
cmp al,62 ;shift F4
jz rstor_file ;restore `typed in page` file
cmp al,63 ;shift F5
jz sho_vga ;diz vga graphics
cmp al,64 ;shift F6
;use whatever you wish
cmp al,65 ;shift F7
; "
cmp al,66 ;shift F8
; "
cmp al,67 ;shift F9
; "
cmp al,68 ;shift F10
; "
cmp al,87 ;shift F11
; "
cmp al,88 ;shift F12
; "
cmp al,29 ;Ctrl key
jz go_edmod ;fast go to real mode edmod
;also Pause/Break key on PS/2

cmp al,70 ;Scroll Lock
; jz diz_anything ;diz anything in EAX for test

cmp al,14 ;backspace key
jz ky13
cmp al,73 ;PgUp key
jz ky14
cmp al,72 ;up arrow
jz ky15
cmp al,75 ;left arrow
jz ky16
cmp al,77 ;right arrow
jz ky17
cmp al,80 ;down arrow
jz ky18
cmp al,71 ;Home
jz ky19
ky4: mov si,offset ta_ble ;mini-kybd lower case table
cmp bp,1 ;bp is UPPER/lower pointer
jnz ky5
mov si,offset ta_ble2 ;mini-kybd UPPER case table
ky5: mov ah,0
mov ds:[las_one],al
add si,ax ;table address for character
mov al,[si] ;character to display
mov ah,attribute ;white character on black
mov es:[di],ax ;diz keyboard input

ky5a: add di,2 ;next video address
mov bx,es:[di]
mov ds:sav_char,bx
mov word ptr es:[di],075fh ;display cursor
ky5b: call ky6 ;counter & limits
ret
ky6: cmp word ptr [savdi],3536 ;bottom video line
jae ky6a
inc byte ptr [line]
cmp byte ptr [line],64
jae ky7 ;update line begin counter
ret
ky6a: cmp byte ptr [line],63 ;end of bottom line
jae ky6b ;do not go off screen
inc byte ptr [line]
ret
ky6b: mov byte ptr es:[di],20h ;blank cursor
mov di,[savdi] ;start over on bottom line
mov word ptr es:[di],075fh
mov byte ptr [line],0
ret
ky7: mov byte ptr [line],0
mov byte ptr es:[di],20h
add di,32
mov ax,es:[di]
mov ds:sav_char,ax
mov word ptr es:[di],075fh
push di
mov di,[savdi]
cmp di,3536
jae ky7a
add di,160
mov [savdi],di
pop di
ret
ky7a: mov word ptr [savdi],3536
ret

ky8: call re_lease ;PgDn - await key release
mov ax,ds:sav_char
mov es:[di],ax
cmp di,3536 ;PgDn - bottom line ?
jae ky8a
mov di,3536
mov [savdi],di
mov ax,ds:line
shl ax,1 ;times 2
add di,ax
mov ax,es:[di]
mov ds:sav_char,ax
ky8a: mov es:[di],075fh ;new cursor
ret

ky9: mov byte ptr line,0 ;zero out
mov word ptr savdi,0 ;for fresh restart
mov di,hold_video
mov ax,0
mov cx,2000
ky9a: mov [di],ax
add di,2
loop ky9a
ky9b: pop ax ;for call
mov si,offset in_real ;diz now in real mode
mov di,172
call disp_it
jmp bb4 ;begin exit to real mode
ky13: cmp word ptr [savdi],656 ;backspace
jnz ky13a
mov ax,ds:line
cmp ax,0
jnz ky13a
jmp short ky13c
ky13a: mov word ptr es:[di],0720h
sub di,2
mov ax,ds:line
cmp ax,0
jnz ky13b
push di
mov di,[savdi]
sub di,160
mov [savdi],di
mov byte ptr ds:[line],64
pop di
sub di,32
ky13b: mov word ptr es:[di],075fh
dec byte ptr [line]
ky13c: ret

ky14: call re_lease ;PgUp - await key release
mov ax,ds:sav_char
mov es:[di],ax
cmp di,656 ;PgUp - top line ?
jbe ky14a
mov di,656
mov [savdi],di
mov ax,ds:line
shl ax,1 ;times 2
add di,ax
mov ax,es:[di]
mov ds:sav_char,ax
ky14a: mov es:[di],075fh ;new cursor
ret

ky15: cmp word ptr [savdi],656 ;up arrow
jbe ky1
mov ax,ds:sav_char
mov es:[di],ax
sub di,160
mov ax,es:[di]
mov ds:sav_char,ax
mov es:[di],075fh
sub word ptr [savdi],160
ret
ky16: cmp word ptr [savdi],656 ;left arrow
jnz ky16a
mov ax,ds:line
cmp ax,0
jnz ky16a
jmp short ky16c
ky16a: mov ax,ds:sav_char
mov es:[di],ax
sub di,2
mov ax,ds:line
cmp ax,0
jnz ky16b
push di
mov di,[savdi]
sub di,160
mov [savdi],di
mov byte ptr ds:[line],64
pop di
sub di,32
ky16b: mov ax,es:[di]
mov ds:sav_char,ax
mov word ptr es:[di],075fh
dec byte ptr [line]
ky16c: ret

ky17: mov ax,ds:sav_char ;right arrow
mov es:[di],ax
add di,2
mov ax,es:[di]
mov ds:sav_char,ax
mov word ptr es:[di],075fh
jmp ky5b

ky18: cmp word ptr [savdi],3536 ;down arrow
jae ky1
mov ax,ds:sav_char
mov es:[di],ax
add di,160
mov ax,es:[di]
mov ds:sav_char,ax
mov es:[di],075fh
add word ptr [savdi],160
ret

ky19: cmp di,656 ;Home - top line ?
jbe ky1
mov ax,ds:sav_char
mov es:[di],ax
mov di,656
mov [savdi],di
mov ax,es:[di]
mov ds:sav_char,ax
mov es:[di],075fh ;new cursor
mov word ptr line,0
ret

ky20: call re_lease ;Enter - await key release
mov ax,ds:sav_char
mov es:[di],ax
cmp di,3536 ;bottom line ?
jae ky20a
mov di,[savdi]
add di,160
mov [savdi],di
mov byte ptr line,0
mov ax,es:[di]
mov ds:sav_char,ax
ky20a: mov es:[di],075fh ;new cursor
ret

wait_keyin: call re_lease ;F1 - HELP 1
call pr_ess
cmp ah,59 ;F1 key
jz wa1
cmp ah,60 ;F2 key
jz wa2
cmp ah,61 ;F3 key
jz wa3
cmp ah,62 ;F4 key
jz wa4
cmp ah,63 ;F5 key
jz wa5
cmp ah,64 ;F6 key
jz wa6
cmp ah,65 ;F7 key
jz wa7
cmp ah,66 ;F8 key
jz wa8
cmp ah,67 ;F9 key
jz wa9
cmp ah,68 ;F10 key
jz wa10
cmp ah,87 ;F11 key
jz wa11
cmp ah,88 ;F12 key
jz wa12
cmp ah,42 ;weird Print Screen
jz wa13
ret
wa1: pop ax ;for call
call key_delay
mov si,offset help1
mov [savsi],si
jmp diz_h
wa2: pop ax
call key_delay
mov si,offset help2
mov [savsi],si
jmp diz_h2
wa3: pop ax
call key_delay
mov si,offset help3
mov [savsi],si
mov dx,1
jmp diz_h
wa4: pop ax
call key_delay
mov si,offset help4
mov [savsi],si
jmp diz_h
wa5: pop ax
call key_delay
mov si,offset help5
mov [savsi],si
jmp diz_h3
wa6: pop ax
call key_delay
mov si,offset help6
mov [savsi],si
jmp diz_h
wa7: pop ax
call beep2
mov si,offset help7
mov [savsi],si
jmp diz_h
wa8: pop ax
call rstor_video
mov di,[savdi2]
jmp sim_edmod
wa9: pop ax
call rstor_video
mov di,[savdi2]
jmp diz_hlp9
wa10: pop ax
call key_delay
mov si,offset help10
mov [savsi],si
mov dx,2
jmp diz_h
wa11: pop ax
call key_delay
mov si,offset help11
mov [savsi],si
jmp diz_h
wa12: pop ax
call key_delay
call rstor_video
jmp diz_int
wa13: pop ax
call prt_scn
mov byte ptr savch,1
jmp diz_m

diz_hlp1: mov si,offset help1 ;help screen1
mov [savsi],si ;save it
jmp short diz_hlp
diz_hlp2: mov si,offset help2 ;help screen2 page 1
mov [savsi],si
mov byte ptr [sav_paj],1 ;page 1
jmp diz_help2
diz_hlp3: mov si,offset help3 ;help screen3
mov [savsi],si
mov dx,1 ;diz new cs pointer
jmp short diz_hlp
diz_hlp4: mov si,offset help4 ;help screen4
mov [savsi],si
jmp short diz_hlp
diz_hlp5: mov si,offset help5 ;help screen5
mov [savsi],si
jmp diz_help5
diz_hlp6: mov si,offset help6 ;help screen6
mov [savsi],si
jmp short diz_hlp
diz_hlp7: mov si,offset help7 ;help screen7
mov [savsi],si
call beep2
jmp short diz_hlp
diz_hlp9: mov si,offset help9 ;help screen9
mov [savsi],si
jmp diz_help9
diz_hlp10: mov si,offset help10 ;help screen10
mov dx,2 ;help 10 pointer
mov [savsi],si
jmp short diz_hlp
diz_hlp11: mov si,offset help11 ;help screen11
mov [savsi],si

diz_hlp: mov [savdi2],di ;cursor location
call stor_video ;save screen
diz_h: call cls
mov si,[savsi] ;help screen location
mov di,0 ;diz top of screen
call disp_it
call fyx_1 ;custom overlap characters
cmp dx,1
jnz diz_k ;skip it
call new_cs ;diz CS DS ES FS GS SS SP
jmp diz_l
diz_k: cmp dx,2 ;CR DEBUG FLAGS pointer
jnz diz_l
call new_cr
diz_l: call wait_keyin ;await Del key to exit
diz_m: call rstor_video ;restore screen
mov di,[savdi2] ;cursor location
mov word ptr es:[di],075fh ;diz cursor
ret

wait2: call re_lease ;wait key release
call pr_ess ;wait key pressed
cmp ah,28 ;Enter key
jz it1
cmp ah,12 ;hyphen key
jz it2
cmp ah,74 ;keypad -
jz it2
cmp ah,42 ;weird Print Screen
jz wa13
ret
it1: cmp byte ptr [sav_paj],8
jz wait2 ;ignore
cmp byte ptr [sav_paj],1
jz it1a
cmp byte ptr [sav_paj],2
jz it1b
cmp byte ptr [sav_paj],3
jz it1c
cmp byte ptr [sav_paj],4
jz it1d
cmp byte ptr [sav_paj],5
jz it1e
cmp byte ptr [sav_paj],6
jz it1g
mov byte ptr [sav_paj],8
mov word ptr [savsi],help2h
jmp it1i
it1a: mov byte ptr [sav_paj],2
mov word ptr [savsi],help2b
jmp it1i
it1b: mov byte ptr [sav_paj],3
mov word ptr [savsi],help2c
jmp it1i
it1c: mov byte ptr [sav_paj],4
mov word ptr [savsi],help2d
jmp it1i
it1d: mov byte ptr [sav_paj],5
mov word ptr [savsi],help2e
jmp it1i
it1e: mov byte ptr [sav_paj],6
mov word ptr [savsi],help2f
jmp it1i
it1g: mov byte ptr [sav_paj],7
mov word ptr [savsi],help2g
it1i: pop ax ;for call
call key_delay
jmp diz_h2
it2: cmp byte ptr [sav_paj],1 ;PgUp
jz wait2 ;ignore
cmp byte ptr [sav_paj],8
jz it2g
cmp byte ptr [sav_paj],7
jz it2e
cmp byte ptr [sav_paj],6
jz it2d
cmp byte ptr [sav_paj],5
jz it2c
cmp byte ptr [sav_paj],4
jz it2b
cmp byte ptr [sav_paj],3
jz it2a
mov byte ptr [sav_paj],1
mov word ptr [savsi],help2
jmp it1i
it2a: mov byte ptr [sav_paj],2
mov word ptr [savsi],help2b
jmp it1i
it2b: mov byte ptr [sav_paj],3
mov word ptr [savsi],help2c
jmp it1i
it2c: mov byte ptr [sav_paj],4
mov word ptr [savsi],help2d
jmp it1i
it2d: mov byte ptr [sav_paj],5
mov word ptr [savsi],help2e
jmp it1i
it2e: mov byte ptr [sav_paj],6
mov word ptr [savsi],help2f
jmp it1i
it2g: mov byte ptr [sav_paj],7
mov word ptr [savsi],help2g
jmp it1i

diz_help2: mov [savdi2],di ;cursor location
call stor_video ;save screen
mov byte ptr [sav_paj],1
diz_h2:; call cls
mov si,[savsi] ;help screen location
mov di,0 ;diz top of screen
call disp_it
call wait2 ;await Del key to exit
mov byte ptr [sav_paj],1
call rstor_video ;restore screen
mov di,[savdi2] ;cursor location
mov word ptr es:[di],075fh ;diz cursor
ret

wait_keyin5: xor eax,eax ;display kybd time delay 1-9
mov al,ds:[savcl]
mov cx,1
mov si,offset sav_del
call htoa
mov si,offset sav_del
mov di,1964
call disp_it
mov byte ptr es:[1966],'h'
mov byte ptr es:[1968],' '
mov byte ptr es:[1970],' '
call re_lease
wait5: call re_lease ;wait key released
call pr_ess ;wait key pressed
cmp ah,72 ;up arrow more delay
jz tt2
cmp ah,80 ;down arrow less delay
jz tt1
cmp ah,42 ;weird Print Screen
jz wa13
ret
tt1: xor eax,eax ;faster repeat
mov al,ds:[savcl]
cmp al,1
jz wait5
dec al
jmp tt3
tt2: xor eax,eax ;slower repeat
mov al,ds:[savcl]
cmp al,9
jz wait5
inc al
tt3: mov ds:[savcl],al ;keyboard relative delay
mov cx,1
mov si,offset sav_del ;display new delay value
call htoa
mov si,offset sav_del
mov di,1964
call disp_it
mov byte ptr es:[1966],'h'
mov byte ptr es:[1968],' '
mov byte ptr es:[1970],' '
call key_delay
jmp wait5

diz_help5: mov [savdi2],di ;cursor location
call stor_video ;save screen
diz_h3: call cls
mov si,[savsi] ;help screen location
mov di,0 ;diz top of screen
call disp_it
mov byte ptr es:[0564],0e8h
mov byte ptr es:[3052],0e7h
call wait_keyin5 ;await Del key to exit
call rstor_video ;restore screen
mov di,[savdi2] ;cursor location
mov word ptr es:[di],075fh ;diz cursor
ret

wait_keyin9: call re_lease ;wait key release
call pr_ess ;wait for f or g key
call re_lease ;any other key exits
cmp al,33 ;F or f
jnz ih1
mov byte ptr savdl,33 ;f for fs seg
jmp ii0
ih1: cmp al,34 ;G or g
jnz ih2
mov byte ptr savdl,34 ;g for gs seg
jmp ii0
ih2: cmp ah,42 ;weird Print Screen
jz wa13
jmp diz_9 ;ok, exit
ii0: xor eax,eax
cmp byte ptr savdl,33 ;33=f fsseg 34=g gsseg
jnz ii1
mov ax,ds:[savax] ;fsseg
mov byte ptr es:[1934],'F' ;fs segment
jmp ii2
ii1: mov ax,ds:[savbx] ;gsseg
mov byte ptr es:[1934],'G' ;gs segment
ii2: mov cx,4 ;diz 4 bytes
mov si,offset sav_del
call htoa
mov si,offset sav_del
mov di,1958
call disp_it
mov byte ptr es:[1966],'h'
mov byte ptr es:[1968],' '
call beep2 ;acknowledge f or g input

in2: call re_lease
call pr_ess
cmp byte ptr savdl,33 ;update fs seg
jz in4a
jmp in4b ;update gs seg

in4a: cmp ah,72 ;up arrow add seg 1000h
jz vv2
cmp ah,80 ;down arrow sub seg 1000h
jz vv1
cmp ah,42 ;weird Print Sreen
jz wa13
vv0: call re_lease ;wait key released
call cls
mov ax,ds:[savax]
mov word ptr fseg,ax
pop ax ;for 2 calls
pop ax
mov bp,4
jmp bb4 ;begin exit
vv1: xor eax,eax
mov ax,ds:[savax]
sub ax,1000h
jmp vv3
vv2: xor eax,eax
mov ax,ds:[savax]
add ax,1000h
vv3: mov ds:[savax],ax
mov cx,4
mov si,offset sav_del
call htoa
mov si,offset sav_del
mov di,1958
call disp_it
mov byte ptr es:[1966],'h'
mov byte ptr es:[1968],' '
call key_delay
jmp in2

in4b: cmp ah,72 ;up arrow add seg 1000h
jz ww2
cmp ah,80 ;down arrow sub seg 1000h
jz ww1
cmp ah,42 ;weird Print Sreen
jz wa13
ww0: call re_lease ;wait key released
call cls
mov ax,ds:[savbx]
mov word ptr gseg,ax
pop ax ;for call
pop ax
mov bp,4 ;near instant exit protected
jmp bb4 ;reset gs seg & ret protected
ww1: xor eax,eax
mov ax,ds:[savbx]
sub ax,1000h
jmp ww3
ww2: xor eax,eax
mov ax,ds:[savbx]
add ax,1000h
ww3: mov ds:[savbx],ax
mov cx,4
mov si,offset sav_del
call htoa
mov si,offset sav_del
mov di,1958
call disp_it
mov byte ptr es:[1966],'h'
mov byte ptr es:[1968],' '
call key_delay
jmp in2

diz_help9: mov [savdi2],di ;cursor location
call stor_video ;save screen
call cls
mov si,[savsi] ;help screen location
mov di,0 ;diz top of screen
call disp_it
mov byte ptr es:[0564],0e8h
mov byte ptr es:[2892],0e7h
call wait_keyin9 ;wait keyboard input
diz_9: call rstor_video ;restore screen
mov di,[savdi2] ;cursor location
mov word ptr es:[di],075fh ;diz cursor
ret

beep_it: call beep2
ret

tezgs: call cls2 ;test size of GS segment
call frame_it
mov byte ptr es:[656],20h ;erase cursor
mov si,offset pres_F9
mov di,840
call disp_it ;Press F9 to go to top GS
mov si,offset wh_en
mov di,1800
call disp_it ;When GS overruns message
mov si,offset int_err
mov di,1960
call disp_it ;int 0DH exception message
mov edx,0 ;test size of GS segment
mov si,offset loc_ate
mov di,1200
call disp_it
mov si,offset val_ue
mov di,1520
call disp_it
te1: mov eax,edx ;when done exit "exception"
call te6
xor eax,eax
mov word ptr ax,gs:[edx]
xchg al,ah
shl eax,16
mov word ptr ax,gs:[edx+2] ;rearrange so diz 4 bytes
xchg al,ah ;from gs: in correct order
call te7
add edx,4
call wait_f9 ;wait till F9 press
jmp te1
te6: mov cx,8 ;diz location in gs segment
mov si,sav_seg
call htoa
mov si,sav_seg
mov di,1180 ;at video 1180
call disp_it
ret
te7: mov cx,8 ;diz 4 bytes values in gs:
mov si,sav_seg
call htoa
mov si,sav_seg
mov di,1500 ;at video 1500
call disp_it
ret
wait_f9: in al,60h ;await F9 key pressed
mov ah,al
test al,80h
jnz wait_f9
cmp ah,55 ;Print Screen
jnz wt4
call prt_scn
mov ah,0
wt4: cmp ah,67 ;f9 key pressed ?
jnz wait_f9
ret

new_chars: mov ax,1201h ;set 350 scan lines
mov bl,30h
int 10h
mov ax,3
int 10h ;must reset video
push es
mov ax,cs
mov es,ax
mov ax,1110h ;set custom characters
mov bx,0e00H ;14 points in table zero
mov cx,2 ;2 characters
mov dx,0e7h ;1st one`s ASCII code
mov bp,cs:table ;to eliminate help overlap
int 10h ;do it in real mode
pop es
mov bp,0
ret
table:
DB 0,0,0,0,0,0ffh,0,0ffh,36h,36h,36h,36h,36h,36h ;e7h
DB 36h,36h,36h,36h,36h,37h,36h,37h,36h,36h,36h,36h,36h,36h ;e8h

flopof: mov dx,3f2h ;floppy motor off
mov al,12
out dx,al
push ds
mov ax,0
mov ds,ax
mov byte ptr ds:[417h],0 ;num + caps + scroll lock off
call re_lease ;await key release
cli
mov byte ptr al,ds:[41ah] ;clear keyboard buffer
mov byte ptr ds:[41ch],al
sti
pop ds
ret

cursof: mov cx,0e00h ;cursor off
cur: mov bh,0
mov ah,1
int 10h
ret
curson: mov bh,0
mov dx,1700H
mov ah,2
int 10h ;set cursor for exit
mov cx,0607h ;cursor on for exit
jmp short cur

cls: mov di,hold_video ;maybe
add di,656
mov al,[di]
cmp al,0
jz ls1
jmp bak
ls1: mov ax,video_selec ;get video segment selector
mov es,ax ;put in ES
mov cx,4000h ;buffer size to clear
xor di,di ;screen starting address
mov ah,attribute ;character attribute
mov al,space ;space
rep stosw ;fill it
ret
bak: call rstor_video
ret

cls1: mov di,hold_video
mov cx,2000
mov ax,0
cl2: mov [di],ax
add di,2
loop cl2
ret

stor_video:
mov ax,video_selec
mov es,ax
mov di,0
mov si,hold_video
mov cx,2000
st1: mov ax,es:[di]
add di,2
mov [si],ax
add si,2
loop st1
ret

rstor_video: pusha
mov ax,video_selec
mov es,ax
mov si,0
mov di,hold_video
mov cx,2000
st2: mov ax,[di]
add di,2
mov es:[si],ax
add si,2
loop st2
popa
ret

diz_int: call re_lease ;diz int. decriptor table
mov [savdi2],di ;cursor location
call stor_video ;save screen
mov bp,0
call cls
mov ax,ds:savax ;current FS seg value
mov ds:savcx,ax ;save current FS seg value
mov eax,0 ;interrupt vector segment
mov ds:[savax],ax ;reset FS seg to seg 0
mov word ptr fseg,ax ;"
pop ax ;for call
mov byte ptr savdh,1 ;ret to int_table pointer
mov bp,4 ;millisec exit ret protected
jmp bb4 ;exit protected mode millisec
int_table: mov byte ptr savdh,0 ;reset pointer
mov si,help2s ;help screen location
mov di,0 ;diz top of screen
call disp_it

call fyx_1 ;fix rectangle oerlaps

mov di,0 ;source
mov cx,21 ;21 interrupts
mov si,494
mov savsi3,si
zh1:
xor eax,eax
xor ebx,ebx
mov ax,fs:[di+2]
shl eax,4
mov bx,fs:[di]
add eax,ebx
call zh3
add di,4
loop zh1

mov ax,ds:savcx ;old FS seg value
mov ds:savax,ax ;reset it
mov ds:fseg,ax ; " "
call pr_ess ;wait till any key pressed
call re_lease ;wait till key released
cmp al,42 ;weird Print Screen
jnz zh2
jmp wa13
zh2: call rstor_video ;restore screen
mov di,[savdi2] ;cursor location
mov word ptr es:[di],075fh ;diz cursor
mov bp,4 ;millisec reset pointer
jmp bb4 ;exit & reset protected
zh3: pusha
mov cx,6
mov si,offset sav_seg2
call htoa
mov si,offset sav_seg2
mov di,savsi3
call disp_it
add word ptr savsi3,160
popa
ret

pr_ess: in al,60h ;keyboard port
test al,80h ;wait till key down
mov ah,al
jnz pr_ess
call key_delay
call key_delay
ret

re_lease: push ax
rea: in al,60h ;keyboard port unload
test al,80h ;wait till key released
jz rea
pop ax
ret

re_peat: mov ch,ds:[savcl]
mov byte ptr ds:[savcl],4
call key_delay
call key_delay
call key_delay
mov byte ptr ds:[count1],1
mov ds:[savcl],ch
ret

dizhi: pusha ;diz 256 character set
mov cx,256
mov al,0
mov di,3056
mov ah,64 ;65
zh: mov es:[di],al
inc al
dec ah
jnz zj
call zk
zj: add di,2
loop zh
popa
ret
zk: add di,32
mov ah,64
ret

dizsp: pusha ;display stack pointer
xor eax,eax
mov ax,sp
mov cx,4
mov si,offset sav_sp
call htoa
mov si,offset sav_sp
mov di,3990
call disp_it
mov byte ptr es:[3998],'h'
mov byte ptr es:[3832],'S'
mov byte ptr es:[3834],'P'
popa
ret

dizupper: mov dl,3 ;3 keypad inputs counter
mov ah,0
mov dh,0
di1: call key_pad ;get 0 to 9
call convert
call mulply ;multiply
add dh,al ;add up
call key_delay
dec dl ;3 keypad press counter
jnz di1
mov es:[di],dh
add di,2
mov word ptr es:[di],075fh
call ky6 ;count on line
call key_delay
ret

key_pad: in al,64h
test al,1
jz key_pad ;wait kybd buffer full
in al,60h ;keyboard buffer
cmp al,56 ;ignore Alt that got us here
jz key_pad
cmp al,80h ;ignore release values
ja key_pad
cmp al,46 ;C or c key
jz ey2
cmp al,71 ;lowest keypad number key
jb ey1 ;quit
cmp al,82 ;highest keypad number key
ja ey1 ;quit
ret
ey1: pop ax ;for call
ret ;ignore further input
ey2: call re_lease ;wait for key release
pop ax ;for call
call cls3 ;clear rectangle
call frame_it
ret

convert: push di
mov di,offset array
mov ah,0
sub al,71
add di,ax
mov al,[di]
pop di
ret

mulply: cmp dl,3
jz mul100
cmp dl,2
jz mul10
ret
mul100: mov bh,100
mul bh
ret
mul10: mov bh,10
mul bh
ret

cls2: mov di,0
jmp ls3
cls3: mov di,480
ls3: mov cx,2000
mov ax,0720h
cld
rep stosw
mov di,656
mov [savdi],di
mov word ptr es:[di],075fh
mov byte ptr ds:[line],0 ;position on video line
ret

beep2: pusha ;beep in protected mode
mov bx,16
MOV DX,1300 ;tone frequency
MOV AL,0B6H
OUT 43H,AL
MOV AL,DL
OUT 42H,AL
MOV AL,DH
OUT 42H,AL
IN AL,61H
MOV AH,AL
OR AL,3
OUT 61H,AL
call delay1
TN1: MOV CX,3340
TA2: LOOP TA2
DEC BX
JNE TN1
MOV AL,AH
OUT 61H,AL
popa
RET

delay1: push ax
mov ax,0
del1: pusha
popa
dec ax
jnz del1
pop ax
ret

prt_scn: cmp byte ptr savch,1 ;if 1, avoid dupe print screen
jnz de0
mov byte ptr savch,0
ret
de0: mov dx,3beh ;printer output control regist.
mov al,12 ;initialize
out dx,al ;(probably not necessary)
mov ax,12000 ;few milliseconds time delay
de1: dec ax ;some HP LaserJet compatibles
jnz de1 ;are NOT totally compatible
mov dx,3bdh ;printer status register
in al,dx
test al,8 ;printer ready ?
jnz pr0
jmp prt_err ;2 beep since printer not ready
pr0: mov bx,0 ;begin video
mov ch,26
pr1: dec ch ;print 25 lines
jz prt_dun
mov cl,80 ;80 characters per line
mov dx,3bch
pr2: call pr3 ;print line
dec cl
jnz pr2
mov al,13 ;carriage return
call pr4
mov al,10 ;line feed
call pr4
jmp pr1
pr3: mov al,es:[bx] ;video location
add bx,2 ;next character
cmp al,20h
ja pr4
mov al,20h ;avoid printer ctrl characters
pr4: out dx,al
inc dx
inc dx
mov al,13 ;strobe bit is zero
out dx,al ;pulse strobe line high
dec al
out dx,al ;pulse strobe line low
dec dx
not_yet: in al,dx ;get status byte
test al,8 ;error ?
jz prt_err
test al,80h ;printer busy ?
jz not_yet
dec dx
ret
prt_err: call beep2 ;printer not ready
call key_delay
prt_dun: call beep2
ret

sim_edmod: call re_lease ;wait key released
mov si,offset frame2 ;in macro4 help file
mov [savsi],si
mov [savdi2],di ;cursor location
call stor_video ;save screen
call cls
mov si,[savsi] ;help screen location
mov di,0 ;diz top of screen
call disp_it
call dizsp
mov si,offset in_protected ;protected mode message address
mov di,172 ;display address
call disp_it ;call display procedure
jmp dizgs ;start display GS segment
ldir: mov di,0
mov [savdi3],di ;cs ds es fs gs seg location
ldir0: call diz_location
mov di,[savdi3]
ldir1: mov cl,16
mov ch,64
mov si,496
mov ah,7
ldir2: cmp bl,1
jz ld1 ;diz cs segment
cmp bl,2
jz ld2 ;diz ds segment
cmp bl,3
jz ld3 ;diz es segment
cmp bl,4
jz ld4 ;diz fs segment
jmp ld5 ;diz gs segment
ld1: mov al,cs:[di]
jmp ld6
ld2: mov al,ds:[di]
jmp ld6
ld3: mov al,es:[di]
jmp ld6
ld4: mov al,fs:[di]
jmp ld6
ld5: mov al,gs:[di]
ld6: cmp al,0
jnz ldir3
mov al,'0'
ldir3: mov es:[si],ax
inc di
add si,2
dec ch
jz newlin
jmp ldir2
newlin: mov ch,64
add si,32
dec cl
jnz ldir2
mov [savdi3],di
wait_ky: call key_delay ;slow down page display
in al,60h
mov ah,al
cmp ah,55 ;Print Screen
jnz vt1
call prt_scn
mov ah,0
vt1: cmp ah,28 ;Enter key
jz ldir0
cmp ah,12 ;minus/hyphen/dash key
jz vt2
cmp ah,74 ;keypad minus key
jz vt2
cmp ah,46 ;C or c key to diz CS segment
jz dizcs
cmp ah,32 ;D or d key to diz DS segment
jz dizds
cmp ah,18 ;E or e key to diz ES segment
jz dizes
cmp ah,33 ;F or f key to diz FS segment
jz dizfs
cmp ah,34 ;G or g key to diz GS segment
jz dizgs
cmp ah,83 ;Del key pressed ?
jz xit ;quit
cmp ah,1 ;Esc key ?
jz xit
cmp ah,57 ;space bar ?
jz xit
jmp wait_ky ;start over
xit: call re_lease ;wait key released
call rstor_video ;restore screen
mov di,[savdi2] ;cursor location
mov word ptr es:[di],075fh ;diz cursor
ret
vt2: sub [savdi3],2048 ;move down a page
jmp ldir0
dizcs: mov bl,1 ;segment pointer
mov byte ptr es:[86],'C'
mov byte ptr es:[630],'C'
mov ax,code ;code segment value
call diz_val ;diz segment value
jmp ldir
dizds: mov bl,2 ;segment pointer
mov byte ptr es:[86],'D'
mov byte ptr es:[630],'D'
mov ax,gdata ;data segment value
call diz_val
jmp ldir
dizes: mov bl,3 ;segment pointer
mov byte ptr es:[86],'E'
mov byte ptr es:[630],'E'
mov ax,0b800h
call diz_val
jmp ldir
dizfs: mov bl,4 ;segment pointer
mov byte ptr es:[86],'F'
mov byte ptr es:[630],'F'
mov ax,ds:savax
call diz_val
jmp ldir
dizgs: mov bl,5 ;segment pointer
mov byte ptr es:[86],'G'
mov byte ptr es:[630],'G'
mov ax,ds:savbx
call diz_val
jmp ldir
diz_location:
pusha
xor eax,eax
mov ax,ds:[savdi3]
mov cx,4
mov si,offset sav_del
call htoa
mov si,offset sav_del
mov di,640
call disp_it
mov ax,ds:[savdi3]
add ax,3ffh
mov cx,4
mov si,offset sav_del
call htoa
mov si,offset sav_del
mov di,3190
call disp_it
popa
ret
diz_val: pusha
mov cx,4 ;segment value
mov si,edm_seg
call htoa
mov si,edm_seg
mov di,790 ;display below segment name
call disp_it
popa
ret

diz_anything: pusha ;diz eax value
mov cx,8
mov si,sav_any
call htoa
mov si,sav_any
mov di,2280
call disp_it
popa
ret

new_cr: xor dx,dx ;diz CRs Debugs Flag regs
pusha
mov word ptr savdi4,1012
mov eax,cr0
call dizb
mov eax,cr2
call dizb
mov eax,cr3
call dizb
mov eax,dr0
call dizb
mov eax,dr1
call dizb
mov eax,dr2
call dizb
mov eax,dr3
call dizb
mov eax,dr6
call dizb
mov eax,dr7
call dizb
xor eax,eax
pushfd
pop eax
call dizb
popa
ret

dizb: mov di,savdi4
mov cx,8
mov si,sav_reg2
call htoa
mov si,sav_reg2
call disp_it
mov byte ptr es:[di],'h'
add savdi4,160
ret

new_cs: pusha ;diz seg regs
mov word ptr savdi4,1150
mov eax,code
call dizc
mov eax,gdata
call dizc
mov eax,0b800h
call dizc
mov ax,ds:savax
call dizc
mov ax,ds:savbx
call dizc
mov eax,stk0
call dizc
mov eax,stk1
call dizc
mov eax,stk2
call dizc
mov eax,esp
call dizc
popa
xor dx,dx
ret
dizc: mov di,savdi4
mov cx,4
mov si,sav_reg
call htoa
mov si,sav_reg
call disp_it
mov byte ptr es:[di],'h'
add savdi4,160
ret

go_edmod: mov bp,3 ;go directly to EDMOD
call stor_video ;do not pass go
jmp ky9b

frame_it: pusha ;draw rectangle
mov di,492
mov byte ptr es:[di],201
add di,2
mov cx,66
fr1: mov byte ptr es:[di],205
add di,2
loop fr1
mov byte ptr es:[di],187
add di,160
mov cx,19
fr2: mov byte ptr es:[di],186
add di,160
loop fr2
mov byte ptr es:[di],188
sub di,2
mov cx,66
fr3: mov byte ptr es:[di],205
sub di,2
loop fr3
mov byte ptr es:[di],200
sub di,160
mov cx,19
fr4: mov byte ptr es:[di],186
sub di,160
loop fr4
popa
ret

key_delay: pusha ;keybd repeat delay
mov cl,ds:[savcl] ;repeat count for delay
im0: mov di,0
mov savdi4,di
mov al,10110010b ;set interrupt timer
out 43h,al ;control register to
mov ax,0ffffh ;mode 1.
out 40h,al ;interrupt timer port
mov al,ah
out 40h,al
im1: xor eax,eax
in al,40h
mov ah,al ;counter zero
in al,40h
xchg al,ah
mov bx,ax
im2: in al,40h
mov ah,al
in al,40h
xchg al,ah
cmp bx,ax
ja im2
dec cl
jnz im1
popa
ret

sho_vga: pop ax
mov es:[di],0720h
call stor_video
mov byte ptr savdh,4
mov bp,4
jmp bb4 ;fast exit & reenter

save_file: call beep2 ;save file TYPED.DAT
pop ax ;for call
mov es:[di],0720h ;erase cursor
call stor_video ;stash in hold_video
mov byte ptr savdh,2 ;save pointer on re-entry
mov bp,4 ;reenter pointer
jmp bb4 ;fast exit & re-enter

rstor_file: call beep2 ;restore file TYPED.DAT
pop ax ;for call
rsto: mov byte ptr savdh,3 ;restore pointer on re-entry
mov bp,4 ;re-enter pointer
jmp bb4 ;fast exit & re-enter
ole_file: call rstor_video ;from hold_video
fyx: mov di,656 ;video address in es:
mov byte ptr savdh,0 ;zero out restore pointer
mov word ptr line,0 ;set line begin
jmp ski ;continue

zero_empty: mov cx,0ffffh ;zero out end code segment
mov di,elfin
sub cx,di
mov al,0
zer: mov cs:[di],al
inc di
loop zer
ret

fyx_1: ;close rectangle overlaps (beautify)
cmp byte ptr es:[0494],186
jz fyx_4
cmp byte ptr es:[2252],205
jz fyx_6
cmp byte ptr es:[2892],205
jz fyx_10
cmp byte ptr es:[3052],205
jz fyx_11
mov byte ptr es:[0564],0e8h
mov byte ptr es:[3764],0e8h
fyx_4: ret ;ignore help 4
fyx_6: mov byte ptr es:[0564],0e8h
mov byte ptr es:[2252],0e7h ; Ë modified
ret
fyx_10: mov byte ptr es:[0594],0e8h ; Ì modified
mov byte ptr es:[2892],0e7h
ret
fyx_11: mov byte ptr es:[0564],0e8h
mov byte ptr es:[3052],0e7h
ret

UNPAKW4: mov cx,8000h
mov ax,7000h
mov ds,ax
mov di,0
mov ax,0
unp: mov [di],ax
add di,2
loop unp
mov ax,cs
mov ds,ax
call wmem4 ;load Ford.pcx to ds:6000h+
VSEG3: MOV AX,0A000H ;EGA/VGA VIDEO SEGMENT
MOV ES,AX
CLD
MOV AX,6000H
MOV DS,AX
CALL PCXPAL ;DECODE PCX 16 COLORS
VS3: MOV BP,480 ;NO. SCAN LINES TO WRITE
MOV DX,3C4H ;SEQUENCER REGISTER PORT
MOV BX,80 ;BYTES/LINE
XCHG BL,BH
MOV SI,80H ;BEGIN PACKED DATA
MOV CX,0 ;CL= NO. CARRY CH=VIDEO VALUE
UU0: MOV DI,0 ;START IN A000H
U1: MOV AX,102H ;ENABLE WRITE PLANE 0
OUT DX,AX ;SEQUENCER REGISTER PORT
CALL UPCX ;UNPACK AND WRITE TO PLANE
MOV AX,202H ;ENABLE WRITE PLANE 1
OUT DX,AX
CALL UPCX
MOV AX,402H ;ENABLE WRITE PLANE 2
OUT DX,AX
CALL UPCX
MOV AX,802H ;ENABLE WRITE PLANE 3
OUT DX,AX
CALL UPCX
ADD DI,80 ;NEXT SCAN LINE 8x80=640 PELS
DEC BP ;LINE COUNTER
JNZ U1
MOV AX,CS
MOV DS,AX
mov ax,gdata
mov ds,ax
mov byte ptr savdh,0
mov ah,0
int 16h
mov ax,3
int 10h
mov ax,0b800h
mov es,ax
jmp be_gin

UPCX: PUSH DI ;VIDEO MEM ADDRESS OF PLANE
MOV BL,BH ;BH=BYTES/LINE
CMP CL,0 ;CL=NUMBER CARRY CH=PIXEL
JNZ XX4 ;DO BALANCE OF LAST RLL
XX1: MOV AL,[SI]
CMP AL,191
JA XX2
INC SI
JNZ X1A
CALL XX7
X1A: MOV ES:[DI],AL
INC DI
DEC BL
JNZ XX1 ;DO NEXT BYTE
POP DI
RET ;DO NEXT PLANE
XX2: INC SI
JNZ X2A
CALL XX7
X2A: MOV AH,AL
AND AH,63 ;NUMBER RLL BYTES TO DISPLAY
MOV AL,[SI] ;PIXELS' BYTE VALUE TO SHOW
INC SI
JNZ XX3
CALL XX7
XX3: STOSB
DEC BL ;BYTES/PLANE
JZ XX6 ;DONE THIS PLANE
DEC AH ;RLL
JNZ XX3
JMP XX1
XX4: MOV AL,CH ;BALANCE RLL LAST LINE
XX5: STOSB ;DO REMAINDER RLL BYTES
DEC BL ;FROM LAST PLANE
DEC CL ;REMAINDER
JNZ XX5
JMP XX1 ;REMAINDER DONE - TEST NEXT
XX6: DEC AH ;DONE WITH THIS PLANE
XCHG AL,AH
MOV CX,AX ;UNPACK CARRY BYTES REMAIN
POP DI
RET ;DO NEXT PLANE
XX7: push di
mov di,ds
add di,1000h
mov ds,di
pop di
MOV SI,0
RET

W4: DB 'C:\PROTECT\FORD.PCX',0,0
WMEM4: MOV DX,W4
KK0: MOV AX,CS
MOV DS,AX
MOV AX,6000H
MOV CS:[SAVDS],AX
PUSHA
MOV AX,3D02H ;OPEN FILE
INT 21H
JNC AA0
JMP F2
AA0: MOV BX,AX
NOP
MOV AX,4202H ;LSEEK EOF
MOV CX,0
MOV DX,0
INT 21H
MOV DI,DX ;MSP
MOV SI,AX ;LSP
MOV [savdx],DX
MOV WORD PTR CS:[SAVLS],AX
A1: MOV AX,4200H ;LSEEK BEGIN FILE
MOV CX,0
MOV DX,0
INT 21H
MOV AX,CS:[SAVDS]
MOV DS,AX ;1ST SEG
CMP word ptr [savdx],0 ;MSP
JZ F1 ;< 1 SEG
CALL LHNG1 ;READ 65536 BYTES
DEC word ptr [savdx] ;MSP
JZ F1
CALL LHNG1
DEC word ptr [savdx] ;MSP
JZ F1
CALL LHNG1
DEC word ptr [savdx] ;MSP
JZ F1
CALL LHNG1
DEC word ptr [savdx] ;MSP
JZ F1
CALL LHNG1
F1: MOV CX,CS:[SAVLS]
MOV AX,CS:[SAVDS]
MOV DS,AX
MOV DX,0
MOV AX,3F00H
INT 21H
NOP
MOV AX,3E00H ;CLOSE
INT 21H
POPA
MOV AX,CS
MOV DS,AX
RET
LHNG1: MOV AX,3F00H ;READ ENTIRE SEGMENT
MOV CX,0FFFFH
MOV DX,CS:[SAVDS]
MOV DS,DX
MOV DX,0
INT 21H
NOP
MOV AX,3F00H
MOV CX,1
MOV DX,CS:[SAVDS]
MOV DS,DX
MOV DX,0FFFFH
INT 21H
ADD CS:[SAVDS],1000H ;NEXT SEGMENT
RET
F2: POPA
MOV AX,CS
MOV DS,AX
RET

PALETTE: DB 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
SETOVER: DB 0
SCANLIN: DW 0
LINBYT: DW 0
PCXPAL: PUSH ES ;DECODE SCREWY PCX TRIPLES
MOV AX,CS
MOV ES,AX ;SETPAL SEGMENT
MOV AX,12H
INT 10H
JMP CONVDAC ;CONVERT DACS+SET PALETTES
CONVDAC: MOV AX,1013H
MOV BL,0
MOV BH,1
INT 10H ;SET ATTRIBUTE CONTROLLER SELECT STATE
MOV AX,DS
MOV ES,AX ;HEADER ADDRESS NOW ES = DS
MOV DI,16 ;BEGIN TRIPLES IN HEADER
MOV CX,48 ;NUMBER TO UPDATE
XY1: SHR BYTE PTR ES:[DI],2 ;SHR 2 BITS - BIT 6/7 IGNORED
INC DI
LOOP XY1
MOV AX,1012H ;UPDATE BLOCK
MOV BX,0
MOV CX,16 ;16 EA 3 BYTE DACs
mov dx,16
INT 10H ;UPDATE 16 DAC COLOR REGISTERS
MOV AX,1000H ;FIX INDEX #6
MOV BX,606H ;BAD BIOS DAC UPDATE
INT 10H ;BIOS ERROR
POP ES ;BACK TO A000H
RET ;GO UNPACK

SAVLS: DW 0

db 64 dup(20h)
db 'this is the end of protected mode code in the code segment'
db 64 dup(20h)
elfin: db 0

kybd_in endp

code ends
end main






  3 Responses to “Category : Assembly Language Source Code
Archive   : PROTEC.ZIP
Filename : EN.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/