📄 atoms.asm
字号:
.ENDIF
les di, [lpHeader] ; re-load the request header
ASSUME di:PTR REQ_HEADER ; to use the REQ_HEADER offsets
mov es:[di].xcount, bx ; store the number of chars transferred
ASSUME di:NOTHING ; di will be something else now
mov pAtomVal, offset null ; set pAtomVal to null:won't read twice
xor ax, ax ; set status to OK
ret ; return
Read ENDP
;----------------------------------------------------------------------------;
; output (write) status: if there's still memory, fine. Otherwise, error
;----------------------------------------------------------------------------;
OutStat PROC NEAR
mov ax, MemEnd ; mov MemEnd into ax
inc ax ; increment ax (test space for 1 more char)
.IF (ax < MaxMem) ; if MemEnd less than MaxMem, we have space,
xor ax, ax ; set status to OK
.ELSE ; otherwise, set the Write Fault error
mov ax, fERROR + fWRITE_E
.ENDIF
ret
OutStat ENDP
;----------------------------------------------------------------------------;
; function 8 = write (output) to device from program
;----------------------------------------------------------------------------;
; big chunk of the program.
; if string: 'variable', it's a search
; if string: 'variable=' it's a delete
; if string: 'variable=value' it's an insert
;----------------------------------------------------------------------------;
Write PROC NEAR USES si es di cx ds
LOCAL func:BYTE, count:WORD, pAtom:NPTR, buf_seg:SEGPTR, buf_off:NPTR
; func is used to see what function we're doing
; count is used to store the length of the current atom
; pAtom is used to point to the start of the current atom
; buf_seg and buf_off point to the buffer to read from
ASSUME di:PTR REQ_HEADER ; to use the REQ_HEADER offsets
mov ax, es:[di].xseg ; load buf_seg with the buffer segment
mov buf_seg, ax
mov cx, es:[di].xfer ; load buf_off with the buffer offset
mov buf_off, cx
ASSUME di:NOTHING ; di will be something else now
mov es, ax ; load string into ES:DI
mov di, cx
INVOKE st_len, di, es ; load string length into ax, since
; we're not interested in xcount (for
; safety reasons)
mov count, ax ; Store length in count
mov cx, ax ; and copy to cx
; find if we're doing a search, delete or insert
mov bx, cx ; store the count temporarily
mov al, '=' ; we will look in the string for a '='
repnz scasb ; do the scanning
.IF (ZERO?) ; zero will be set if we found a '=',
xor al, al ; in which case we have to see if it's a delete
scasb ; or insert: in a delete, the char after the
; '=' has to be a 0
.IF (ZERO?) ; if there was a 0 after the =,
mov func,fDELETE ; set the function to delete
.ELSE
mov func,fINSERT ; else, the function is insert
.ENDIF
.ELSE
mov func, fSEARCH ; else (no '=' in string) it's a search
.ENDIF
inc cx ; cx holds amount of bytes after the '=', so
sub bx, cx ; by increasing it, cx holds # of bytes after
; the variable name. If we substract cx from
; the original length (in bx), bx will have
; the length of the variable only
.IF (bx == 0) ; if the length of the variable is 0 (i.e.
xor ax, ax ; string= "=....", then finish. set ax to OK
jmp wri_e ; jump to the return place
.ENDIF
mov pAtomVal, offset null ; set pAtomVal to null. only a search
; will change this value, taken care
; of in the loops below
; now go into the memory space and search for a matching variable. we will stop
; if we find a match or a variable that starts with a 0 (meaning no matches)
mov si, offset AtomList ; load SI the start of the driver memory
; (pointed to by AtomList, of course)
.WHILE 1
mov pAtom, si ; save the start of the current atom in memory
INVOKE st_len, si, ds ; length of current atom will be in ax
.IF (ax <= 1) ; if the length of the current atom is 1 (never
mov di, si ; can be 0), that means that we reached the end
mov si, ds ; of the driver memory. set ES:DI to DS:SI, the
mov es, si ; end of memory,
.BREAK ; and break from the loop
.ENDIF
mov di, buf_off ; restore di to the buffer offset
mov cx, bx ; load into the count reg. the variable length
.IF (cx >= ax) ; if the length of the var.name is greater than
add si, ax ; the whole atom length, it's sure not to be a
.CONTINUE ; match. increase si by the length of the
.ENDIF ; current atom, and continue to next iteration
repe cmpsb ; find the first non-matching character between
; the current atom and the string buffer, for
; a maximum count of the length of the name
.IF (!ZERO? || (byte ptr [si]!='='))
mov si,pAtom; if we didn't stop because of two chars not
add si,ax ; matching in the repe, or if the next char
.CONTINUE ; is not a '=' (i.e. comspec would match com),
.ENDIF ; increase si by the length of the atom, and
; go to the next iteration
; at this point we have found a match for the requested variable
.IF (func==fSEARCH) ; if we're doing a search,
inc si ; increment si (to skip over the '=')
mov pAtomVal,si ; set pAtomVal to address of the char
.ELSE ; else, we're doing a delete or insert: we have
; to take the current atom out of the memory.
; we will scan for the chars beyond our current
; atom. then we shift those chars to a position
; 'ax' places back. ax still holds the length
; of the current atom
mov si,pAtom; set si to the beginning of the current atom,
mov di, ds ; set ES:DI to be the same as DS:SI, since
mov es, di ; scan uses ES:DI
mov di, si
add di, ax ; set DI to point to the char just after the
mov bx, ax ; current atom. save atom length in bx.
xor al, al ; clear al (will be used in the scan)
mov cx, -1 ; cx=-1 so that the reps only stop with a match
.WHILE 1 ; a loop:
dec cx ; decrease cx (because scasb doesn't)
scasb ; and test if it's a 0 (to signal end)
.BREAK .IF ZERO?; break if the character matches
repne scasb ; else repeat scanning (decrements cx)
.ENDW ; until the next 0. then continue loop.
not cx ; if cx=-(length+1), not cx=length (see st_len)
mov si,pAtom; get back to the beginning of the atom to
mov di, si ; erase. the source for the movsb will be ahead
add si, bx ; by bx chars (the atom length).
rep movsb ; move as many chars as left in memory
dec di ; for the insert following, we'll want di to
; point to the end of memory. the rep took us
; one beyond, so we decrement it.
sub MemEnd,bx ; De-allocate the memory used by atom
.ENDIF ; of (func == fSEARCH)
.BREAK ; break from the loop: one match is all we need
.ENDW ; actually, no one gets here. they either do a
; continue or a break.
; if we're doing an insert, we'll do it at the end of the memory space
.IF (func == fINSERT)
mov ds, buf_seg ; load DS:SI with the buffer to read from
mov si, buf_off
mov cx, count ; cx and bx will have the count
mov bx, cx
add bx, cs:MemEnd ; add to bx the end of memory
; if we have a carry, it means that if bx > MaxMem, we don't have space
; in our local AtomList. The bx>MaxMem test is not enough because if
; MemEnd is high and adding cx goes over the segment boundary (starting
; at 0000h), we wouldn't catch it with a bx >= MaxMem
.IF (CARRY? || bx >= cs:MaxMem)
mov ax, fERROR + fWRITE_E ; set write fault error
jmp wri_e
.ELSE
mov cs:MemEnd , bx ; set new memory size
.ENDIF
rep movsb ; copy the buffer into our memory
xor ax, ax ; add a null byte to the end of strings,
stosb ; to signal the end of memory
.ENDIF
xor ax, ax ; set status to OK
wri_e: ret ; return!
Write ENDP
;----------------------------------------------------------------------------;
; Success: When the only thing the program needs to do is set status to OK
;----------------------------------------------------------------------------;
Success PROC NEAR
xor ax, ax ; set status to OK
ret
Success ENDP
;----------------------------------------------------------------------------;
; error: set the status word to error: unknown command
;----------------------------------------------------------------------------;
Error PROC NEAR
mov ax, fERROR + fUNKNOWN_E ; error bit + "Unknown command" code
ret
Error ENDP
;----------------------------------------------------------------------------;
; st_len
; finds the length of the string pointed to by st_off and st_seg and stores it
; in ax. no other registers are affected
;----------------------------------------------------------------------------;
st_len PROC NEAR USES es di cx, st_off:NPBYTE, st_seg:SEGPTR
mov di, st_off ; load string into ES:DI, since scas uses
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -