SPRAY.ASM


comment }

  SPRAY.COM      program copyright Dave Angel  71046,1567.

                 free for anybody, as long as it's not included with

                 commercial software.  Nominal charge (under $6) okay.



  SPRAY.ASM      This file serves as both documentation and source code.

                 The program was written in response to a message by

                 Joe Wallace 21550,6003, who wanted a program to dump

                 memory after an accidental abort of some other program.



                 The program was entered with KEDIT, assembled with MASM

                 5.1, and debugged with SYMDEB.  There are several known

                 simplifications, to keep it small.



                 It only parses the command line to the extent that if the

                 command line is non-blank it gives the copyright message.

                 If run with a blank line, it dumps memory from its own end

                 to the 640k boundary.  If you have some other amount of

                 memory, change the line below containing '**memory' as

                 appropriate.



                 It outputs to standard out, and you have to redirect it if

                 you want it in a disk file.  So you'd run   SPRAY>C:\temp

                 to get it to dump to a file on C: called temp.



                 Finally, it will go somewhat beyond the (640k) limit, as

                 much as 63.9 k beyond.  This is no problem on most

                 systems, you just may get a bit of garbage at the end.

                 But on a few systems you may get funny errors accessing

                 that memory.  If so, the 'nextsegment' logic needs to be

                 tightened up, to handle the final, partial segment.



                 Good luck.  Any suggestions or improvements welcome.

                 Dave Angel  Compuserve 71046,1456    or    Genie   D.Angel

                 July 27, 1989



}

CGROUP  group  CODE

CODE    segment

        org     100h

     assume  cs:CODE, DS:CODE

start   proc    near

        mov     sp,100h

        cmp     byte ptr ds:[80h],0

        jz      start2

        mov     dx,offset CGROUP:helpmessage

        mov     ah,9

        int     21h

        jmp     next2

helpmessage     db    'SPRAY  copyright 1989 by Dave Angel 71046,1567',13,10

                db    '   free software to dump memory to stdout',13,10,'$'



start2:

        mov     di,offset CGROUP:endcode

        mov     si,offset CGROUP:endcode+5  ; source starting address

        cld

        mov     cx,78

        xor     bx,bx           ; bx is count of printables 'in-a-row'

loop1:

        cmp     si,0fff0h

        jb      loop1a

        call    nextsegment        ; call if we're at end of segment

loop1a:

        lodsb                   ; retrieve one byte

        cmp     al,20h

        jb      loop5

        cmp     al,7fh

        ja      loop5           ; skip if unprintable character

;  found a printable character

loop2:

        stosb

        inc     bx

        loop    loop1

; we've printed enough on this line, go to next

loop3:

        mov     al,0dh

        stosb

        mov     al,0ah

        stosb

        call    flushoutput             ; write the data so far

        xor     bx,bx

        loop    loop1



;  We found a non-printable

loop5:

        cmp     bx,3

        ja      loop5a          ; skip if at least 3 printables in a row

        sub     di,bx

        add     cx,bx           ; back up over them, if 3 or less

        jmp     loop5b

loop5a:

        cmp     cx,8

        jb      loop3           ; if near the end of line, make a new one

        mov     al,20h

        stosb

        dec     cx

        stosb           ; otherwise, add two spaces and keep scanning

loop5b:

        dec     cx

loop6:

        xor     bx,bx           ; zero 'printables in-a-row'

        cmp     si,0fff0h

        jb      loop6a

        call    nextsegment        ; call if we're at end of segment

loop6a:

        lodsb

        cmp     al,20h

        jb      loop6

        cmp     al,7fh

        ja      loop6           ; ignore any more unprintables

        jmp     loop2

start   endp



flushoutput     proc    near

;  DI points one beyond last character of buffer.  So write from

;    endcode to one less than DI

        mov     cx,di

        mov     dx,offset CGROUP:endcode            ; address

        sub     cx,dx           ; count

        mov     bx,1            ; standard out

        mov     ah,40h

        push    ds

        push    cs

        pop     ds

        int     21h             ; write the line to stdout

        pop     ds

     ; ignore errors

        mov     di,offset cgroup:endcode

        mov     cx,78

        ret

flushoutput     endp





nextsegment     proc    near

;  this routine is only called when SI exceeds FFF0

;  here's where we move to another segment, and check for 640k.  We adjust

;  DS and SI, and return, if still more to do.



        push    bx              ; save bx

        mov     bx,0a000h       ; end of **memory assumed to be A000

        mov     ax,ds

        add     ax,0fffh

        sub     si,0fff0h

        mov     ds,ax

; notice, we're being sloppy here, and dumping as much as 63.9k beyond 640k

        cmp     ax,bx

        jae     next2

        pop     bx              ; restore bx

        ret                     ; return if still more memory to go

next2:

        mov     ax,4c00h

        int     21h

nextsegment     endp

endcode label   byte

CODE    ends

        end     start