programmers resources
  http://www.intel-assembler.it/  (c)2017 intel-assembler.it   info@intel-assembler.it
 
Search :  
Lingua Italiana    English Language   
Index
 
just an empty assembly space
just an arrow Intel Platform
just an arrow Article & Guides
just an arrow Download Software


23/01/2009 Featured Article: How to remove Buzus Virus (permalink)




:::3061960:::
Bottone Scambio Directory Pubblicitaonline.it
Home Page | Articles & Guides | Download | Intel Platform | Contacts

Google
 


Bookmark and Share
Download 
Tell a friend



Simple text mode File Browser

DOS Assembly source code

(by unknown)

A fully commented Intel source code which implements a file browser in a DOS window. Very simple and a good example of coding.
This article is online from 2311 days and has been seen 7341 times




;       BROWSE.ASM -- Full Screen File Pager
;       ====================================

CSEG            Segment
                Assume  CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
                Org     0080h
Parameter       Label   Byte
                Org     0100h
Entry:          Jmp Begin

;       All Data
;       --------

                db      'ATTR='
Attribute       db      0               ; Current screen attribute
                db      'SHIFT='
ShiftHoriz      db      8               ; Horizontal shift screen default
DosVersionFail  db      'Requires DOS 2.0 or above$'
NoSpaceFail     db      'Not enough memory$'
FileFail        db      'File Not Found$'
ScreenFail      db      'Unsupported video mode$'
Delimiters      db      9,' ,;=/'       ; Delimiters in parameter
FileHandle      dw      ?               ; Use for saving file handle
WSMode          db      0FFh            ; AND value for non-WordStar mode
LineLength      db      ?               ; Length of line (from BIOS)
NumberLines     db      25,0            ; Number of lines (check EGA BIOS)
ScreenSize      dw      ?               ; Size of screen in bytes
CheckRetrace    db      1               ; Flag zero if EGA or MONO used
Addr6845        dw      ?               ; Could use for retrace check
ScreenAddr      Label   DWord           ; Address of screen
ScreenOff       dw      0               ; Higher for non-page 0
ScreenSeg       dw      0B800h          ; Set to B000h for Mono Mode 7
ScreenStart     dw      ?               ; Points within buffer
EndOfFile       dw      ?               ; Points within buffer
FileOffset      dw      -1, -1          ; Address within file of buffer data
HorizOffset     dw      0               ; Horizontal offset for display
RightMargin     dw      0               ; Right margin for offset display
Dispatch        dw      Home, Up, PgUp, Dummy, Left
                dw      Dummy, Right, Dummy, End, Down, PgDn

;       Check DOS Version for 2.0 or above
;       ----------------------------------

Begin:          Cld                     ; All string directions forward
                Mov     AH,30h
                Int     21h             ; Get DOS Version Number
                Cmp     AL,2            ; Check for 2.0 or later
                Jae     DOSVerOK
                Mov     DX,Offset DOSVersionFail
ErrorExit:      Mov     AH,9            ; Write error message
                Int     21h
                Int     20h

;       Parse Command Line to get File Name and WordStar flag
;       -----------------------------------------------------

DOSVerOK:       Mov     SI,1 + Offset Parameter ; Points to parameter
NameSearch:     Lodsb                           ; Get byte
                Cmp     AL,13                   ; Check if carriage return
                Jz      NoFileFound             ; If so, no file name
                Mov     DI,Offset Delimiters    ; String of delimiters
                Mov     CX,5                    ; Number of delimiters (no /)
                Repne   Scasb                   ; See if a match
                Je      NameSearch              ; If a delimiter, keep looking
                Mov     DX,SI                   ; Otherwise found file name
                Dec     DX                      ; Points to beginning of it
EndSearch:      Lodsb                           ; Get next byte
                Cmp     AL,13                   ; See if carriage return
                Je      GotFileEnd              ; If so, we're all done
                Mov     DI,Offset Delimiters    ; String of delimiters
                Mov     CX,6                    ; Number (including /)
                Repne   Scasb                   ; See if a match
                Jne     EndSearch               ; If not, still in file name
                Mov     Byte Ptr [SI - 1],0     ; If so, mark end of file name
                Jcxz    GotFlag                 ; If slash, check for W
                Jmp     EndSearch               ; Or continue flag search
GotFlag:        Lodsb                           ; Get byte after / flag
                Or      AL,20h                  ; Uncapitalize
                Cmp     AL,'w'                  ; See if w for WordStar mode
                Jnz     GotFileEnd              ; If not, just ignore it
                Mov     [WSMode],7Fh            ; AND value for WordStar

