data segment
    org  6ah
    rec_size dw ?
    org  07ch
    recno  db ?
    randlow  dw  ?
    randhi   dw  ?
    org  80h
    dta  db  80h dup(?)
data ends

PSize    equ  8
RSize  equ  18
fcb    equ  5ch

vars segment
    names db 10 dup(?)
    age   db  ?,?
    sex   db  ?
    height db ?,?,?
    weight db ?,?
    pcounter db ?
    mess_n db 0ah,0dh,"    name   : $"
    mess_a db 0ah,0dh,"    age    : $"
    mess_s db 0ah,0dh,"    sex    : $"
    mess_h db 0ah,0dh,"    height : $"
    mess_w db 0ah,0dh,"    weight : $"
    err_fopen  db  0ah,0dh,"    File open error !$"
    err_fcreat  db  0ah,0dh,"    File creat error !$"
    err_fread1 db  0ah,0dh,"    File read error in sequence manner !$"
    err_fread2 db  0ah,0dh,"    File read error in random manner !$"
    err_fclose db  0ah,0dh,"    File close error !$"
    prompt db 0ah,0dh,"DOCU>> $"
    continue  db 0ah,0dh,"    Press space to continue... $"
vars ends

show macro addrs
;  display a line started at addrs.

    push ds
    mov  ax,es
    mov  ds,ax
    lea  dx,addrs
    mov  ah,09h
    int  21h
    pop  ds
endm

show_item macro addrs,count1,count2
local iloop,spacelp
    mov  bx,0

; display (count1) chars begin at addrs, and 
; followed by (count2) spaces.

iloop:
    mov  dl,es:&addrs&[bx]
    mov  ah,2
    int  21h
    inc  bx
    cmp  bx,count1
    jl   iloop
    mov  cx,count2
spacelp:
    mov  dl," "
    mov  ah,2
    int  21h
    loop  spacelp
endm

getin macro addrs,count
    local lp,zeroit,input_end,exit
    push  ds
    mov   ax,es
    mov   ds,ax
    mov   bx,0

;  get (count) chars from keyboard, and put them
;  to addrs .

zeroit:
    mov  &addrs&[bx],0
    inc  bx
    cmp  bx,count
    jl   zeroit		; let (count) num. of byte
			; starting at addrs be zero.

    mov  bx,0
lp: mov  ah,1
    int  21h
    cmp  al,0dh
    jz   input_end
    cmp  al,0ah
    jz   input_end
    mov  &addrs&[bx],al
    inc  bx
    cmp  bx,count
    jl   lp
input_end:
    cmp  al,0dh
    jz   exit
    cmp  al,0ah
    jz   exit

    mov  ah,1
    int  21h
    jmp  input_end	; if not all char typed in have
			; been received , then get again.
exit:
    pop  ds
endm

code segment
assume  cs:code,ds:data,es:vars
main proc far
start:
    push ds
    sub  ax,ax
    push ax
    mov  ax,vars
    mov  es,ax

main_loop:
    show prompt

; receive commands (l,i,q) and call the
; responding subroutine.

cmd_loop:
    mov  ah,1
    int  21h
    cmp  al,"l"
    jnz  n1
    call list_all
    jmp  main_loop
n1:
    cmp  al,"i"
    jnz  n2
    call insert
    jmp  main_loop
n2:
    cmp  al,"q"
    jnz  cmd_loop
    ret
main endp

;******************************************
;  list_all procedure lists the document  *
;  file in a page manner                  *
;******************************************
list_all proc near
    push ax
    push bx
    push cx
    push dx
    call openf   ; Open the DOCU file
    or   al,al
    jz   go_on
    jmp  ext
go_on:
    mov  recno,0
    mov  rec_size,RSize
list_loop:
    mov  dx,fcb
    mov  ah,14h
    int  21h     ; read a record in sequence manner.
    cmp  al,01
    jne  n3
    jmp  file_end ; (al)=1: meets the end of file.
n3:
    cmp  al,0
    je  n4
    show err_fread1  ; read errror
    mov  dl,"0"
    add  dl,al
    mov  ah,2
    int  21h		; show error no.
    jmp  file_end

n4:
		; reading correct.
    mov  bx,0
moving:
		; moving the record to NAMES in 
		; DS segment.

    mov  al,dta[bx]
    mov  es:names[bx],al
    inc  bx
    cmp  bx,RSize
    jl   moving

    mov  dl,0dh
    mov  ah,2
    int  21h
    mov  dl,0ah
    mov  ah,2
    int  21h		; show RETURN.

    call show_rec	; show the record.

    mov  dl,0dh
    mov  ah,2
    int  21h
    mov  dl,0ah
    mov  ah,2
    int  21h		; show RETURN.

    inc  es:pcounter
    cmp  es:pcounter,PSize
    jl   list_loop	; show record in page manner.

    mov  es:pcounter,0
    show continue	; pause at the end of a page,
			; and print the promt message
			; to wait for continue .
pg_cmd:
    mov  ah,1
    int  21h
    cmp  al," "
    jne  pg_cmd		; wait for space to continue.

    jmp  list_loop
file_end:
    call closef
ext:
    pop  dx
    pop  cx
    pop  bx
    pop  ax
    ret
list_all endp

show_rec proc near
    push  ax
    push  bx
    push  cx
    push  dx
    show_item  names,10,2
    show_item  age,2,4
    show_item  sex,1,3
    show_item  height,3,2
    show_item  weight,2,2
    pop  dx
    pop  cx
    pop  bx
    pop  ax
    ret
show_rec endp
;******************************************
; The insert procedure get a record from  *
; terminal, and insert it into DOCU file. *
;******************************************
insert proc near
    push ax
    push bx
    push cx
    push dx
    call openf
    or   al,al
    jz   getrc
    jmp  back
getrc:
    call get_record	; get a record form keybaord.
    mov  recno,0
    mov  rec_size,RSize
find_end:
    mov  ah,14h
    mov  dx,fcb
    int  21h       ; read a record from DOCU.
    cmp  al,01
    je   write_record	; when read to the end,
			; write the record to the
			; end of DOCU.
    cmp  al,0
    je   find_end
write_record:
    mov  bx,0
to_dta:
    mov  al,es:names[bx]
    mov  dta[bx],al
    inc  bx
    cmp  bx,RSize
    jl   to_dta
    mov  ah,15h
    mov  dx,fcb
    int  21h      ; write arecord to DOCU.
    call closef
back:
    pop  dx
    pop  cx
    pop  bx
    pop  ax
    ret
insert endp

get_record proc near
    push ax
    push bx
    push cx
    push dx
    show mess_n
    getin names,10
    show mess_a
    getin age,2
    show mess_s
    getin sex,1
    show mess_h
    getin height,3
    show mess_w
    getin weight,2
    pop dx
    pop cx
    pop bx
    pop ax
    ret
get_record endp

openf proc near
   
    push bx
    push cx
    push dx
    mov  ah,0fh
    mov  dx,fcb
    int  21h
    or   al,al
    jz   found
    show err_fopen
    mov  ah,16h
    mov  dx,fcb
    int  21h
    or   al,al
    jz   found
    show err_fcreat
found:
    pop  dx
    pop  cx
    pop  bx
    ret
openf endp

closef proc near
    push ax
    push dx
    mov  ah,10h
    mov  dx,fcb
    int  21h
    pop  dx
    pop  ax
    ret
closef endp

code ends
end start


    