home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
mslang
/
dbhex
/
dbhex.asm
next >
Wrap
Assembly Source File
|
1993-04-03
|
22KB
|
933 lines
_MODEL equ <small>
include MODEL.INC
include CONSOLE.INC
include FILEIO.INC
include IMATH.INC
.codeseg lib
.extrn start:auto, exit_ok:auto
.extrn console_init:auto, set_directvideo:auto
.extrn open_h:auto,close_h:auto,read_h:auto
.extrn str_len:auto,str_ncpy:auto,str_stri:auto,str_cat:auto
.extrn put_str:auto,put_newline:auto,put_chr:auto
.extrn byte_to_hex:auto,word_to_hex:auto,dword_to_asc:auto
.extrn arg_next:auto
.extrn getfsize_h:auto
.ends
.dataseg
DBFNAME DB 128 DUP(0)
DBEXT DB ".DBF",0
DBHANDLE DW 0
HEADERMSG DB '.DBF Header:',0
FLDDESCMSG DB 'Field Descriptor:',0
RECNOMSG DB 'Record Number ',0
FLDCOUNTER DB 0
BYTECOUNTER DD 0
BYTECNTRSTRING DB 5 DUP(0)
FILESIZE DW 2 DUP(0)
POS_COUNTER DB 0 ; Position counter, from 1 to 16 (0 to F)
CURPOINTER DW 0 ; For saving SI or DI.
BYTEHEXSTRING DB 3 DUP(0)
VERSNO DB 0
LASTYEAR db 0
LASTMONTH DB 0
LASTDAY DB 0
RECCOUNT DD 0
HEADERLEN DW 0
RECLEN DW 0
DRESERVED1 DW 0
DRESERVED2 DB 0
DRESERVED3 DB 13 DUP(0)
DRESERVED4 DB 0
DRESERVED5 DB 3 DUP(0)
DESCLEN DW 0
NO_OF_FIELDS DB 0
FIELDNAME DB 11 DUP(0)
FIELDTYPE DB 0
FIELDOFFSET DW 2 DUP(0)
FIELDLENGTH DB 0
DECPLACE DB 0
FRESERVED DB 14 DUP(0)
RECNO DD 0 ; Current Record Number
RECNOSTRING DB 10 DUP(0) ; This will contain either the hex or
; decimal ascii string version of RECNO.
LINES_PER_RECORD DW 0 ; Number of lines needed to display a record,
; not counting the bytes on the last line
; of each record block.
REMAINING_BYTES DB 0 ; Number of bytes on last line of each record
; block; when all records are displayed, this
; becomes the number of bytes on the last line
; of the file.
REMAINING_SPACES DB 0 ; Number of spaces to pad with on last line of
; block; when all records are displayed, this
; becomes the number of spaces to pad on the last
; line of the file.
RECBLKCOUNTER DW 0 ; Counter to store which line of block is currently
; being read or displayed.
RECORDDATA DB 16 DUP(0) ; This holds the actual data, which is then
; displayed in hex and ascii formats.
TERMINATOR DB 0Dh ; This holds the terminator byte, which should
; always be 0D hex.
NUM_BYTES_TO_READ DB 0 ; This is the number of bytes to be read. It is
; usually 16, unless the number of fields and/or
; the field widths in the database is small. It
; may become less than 16, though, e.g. for the
; last line of each record block.
.ends
.stackseg
db 1024 dup(?) ;define a 1024 byte stack
.ends
.codeseg
assume cs:@codeseg, ds:@dataseg, es:@dataseg, ss:@stackseg
.public main
.proc main auto
MOV AX, @DATASEG
MOV DS, AX
BEGINNING:
CALL CONSOLE_INIT
CALL SET_DIRECTVIDEO
MOV SI,OFFSET @DATASEG:DBFNAME
CALL ARG_NEXT ; Get 1st argument - database name.
CALL OPENDBF ; Try to open the file.
CALL DISP_HDRSTRING ; Display '.DBF Header:' or similar heading.
CALL GET_AND_DISP_HEADER ; Display hex and ascii forms of header.
CALL CALCFROMHDR ; Calculate some relevant parameters from
; header.
CALL DISP_DESCSTRING ; Display 'Field Descriptor:' or similar heading.
CALL GET_AND_DISP_DESC ; Display hex and ascii forms of field descriptor
; array.
CALL GET_AND_DISP_TERMINATOR ; Display terminator of field descriptor.
CALL GET_AND_DISP_RECS ; Read records from disk and display.
CALL LAST_BYTES ; Read and display the final byte(s).
CALL CLOSE_AND_EXIT ; Close the database file and exit to DOS.
;=============================================================================
;Procedure: CLOSE_AND_EXIT
;
;DESC: Closes the .DBF file and exits.
;
;IN: DBHANDLE should contain the name of the open .DBF file.
;
;OUT: None
;=============================================================================
.PROC CLOSE_AND_EXIT
MOV BX,DBHANDLE ; Make sure the proper file handle is back in BX.
CALL CLOSE_H
CALL EXIT_OK
.ENDP CLOSE_AND_EXIT
ret ;exit to DOS with ERRORLEVEL=0
.endp main
;=============================================================================
;Procedure: DISP_HDRSTRING
;
;DESC: Displays a short description to appear above the .DBF header lines
; e.g., '.DBF Header:'
;
;IN: HEADERMSG should point to the desired description.
;
;OUT: None
;=============================================================================
.PROC DISP_HDRSTRING
PUSH SI
MOV SI,OFFSET @DATASEG:HEADERMSG
CALL PUT_STR
CALL PUT_NEWLINE
POP SI
RET
.ENDP DISP_HDRSTRING
;=============================================================================
;Procedure: DISP_DESCSTRING
;
;DESC: Displays a short description to appear above the .DBF descriptor
; lines. e.g., '.Field Descriptor:'
;
;IN: FLDDESCMSG should point to the desired description.
;
;OUT: None
;=============================================================================
.PROC DISP_DESCSTRING
PUSH SI
MOV SI,OFFSET @DATASEG:FLDDESCMSG
CALL PUT_STR
CALL PUT_NEWLINE
POP SI
RET
.ENDP DISP_DESCSTRING
;=============================================================================
;Procedure: DISP_HEXCHR
;
;DESC: Converts next number to ASCII hex, and displays.
;
;IN: AL contains byte to be displayed.
;
;OUT: BYTECOUNTER is incremented; POS_COUNTER is incremented; BYTEHEXSTRING
; contains ascii hex form of byte.
;=============================================================================
.PROC DISP_HEXCHR
.PUSH AX,DX,SI
LODSB
MOV SI,OFFSET @DATASEG:BYTEHEXSTRING
CALL BYTE_TO_HEX
CALL PUT_STR
INC POS_COUNTER ; Keep track of where the cursor is in hex area.
MOV DX,WORD PTR BYTECOUNTER[2]
MOV AX,WORD PTR BYTECOUNTER[0]
.INC_D DX,AX ; Increment doubleword at BYTECOUNTER
MOV WORD PTR BYTECOUNTER[2],DX
MOV WORD PTR BYTECOUNTER[0],AX
.POP AX,DX,SI
RET
.ENDP DISP_HEXCHR
;=============================================================================
;Procedure: GET_AND_DISP_HEADER
;
;DESC: Reads header information, and displays offset, hex and ascii.
;
;IN: None
;
;OUT: BYTECOUNTER is incremented.
;=============================================================================
.PROC GET_AND_DISP_HEADER
.PUSH CX,SI
MOV SI,OFFSET @DATASEG:VERSNO
; Read 32 bytes
CALL GET_AND_DISP_16BYTES ; Read and display 16 bytes in hexadecimal
; format and ascii format.
CALL GET_AND_DISP_16BYTES ; Same with the next 16 bytes.
CALL PUT_NEWLINE
.POP CX,SI
RET
.ENDP GET_AND_DISP_HEADER
;=============================================================================
;Procedure: GET_AND_DISP_DESC
;
;DESC: Reads and displays the field descriptor array.
;
;IN: None.
;
;OUT: BYTECOUNTER is incremented.
;=============================================================================
.PROC GET_AND_DISP_DESC ; Get and Display field descriptor array
.PUSH AX,CX,SI
GET_AND_DISP_DESC1:
MOV SI,OFFSET @DATASEG:FIELDNAME
; Each field descriptor is 32 bytes long.
CALL GET_AND_DISP_16BYTES
CALL GET_AND_DISP_16BYTES
CALL PUT_NEWLINE
INC FLDCOUNTER
MOV AL,FLDCOUNTER ; Move the number of fields displayed so far
; into AL.
CMP AL,NO_OF_FIELDS ; If the number of fields displayed is less
; the total number [ NO_OF_FIELDS ], then
JB GET_AND_DISP_DESC1 ; display another field.
.POP AX,CX,SI
RET ; Return when all fields specs have been
; displayed.
.ENDP GET_AND_DISP_DESC
;=============================================================================
;Procedure: GET_AND_DISP_TERMINATOR
;
;DESC: Reads and displays the terminator byte, which should be 0D, and
; which follows the field descriptor.
;
;IN:
;
;OUT: BYTECOUNTER is incremented.
;=============================================================================
.PROC GET_AND_DISP_TERMINATOR
.PUSH CX,SI
MOV CL,1
MOV SI,OFFSET @DATASEG:TERMINATOR
CALL GET_BYTES
CALL DISP_OFFSET
CALL DISP_BYTES
MOV CL,45 ; There will always be 45 spaces to display on
; a terminator line, right after the terminator (0D)
CALL PUT_SPACES ; so display them.
MOV CL,1
CALL DISP_ASCII ; Now display the corresponding ascii form of
; TERMINATOR, which in our interpretation is a period.
CALL PUT_NEWLINE
CALL PUT_NEWLINE
.POP CX,SI
RET
.ENDP GET_AND_DISP_TERMINATOR
;=============================================================================
;Procedure: CALCFROMHDR
;
;DESC: Using information from the header, calculates the length of the
; field descriptor array (DESCLEN), the number of fields (NO_OF_FIELDS),
; the number of hex/ascii lines to be displayed for each record
; (LINES_PER_RECORD), the number of bytes on the last line of each ;
; record block (REMAINING_BYTES) and the number of spaces to pad after
; the hex portion (REMAINING_SPACES).
;
;IN: None
;
;OUT: DESCLEN, NO_OF_FIELDS, LINES_PER_RECORD, REMAINING_BYTES,
; REMAINING_SPACES
;=============================================================================
.PROC CALCFROMHDR
.PUSH AX,BX,DX
XOR DX,DX
MOV AX,HEADERLEN
SUB AX,33
MOV DESCLEN,AX ; Field descriptor length
MOV BX,32
DIV BX
MOV NO_OF_FIELDS,AL
XOR DX,DX
MOV AX,RECLEN
MOV BX,16
DIV BX
MOV LINES_PER_RECORD,AX
MOV REMAINING_BYTES,DL
MOV AL,DL
CALL CALC_REM_SPACES
.POP AX,BX,DX
RET
.ENDP CALCFROMHDR
;=============================================================================
;Procedure: CALC_REM_SPACES
;
;DESC: Calculates the necessary number of spaces to pad a line with, after
; the hex area and before the ascii area.
;
;IN: AL contains the number of hex bytes on the line.
;
;OUT: REMAINING_SPACES contains the number of spaces to pad with.
;=============================================================================
.PROC CALC_REM_SPACES
.PUSH AX,BX
MOV BL,16
SUB BL,AL
MOV AL,3
MUL BL
MOV REMAINING_SPACES,AL
.POP AX,BX
RET
.ENDP CALC_REM_SPACES
;=============================================================================
;Procedure: DISP_OFFSET
;
;DESC: Displays the offset from the current 64k block that is being processed,
; as well as a couple of spaces after the offset and before the rest of
; the hex/ascii output.
;IN: BYTECOUNTER contains the hex form of the offset
;
;OUT: BYTECNTRSTRING contains the string form of the offset
;=============================================================================
.PROC DISP_OFFSET
.PUSH AX,SI
MOV SI,OFFSET @DATASEG:BYTECNTRSTRING
MOV AX, WORD PTR BYTECOUNTER[0]
CALL WORD_TO_HEX
CALL PUT_STR
CALL PUT_SPACE
CALL PUT_SPACE
.POP AX,SI
RET
.ENDP DISP_OFFSET
;=============================================================================
;Procedure: PUT_SPACES
;
;DESC: Displays cl number of spaces at the current cursor location.
;
;IN: CL contains number of spaces to display.
;
;OUT: None
;=============================================================================
.PROC PUT_SPACES
PUSH CX
PUT_SPACES1:
CALL PUT_SPACE
LOOP PUT_SPACES1
POP CX
RET
.ENDP PUT_SPACES
;=============================================================================
;Procedure: PUT_SPACE
;
;DESC: Displays a space at the current cursor location.
;
;IN: None
;
;OUT: None
;=============================================================================
.PROC PUT_SPACE
PUSH AX
MOV AL," "
CALL PUT_CHR
POP AX
RET
.ENDP PUT_SPACE
;=============================================================================
;Procedure: GET_AND_DISP_RECS
;
;DESC: Reads and displays all records from file.
;
;IN: None
;
;OUT: BYTECOUNTER is updated.
;=============================================================================
.PROC GET_AND_DISP_RECS
GET_AND_DISP_RECS1:
.PUSH AX,BX,CX,DX
MOV DX, WORD PTR RECNO[2] ; Bring high word of RECNO into DX
MOV AX, WORD PTR RECNO[0] ; and low word into AX.
MOV CX, WORD PTR RECCOUNT[2] ; High word of RECCOUNT into CX
MOV BX, WORD PTR RECCOUNT[0] ; and low word into BX.
.CMP_DD DX,AX,CX,BX ; Compare double words RECNO and RECCOUNT.
.POP AX,BX,CX,DX
JE GET_AND_DISP_RECSEND ; If RECNO is now the same as RECCOUNT,
; stop displaying records.
CALL DISP_RECNO ; Display hex/decimal string form of record number.
CALL GET_AND_DISP_REC ; Read record from file, and display it in
; hex and ascii formats.
CALL PUT_NEWLINE
JMP GET_AND_DISP_RECS1 ; Loop back to get and display another record.
GET_AND_DISP_RECSEND:
RET
.ENDP GET_AND_DISP_RECS
;=============================================================================
;Procedure: DISP_RECNO
;
;DESC: Displays the current record number, in hex and decimal ascii formats.
;
;IN: None
;
;OUT: Increments RECNO.
;=============================================================================
.PROC DISP_RECNO
.PUSH AX,BX,CX,DX,SI
XOR CH,CH
MOV CL,11
CALL PUT_SPACES
MOV SI,OFFSET @DATASEG:RECNOMSG
CALL PUT_STR
MOV DX,WORD PTR RECNO[2]
MOV AX,WORD PTR RECNO[0]
.INC_D DX,AX ; Increment double word at RECNO.
MOV WORD PTR RECNO[2],DX
MOV WORD PTR RECNO[0],AX
MOV BL,16
MOV SI,OFFSET @DATASEG:RECNOSTRING
CALL DWORD_TO_ASC
CALL PUT_STR
MOV AL,'h'
CALL PUT_CHR
MOV AL,'/'
CALL PUT_CHR
MOV DX,WORD PTR RECNO[2]
MOV AX,WORD PTR RECNO[0]
MOV BL,10
MOV SI,OFFSET @DATASEG:RECNOSTRING
CALL DWORD_TO_ASC
CALL PUT_STR
MOV AL,'d'
CALL PUT_CHR
MOV AL,':'
CALL PUT_CHR
CALL PUT_NEWLINE
.POP AX,BX,CX,DX,SI
RET
.ENDP DISP_RECNO
;=============================================================================
;Procedure: GET_AND_DISP_REC
;
;DESC: Reads 16 bytes from file, and displays in hex and ascii format.
;
;IN: None
;
;OUT: BYTECOUNTER is updated.
;=============================================================================
.PROC GET_AND_DISP_REC
.PUSH AX,CX,SI
GET_AND_DISP_REC1:
MOV SI,OFFSET @DATASEG:RECORDDATA
CALL GET_AND_DISP_16BYTES ;Display 16 bytes of a record.
INC RECBLKCOUNTER
MOV AX,RECBLKCOUNTER
CMP AX,LINES_PER_RECORD
JB GET_AND_DISP_REC1
MOV RECBLKCOUNTER,0
MOV SI,OFFSET @DATASEG:RECORDDATA
XOR CH,CH
MOV CL,REMAINING_BYTES
CMP CL,0
JE GET_AND_DISP_RECEND ;If no remaining bytes in block, then display
; blank line and return.
CALL GET_BYTES
CALL DISP_OFFSET
CALL DISP_REMBYTES
GET_AND_DISP_RECEND:
CALL PUT_NEWLINE
.POP AX,CX,SI
RET
.ENDP GET_AND_DISP_REC
;=============================================================================
;Procedure: GET_AND_DISP_16BYTES
;
;DESC: Reads 16 bytes from file, and displays in hex and ascii format.
;
;IN: SI points to sequence of bytes.
;
;OUT: BYTECOUNTER is updated.
;=============================================================================
.PROC GET_AND_DISP_16BYTES
PUSH CX
MOV CX,16
CALL GET_BYTES
CALL DISP_OFFSET
CALL DISP_BYTES
CALL DISP_ASCII_CHARS
CALL PUT_NEWLINE
POP CX
RET
.ENDP GET_AND_DISP_16BYTES
;=============================================================================
;Procedure: GET_BYTES
;
;DESC: Reads CL number of bytes from file.
;
;IN: CL contains number of bytes to read. SI points to sequence of bytes.
; BL contains the file handle.
;
;OUT:
;=============================================================================
.PROC GET_BYTES
.PUSH CX,SI
MOV NUM_BYTES_TO_READ,CL
CALL READ_H
JA GET_BYTES1
JMP GET_BYTES2
GET_BYTES1:
CALL CLOSE_AND_EXIT
GET_BYTES2:
CMP CL,NUM_BYTES_TO_READ ;If number of bytes read is less than
; expected, pointer must be at end of file.
JE GET_BYTESEND
GET_BYTESEND:
.POP CX,SI
RET
.ENDP GET_BYTES
;=============================================================================
;Procedure: LAST_BYTES
;
;DESC: Reads and displays the last line of file.
;
;IN: BL contains the file handle.
;
;OUT: None
;=============================================================================
.PROC LAST_BYTES
.PUSH AX,BX,CX,SI
MOV SI,OFFSET @DATASEG:RECORDDATA
MOV CX,16 ; There should only be 1 byte left to read, but it
; doesn't hurt to attempt it at 16. The true number
; of bytes left will be returned in CL after a call
; to READ_H.
CALL READ_H
CALL DISP_OFFSET
CALL DISP_BYTES
MOV REMAINING_BYTES,CL
MOV AL,CL
CALL CALC_REM_SPACES
MOV CL,REMAINING_SPACES
CALL PUT_SPACES
MOV CL,REMAINING_BYTES
CALL DISP_ASCII_CHARS
CALL PUT_NEWLINE
.POP AX,BX,CX,SI
RET
.ENDP LAST_BYTES
;=============================================================================
;Procedure: DISP_BYTES
;
;DESC: Displays CL number of bytes from file, in hex format.
;
;IN: CL contains number of bytes to display. SI points to sequence of bytes.
;
;OUT: None
;=============================================================================
.PROC DISP_BYTES
PUSH AX
MOV CURPOINTER,SI
MOV POS_COUNTER,0
DISP_BYTES1:
CALL DISP_HEXCHR
CALL PUT_SPACE
INC SI
CMP POS_COUNTER,CL ;If position counter is still less than the
; number of bytes to be displayed, then
JNE DISP_BYTES1 ; continue displaying.
POP AX
RET
.ENDP DISP_BYTES
;=============================================================================
;Procedure: DISP_ASCII_CHARS
;
;DESC: Displays CL number of bytes from file, in ascii format.
;
;IN: CL contains number of bytes to display. SI points to sequence of bytes.
;
;OUT: None
;=============================================================================
.PROC DISP_ASCII_CHARS
PUSH AX
MOV SI,CURPOINTER
MOV POS_COUNTER,0
DISP_BYTES2:
CALL DISP_ASCII
INC SI
CMP POS_COUNTER,CL
JNE DISP_BYTES2
POP AX
RET
.ENDP DISP_ASCII_CHARS
;=============================================================================
;Procedure: DISP_ASCII
;
;DESC: Displays byte in ascii format. If ascii code of byte is less than 32,
; (20h), then display a period (.).
;
;IN: AL contains byte to display.
;
;OUT: POS_COUNTER is incremented.
;=============================================================================
.PROC DISP_ASCII
.PUSH AX,BX,SI
LODSB
CMP AL,20h
JB PUT_PERIOD
CALL PUT_CHR
JMP DISP_ASCII1
PUT_PERIOD:
MOV AL,'.'
CALL PUT_CHR
DISP_ASCII1:
INC POS_COUNTER
.POP AX,BX,SI
RET
.ENDP DISP_ASCII
;=============================================================================
;Procedure: DISP_REMBYTES
;
;DESC: Displays last line of record, if less than 16 bytes and more than 0.
; If the last line contains exactly 16 bytes, then it has already
; been displayed during a call to DISP_BYTES.
;
;IN: AL contains byte to display. SI points to sequence of bytes.
;
;OUT: POS_COUNTER is incremented.
;=============================================================================
.PROC DISP_REMBYTES ; Display remainder of record.
.PUSH AX,SI,CX
MOV CURPOINTER,SI
MOV POS_COUNTER,0
DISP_REMBYTES1:
CALL DISP_HEXCHR
CALL PUT_SPACE
INC SI
MOV AL,REMAINING_BYTES
CMP POS_COUNTER,AL
JNE DISP_REMBYTES1
MOV CL,REMAINING_SPACES
CALL PUT_SPACES
MOV SI,CURPOINTER
MOV POS_COUNTER,0
DISP_REMBYTES2:
CALL DISP_ASCII
INC SI
MOV AL,REMAINING_BYTES
CMP POS_COUNTER,AL
JNE DISP_REMBYTES2
.POP AX,SI,CX
RET
.ENDP DISP_REMBYTES
;=============================================================================
;Procedure: OPENDBF
;
;DESC: Opens a .DBF file.
;
;IN: DS:SI should point to the .DBF PATHNAME.
;
;OUT: BX and DBHANDLE contain the file handle.
;=============================================================================
.PROC OPENDBF
.PUSH AX,CX,DX,SI,DI
MOV DI,OFFSET @DATASEG:DBFNAME
CALL STR_LEN
CALL STR_NCPY ; Now DI should point to the full path name,
; with or without the extension.
MOV SI,DI ; But now SI should have the path name.
MOV DI,OFFSET @DATASEG:DBEXT
PUSH SI
CALL STR_STRI ; Look for ".DBF" extension in path name;
; that is, look for the extension pointed
; to by DI in the string pointed to by SI.
POP SI
JNC OPEN_IT ; If the extension is in the filename,
; open the file.
; Otherwise,...
; Right now, SI points to the filename
; string, and DI points to the extension.
XCHG SI,DI ; Make DI point to the filename and SI to
; the extension, for a call to STR_CAT.
CALL STR_CAT ; Append the extension to the filename;
; that is, append the string pointed to
; by SI to the string pointed to by DI.
MOV SI,DI ; Okay. Now move the offset of the path
; name back into SI.
OPEN_IT:
MOV AX,O_RDONLY
CALL OPEN_H
JC OPENDBFOUT
JMP OPENDBFEND
OPENDBFOUT:
CALL CLOSE_AND_EXIT
OPENDBFEND:
MOV DBHANDLE,BX ; The file handle will generally remain in BX
; throughout the program, but store it in DBHANDLE
; just in case BX is temporarily used for
; something else.
CALL GETFSIZE_H ; Get size of file at handle BX.
MOV FILESIZE[0],AX ; Store it in FILESIZE.
MOV FILESIZE[2],DX
.POP AX,CX,DX,SI,DI
RET
.ENDP OPENDBF
.ends
.public nheap_default, fheap_default
.stackseg
.public stack_end ;used by START to normalize stack
.label stack_end word ;must be defined past entire stack
.label nheap_default word ;used by the near heap
.label fheap_default word ;used by the far heap
.ends
end start ;specify START as starting address