;       Open the File
;       -------------

GotFileEnd:     Mov     Byte Ptr [SI - 1],0     ; Mark end of file name
                                                ; DX still points to name
                Mov     AX,3D00h                ; Open file for reading
                Int     21h                     ;   by calling DOS
                Jnc     GotTheFile              ; If no error, continue
NoFileFound:    Mov     DX,Offset FileFail      ; Otherwise print a message
                Jmp     ErrorExit
GotTheFile:     Mov     [FileHandle],AX         ; Save the file handle

;       Get Screen Mode Information from BIOS Data Area
;       -----------------------------------------------

                Push    ES                      ; Save register
                Sub     AX,AX
                Mov     ES,AX                   ; Set ES to 0 (BIOS Data)
                Mov     AL,ES:[0449h]           ; Current Video Mode
                Cmp     AL,3                    ; Check if Color Alpha
                Jbe     DisplayOK               ; Continue if so
                Cmp     AL,7                    ; Check if monochrome display
                Je      Monochrome              ; If so, branch
                Mov     DX,Offset ScreenFail    ; We can't handle graphics
                Jmp     ErrorExit               ; So print an error message
Monochrome:     Mov     [ScreenSeg],0B000h      ; Use Monochrome Segment
                Mov     [CheckRetrace],0        ; Don't have to check retrace
DisplayOK:      Mov     AL,ES:[044Ah]           ; Number of Columns
                Mov     [LineLength],AL         ; Save it
                Mov     AX,ES:[044Eh]           ; Offset into screen buffer
                Mov     [ScreenOff],AX          ; Save it
                Mov     AX,ES:[0463h]           ; Address of 6845 Regsiter
                Mov     [Addr6845],AX           ; Save it
                Push    ES
                Sub     DL,DL                   ; Set Rows to zero first
                Sub     BH,BH
                Mov     AX,1130h                ; EGA BIOS: Get Information
                Int     10h
                Pop     ES
                Or      DL,DL                   ; Check if DL is still zero
                Jz      NoEGA                   ; If so, skip rest of stuff
                Inc     DL
                Mov     [NumberLines],DL        ; Save Number of Lines
                Test    Byte Ptr ES:[0487h],4   ; Check if must check retrace
                Jnz     NoEGA
                Mov     [CheckRetrace],0        ; EGA says we don't have to
NoEGA:          Mov     BH,ES:[0462h]           ; Get Current Page (use later)
                Pop     ES
                Mov     AL,[LineLength]         ; Length of each line
                Mul     [NumberLines]           ; Total chars on screen
                Add     AX,AX                   ; Double for attributes
                Mov     [ScreenSize],AX         ; And Save it

;       See if enough memory is left
;       ----------------------------

                Add     AX,Offset ScreenHold    ; Add ScreenSize to code end
                Add     AX,256                  ; Add a little stack room
                Cmp     AX,SP                   ; Check against stack pointer
                Jbe     GotEnufMemory           ; Continue if OK
                Mov     DX,Offset NoSpaceFail   ; Otherwise end program
                Jmp     ErrorExit               ;    with error messae

;       Get Current Screen Attribute
;       ----------------------------

GotEnufMemory:  Cmp     [Attribute],0           ; Check if attribute pre-set
                Jnz     GotAttribute            ; If so, move on
                Mov     DL,' '                  ; Write out a byte
                Mov     AH,2                    ;   using DOS
                Int     21h
                Mov     AL,8                    ; Now backspace
                Mov     AH,14                   ;   using BIOS call
                Int     10h
                Mov     AH,8                    ; Read character & attribute
                Int     10h                     ;   using BIOS call (BH = pg)
                Mov     [Attribute],AH          ; And save attribute

;       Save Current Screen
;       -------------------

GotAttribute:   Mov     DX,Offset Terminate     ; Set Ctrl-Break exit
                Mov     AX,2523h                ;   to terminate that way
                Int     21h
                Mov     DI,Offset ScreenHold    ; Destination of screen
                Mov     CX,[ScreenSize]         ; Size of screen
                Push    DS                      ; Save Source Segment
                Lds     SI,[ScreenAddr]         ; Get screen address
                Rep     Movsb                   ; Move in the bytes
                Pop     DS                      ; Restore Source Segment

;       Get Keyboard Key and Decide on Action
;       -------------------------------------

                Call    Home                    ; Read file in
                Mov     [ScreenStart],SI        ; Set buffer address
