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