history.asm
来自「比dos下的debug更好的debug程序源码」· 汇编 代码 · 共 383 行
ASM
383 行
;
; GRDP
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
;
; HISTORY.ASM
;
; Function: Handle command line history
;
;MASM MODE
.MODEL SMALL
.386
HISTSIZE EQU 1024 ; MUST be longer than longest command line!!!!
; but shorter than 32K
include eprints.inc
include einput.inc
include emtrap.inc
include ebreaks.inc
include eloader.inc
include edos.inc
include eoptions.inc
include eexec.inc
include ememory.inc
include elogging.inc
PUBLIC CheckHistory, EnterHistory, LoadHistory, histoff,histon
.data
oldhistory db 0 ;to keep track of when history opt changes
db 0 ; safety net for pushing value
histlen dw 0 ;length of history segment
histseg dw 0 ;history segment itself
histpos dw 0 ;position in history segment
nonext db 0 ; flag to not do first find next after new
; command entered
.code
histonm db 13,10,"History enabled",0
histoffm db 13,10,"History disabled",0
histerrm db 13,10,"No mem for history",0
histmsg db " (History access)",0
;
; turn history off temporarily
;
histoff proc
mov ax,word ptr [oldhistory]
xchg ax,[esp]
mov [oldhistory],0
jmp ax
histoff endp
;
; turn history back on
;
histon proc
pop ax
pop word ptr [oldhistory]
jmp ax
histon endp
; log that we are doing a history access
;
CommandToLog PROC
push di ; save hist buffer index
sub si,offset inputbuffer ; get length of input
mov cx,si ; this many backspaces
jcxz nobkspc
clrlp:
mov ah,2 ; we are bypassing the logger
; for this, in a moment we will
; log a message saying we did this
mov dl,8
int 21h ;
mov dl,' '
int 21h ;
mov dl,8
int 21h ;
loop clrlp ;
nobkspc:
mov bx,offset histmsg ; now log a message saying we
cllp: ; did this
mov al,cs:[bx]
or al,al
jz clnd
inc bx
call LogToFile
jmp cllp
clnd:
pop si ; retreive hist buffer index
push si
cllp2:
lods byte ptr es:[si] ; play out the new string
or al,al
jz clnd2
mov dl,al
call PutChar
jmp cllp2
clnd2:
pop di
ret
CommandToLog ENDP
;
; go back one history line
;
findprev proc
mov di,[histpos] ; start here
or di,di ; check if here is beginning
jnz prevnowrap
add di,[histlen] ; yes,start at end
prevnowrap:
dec di ; point back one char
or di,di
jle zerprev ; get out if past zero
test byte ptr es:[di-1],0ffh ; check for null terminator
jnz prevnowrap ; loop if not
mov [histpos],di ; else exit with pointer
ret
zerprev:
sub di,di ; zero pointer
mov [histpos],di
ret
findprev endp
;
; go forward one history line
;
findnext proc
mov di,[histpos] ; start here
test [nonext],1
jnz nofindnext
fnlp:
inc di ; inc di
cmp di,[histlen] ; see if past end
jae zernext ; yes, zero
test byte ptr es:[di-1],0ffh ; no, test for null term
jnz fnlp ; loop until found
mov [histpos],di ; exit with pointer
ret
zernext:
sub di,di ;
mov [histpos],di
ret
nofindnext:
mov [nonext],0
ret
findnext endp
;
; compare two strings
;
compare1 proc
jcxz matches
push cx
push si
push di
repe cmpsb
pop di
pop si
pop cx
ret
matches:
sub ax,ax
ret
compare1 endp
;
; search to see if in history list
;
search1 proc
push es
mov es,[histseg]
sub di,di
mov [histpos],di
lp:
call stringsize
mov cx,ax
dec cx
push si
call compare1
pop si
jz founds
call findnext
or di,di
jnz lp
pop es
stc
ret
founds:
pop es
clc
ret
search1 endp
;
; find the size of a string, including null terminator
;
stringsize proc
push di
push cx
mov cx,-1
sub al,al
repne scasb
not cx
mov ax,cx
pop cx
pop di
ret
stringsize endp
;
; string copy back to main buffer
;
copystring proc
lodsb
or al,al
jz csend
stosb
jmp copystring
csend:
ret
copystring endp
CheckHistory PROC
push di
push si
push es
test [oldhistory],1 ;history on?
jz okcheck
test [histlen],-1 ; anything in history buf?
jz okcheck
mov cx,si ; calculate length of input
sub cx,di
mov si,di
cmp ax,3d00h ; F3 key
jz dof3
cmp ax,5000h ; down arrow
jz up
cmp ax,4800h ; up arrow
clc
jnz okcheck
down:
mov es,[histseg] ; down arr, load stuf
mov di,[histpos]
call findprev ; back one
jmp found
dof3:
mov es,[histseg]
sub di,di ; F3, just go to last item
mov [histpos],di
call findprev
jmp found
up:
mov es,[histseg] ; up arr, load stuff
mov di,[histpos]
call findnext ; forward one
jmp found
found:
call CommandToLog ; output the command
pop es ; found, swap seg regs
push es
push ds
mov ds,[histseg]
mov si,di ; put string in input buffer
mov di,offset inputbuffer
call copystring
pop ds
pop es
pop si
add sp,2
stc
ret
nokcheck:
stc
okcheck:
pop es
pop si
pop di
ret
CheckHistory ENDP
;
; add a new line to the history segment
;
EnterHistory PROC
test [oldhistory],1 ; history on ?
jz noenter
mov cx,di ; yes, any chars besides CR?
sub cx,si
cmp cx,1
jbe noenter ; no, get out
push di ; is in hist list?
push cx
push [histpos]
call search1
pop [histpos]
pop cx
pop di
jnc noenter ; yes, don't put again
push es
push si
mov es,[histseg] ; ES = hist segment
ehsl:
sub di,di ; di = pointer to first string
mov ax,HISTSIZE ; See if enough room for new string
sub ax,[histlen]
sub ax,cx
jnc enoughroom ; yes, go insert new string
push cx ; no, get size of first string
call stringsize
mov cx,HISTSIZE ; count to move = seg size - string size
sub cx,ax
mov si,di
add si,ax ; SI = second string
push ds
mov ds,[histseg]
rep movsb ; cancel out first string
pop ds
sub [histlen],ax
pop cx
jmp ehsl ; loop
enoughroom:
mov di,[histlen] ; add new length to hist seg
pop si
push si
push di
add [histlen],cx
rep movsb ; concat new string
mov byte ptr es:[di-1],0 ; null terminator
pop di
pop si
pop es
mov [histpos],0 ; pos = 0...
noenter:
ret
EnterHistory ENDP
;
; turn history on or off
;
LoadHistory PROC
sub ah,ah
mov al,[opthist] ; see if history flag changed
cmp al,[oldhistory]
jz nochange ; get out if not
call KillFiles ; else clear mem state to allow
call ReleaseMemory ; the change
test [opthist],0ffh ; turning on?
jnz doload ; yes, turn on
push es
mov es,[histseg] ; else unload history seg
mov ah,49h
int 21h
mov [oldhistory],0 ; flag off
pop es
mov bx,offset histoffm ; history off message
jmp reload
doload:
mov bx,HISTSIZE SHR 4 ; load history seg
mov ax,4800h
int 21h
mov bx, offset histerrm
mov [opthist],0 ; assume it didn't succeed
jc reload
mov [oldhistory],1 ; turn on history
mov [opthist],1
mov [histseg],ax ; init the vars
mov [histlen],0
mov [histpos],0
mov [nonext],1
mov bx, offset histonm ; history on message
reload:
call olMessage
mov si,offset grdbname ; reload empty program
call MakeEmptyProg
sub ax,ax
test [loadfile],0ffh
jz nochange
call LoadProgram ; reload user program
lahf
nochange:
ret
LoadHistory ENDP
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?