KeyLoop:        Call    UpDateScreen            ; Write file to screen
GetKey:         Mov     AH,8                    ; Get key
                Int     21h                     ;   by calling DOS
                Cmp     AL,27                   ; Check if ESC
                Je      Terminate               ; If so, terminate
                Cmp     AL,0                    ; Check if extended
                Jnz     GetKey                  ; If not, try again
                Mov     AH,8                    ; Get extended code
                Int     21h                     ;   by calling DOS
                Sub     AL,71                   ; Subtract Home key value
                Jb      GetKey                  ; If below that, not valid
                Cmp     AL,(81 - 71)            ; Check if above PgDn
                Ja      GetKey                  ; If so, ignore it
                Sub     AH,AH                   ; Zero out top byte
                Add     AX,AX                   ; Double for word access
                Mov     BX,AX                   ; Offset in dispatch table
                Mov     SI,[ScreenStart]        ; Set current buffer pointer
                Call    [Dispatch + BX]         ; Do the call
                Mov     [ScreenStart],SI        ; Set new buffer pointer
                Jmp     KeyLoop                 ; And update the screen

;       Terminate -- Restore screen and close file
;       ------------------------------------------

Terminate:      Mov     SI,Offset ScreenHold    ; Address of Saved Screen
                Les     DI,[ScreenAddr]         ; Address of Display
                Mov     CX,[ScreenSize]         ; Number of characters
                Rep     Movsb                   ; Move them back
                Mov     BX,[FileHandle]         ; Get File Handle
                Mov     AH,3Eh                  ; Close File
                Int     21h
                Int     20h                     ; Terminate

;       Cursor Key Routines -- Home Key
;       -------------------------------

Home:           Sub     BX,BX                   ; For zeroing out values
                Mov     AX,[FileOffset]         ; Check if read in file
                Or      AX,[FileOffset + 2]
                Mov     [FileOffset],BX         ; Zero out file address
                Mov     [FileOffset + 2],BX
                Mov     [HorizOffset],BX        ; Zero out horizontal offset
                Mov     SI,Offset Buffer        ; Reset buffer pointer
                Jz      Dummy                   ; Skip file read if in already
                Mov     DX,Offset Buffer        ; Area to read file in
                Mov     CX,32768                ; Number of bytes to read
                Call    FileRead                ; Read in file
Dummy:          Ret

;       Up and PgUp Keys
;       ----------------

Up:             Call    GetPrevChar             ; Get previous char in buffer
                Jc      UpDone                  ; If none available, finish
UpLoop:         Call    GetPrevChar             ; Get previous char again
                Jc      UpDone                  ; if none, we're done
                Cmp     AL,10                   ; Check if line feed
                Jnz     UpLoop                  ; If not, try again
                Call    GetNextChar             ; Get char after line feed
UpDone:         Ret

PgUp:           Mov     CX,Word Ptr [NumberLines]       ; Number of lines
PgUpLoop:       Call    Up                      ; Do UP that many times
                Loop    PgUpLoop
                Ret

;       Left and Right Keys
;       -------------------

Left:           Mov     [HorizOffset],0         ; Reset Horizontal Offset
                Ret

Right:          Mov     AL,[ShiftHoriz]         ; Get places to shift
                Sub     AH,AH
                Add     [HorizOffset],AX        ; Move that many right
                Ret

;       End, Down, and PgDn Keys
;       ------------------------

End:            Mov     BX,SI                   ; Save buffer pointer
                Call    PgDn                    ; Go page down
                Cmp     BX,SI                   ; Check if we did so
                Jnz     End                     ; If so, do it again
                Ret

Down:           Call    GetNextChar             ; Get next character
                Jc      NoMoreDown              ; If no more, we're done
DownLoop:       Call    GetNextChar             ; Get one again
                Jc      UpLoop                  ; If no more, find prev LF
                Cmp     AL,10                   ; See if line feed
                Jnz     DownLoop                ; If not, continue
NoMoreDown:     Ret

PgDn:           Mov     CX,Word Ptr [NumberLines]       ; Number of lines
PgDnLoop:       Call    Down                    ; Do DOWN that many times
                Loop    PgDnLoop
                Ret

;       Update Screen
;       -------------

UpdateScreen:   Push    ES
                Mov     SI,[ScreenStart]        ; Address of data in buffer
                Les     DI,[ScreenAddr]         ; Address of display
                Mov     CX,ScreenSize           ; Number of bytes in screen
                Shr     CX,1                    ; Half for number of chars
                Mov     AL,' '                  ; Will blank screen
                Mov     AH,[Attribute]          ; With screen attribute
                Rep     Stosw                   ; Blank it
                Mov     AL,[LineLength]         ; Length of display line
                Sub     AH,AH
                Add     AX,[HorizOffset]        ; Add Horizontal Offset
                Mov     [RightMargin],AX        ; That's right display margin
                Sub     DL,DL                   ; Line Number
LineLoop:       Sub     BX,BX                   ; Column Number
                Mov     AL,[LineLength]         ; Use Line Length
                Mul     DL                      ;   and Line Number
                Add     AX,AX                   ;     to recalculate
                Mov     DI,AX                   ;       display destination
                Add     DI,[ScreenOff]          ; Add beginning address
CharLoop:       Call    GetNextChar             ; Get next character
                Jc      EndOfScreen             ; If no more, we're done
                And     AL,[WSMode]             ; Will be 7Fh for WordStar
                Cmp     AL,13                   ; Check for carriage return
                Je      CharLoop                ; Do nothing if so
                Cmp     AL,10                   ; Check for line feed
                Je      LineFeed                ; Do routine if so
                Cmp     AL,9                    ; Check for tab
                Je      Tab                     ; Do routine if so
                Mov     CX,1                    ; Just 1 char to display
PrintChar:      Cmp     BX,[HorizOffset]        ; See if we can print it
                Jb      NoPrint
                Cmp     BX,[RightMargin]        ; See if within margin
                Jae     NoPrint
                Mov     AH,[Attribute]          ; Attribute for display
                Cmp     [CheckRetrace],0        ; See if must stop snow
                Jz      WriteIt                 ; If not, skip retrace wait
                Push    BX
                Push    DX
                Mov     BX,AX                   ; Save character and attribute
                Mov     DX,[Addr6845]           ; Set up I/O address
                Add     DX,6
RetraceWait1:   In      AL,DX                   ; Check until
                Shr     AL,1                    ;   vertical retrace
                Jc      RetraceWait1            ;     ends
                Cli                             ; Clear interrupts
RetraceWait2:   In      AL,DX                   ; Check until
                Shr     AL,1                    ;   vertical retrace
                Jnc     RetraceWait2            ;     begins
                Mov     AX,BX                   ; Get back character & attr
                Stosw                           ; Write to display
                Sti                             ; Enable interrupts again
                Pop     DX
                Pop     BX
                Jmp     Short NoPrint           ; Skip around "no snow" write
WriteIt:        Stosw                           ; Write without retrace wait
NoPrint:        Inc     BX                      ; Bump up line counter
                Loop    PrintChar               ; Do it CX times
                Jmp     CharLoop                ; Then go back to top
Tab:            Mov     AX,BX                   ; Current column number
                And     AX,07h                  ; Take lower three bits
                Mov     CX,8
                Sub     CX,AX                   ; Subtract from 8
                Mov     AL,' '                  ; Will print CX blanks
                Jmp     PrintChar
LineFeed:       Inc     DL                      ; Next line
                Cmp     DL,[NumberLines]        ; See if down at bottom
                Jb      LineLoop                ; If not, continue
EndOfScreen:    Pop     ES                      ; All done -- leave
                Ret

;       Get Next Character from buffer
;       ------------------------------
;               (Input is SI pointing to buffer, Returns AL, CY if no more)

GetNextChar:    Cmp     SI,[EndOfFile]          ; See if at end of file
                Jae     NoMoreNext              ; If so, no more chars
                Cmp     SI,Offset BufferEnd     ; See if at end of buffer
                Jb      CanGetNext              ; If not, just get character
                Push    CX                      ; Otherwise save registers
                Push    DX
                Push    DI
                Push    ES
                Push    DS                      ; Set ES to DS
                Pop     ES                      ;   (could be different)
                Mov     SI,Offset BufferMid     ; Move 2nd buffer half
                Mov     DI,Offset Buffer        ;   to 1st buffer half
                Mov     CX,16384
                Sub     [ScreenStart],CX        ; New buffer pointer
                Rep     Movsb                   ; Move them
                Mov     SI,DI                   ; SI also buffer pointer
                Add     [FileOffset],32768      ; Adjust file addr to read
                Adc     [FileOffset + 2],0
                Mov     DX,Offset BufferMid     ; Place to read file
                Mov     CX,16384                ; Number of bytes
                Call    FileRead                ; Read the file
                Sub     [FileOffset],16384      ; Now adjust so reflects
                Sbb     [FileOffset + 2],0      ;   1st half of buffer
                Pop     ES                      ; Get back registers
                Pop     DI
                Pop     DX
                Pop     CX
                Jmp     GetNextChar             ; And try again to get char
CanGetNext:     Lodsb                           ; Get the character
NoMoreNext:     Cmc                             ; So CY set if no more
                Ret

;       Get Previous Character from buffer
;       ----------------------------------

GetPrevChar:    Cmp     SI,Offset Buffer        ; See if at top of buffer
                Ja      CanGetPrev              ; If not, just get character
                Mov     AX,[FileOffset]         ; See if at top of file
                Or      AX,[FileOffset + 2]
                Jz      AtTopAlready            ; If so, can't get anymore
                Push    CX                      ; Save some registers
                Push    DX
                Mov     SI,Offset Buffer        ; Move 1st half of buffer
                Mov     DI,Offset BufferMid     ;   to 2nd half of buffer
                Mov     CX,16384
                Add     [ScreenStart],CX        ; New buffer pointer
                Rep     Movsb                   ; Do the move
                Sub     [FileOffset],16384      ; Adjust file addr for read
                Sbb     [FileOffset + 2],0
                Mov     DX,Offset Buffer        ; Area to read file into
                Mov     CX,16384                ; Number of bytes
                Call    FileRead                ; Read the file
                Pop     DX                      ; Get back registers
                Pop     CX
                Jmp     Short CanGetPrev        ; Now get character
AtTopAlready:   Stc                             ; CY flag set for no more
                Ret
CanGetPrev:     Dec     SI                      ; Move pointer back
                Mov     AL,[SI]                 ; Get the character
                Clc                             ; CY flag reset for success
                Ret

;       Read CX bytes from the file into DX buffer
;       ------------------------------------------

FileRead:       Push    AX                      ; Save some registers
                Push    BX
                Push    CX
                Push    DX
                Mov     [EndOfFile],-1          ; Initialize this
                Mov     DX,[FileOffset]         ; Get file address to read
                Mov     CX,[FileOffset + 2]
                Mov     BX,[FileHandle]         ; Get file Handle
                Sub     AL,AL                   ; Do LSEEK from beginning
                Mov     AH,42h                  ; LSEEK call
                Int     21h
                Pop     DX                      ; Get back destination
                Pop     CX                      ; Get back count
                Mov     AH,3Fh                  ; Read file function call
                Int     21h
                Jnc     NoReadError             ; If no error, continue
                Sub     AX,AX                   ; Otherwise read zero bytes
NoReadError:    Cmp     AX,CX                   ; See if 32K has been read
                Je      GotItAll                ; If so, we're home free
                Add     AX,DX                   ; Otherwise add to buffer addr
                Mov     [EndOfFile],AX          ; And save as end of file
GotItAll:       Pop     BX
                Pop     AX
                Ret

;       File Buffer and Screen Hold Areas
;       ---------------------------------

Buffer          Label   Byte                    ; Area for file reads
BufferMid       equ     Buffer + 16384          ; Halfway through it
BufferEnd       equ     BufferMid + 16384       ; At end of it
ScreenHold      equ     BufferEnd               ; Area for holding screen
CSEG            EndS                            ; End of segment
                End     Entry                   ; Denotes entry point



Top
Download 
Tell a friend
Bookmark and Share



Similar Articles

386ID Four ways to identify your CPU model
Commented assembly source code
(by Bob Smith - Qualitas)

An assembler DOS Shell
A short code to execute dos commands
(by L. B. Neal)

Directory Treeview x86 assembly source
A commented example of directory tree view
(by Swift-Ware)

Extending DOS Executables
How to modify a Windows executable relocating code
(by Digital Alchemist)

Tetris simple arcade
Tetris source code in x86 assembly only 2K
(by Tore Bastiansen)

UMB Residency
Esempio di allocazione di codice in UMB
(by Dark Angel)

 Tags: medium source


webmaster jes
writers rguru, tech-g, aiguru, drAx

site optimized for IE/Firefox/Chrome with 1024x768 resolution

Valid HTML 4.01 Transitional


ALL TRADEMARKS ® ARE PROPERTY OF LEGITTIMATE OWNERS.
© ALL RIGHTS RESERVED.

hosting&web - www.accademia3.it

grossocactus
find rguru on
http://www.twitter.com/sicurezza3/
... send an email ...
Your name

Destination email

Message

captcha! Code