📄 util.asm
字号:
.model small
.code
.data
extrn DsSave:word
.code
public Blank, ScanP, ScanB, Out16, Hex, HexIn
public GetEol, HexChk, Address, GetHex, GetHex1, Tab
public Backup,PrintMes
extrn OutCh:near, PErr:near, Error:near
BacMes db 8," ",8+80H
;Output one space
BLANK:
MOV AL," "
jmp OutCh
;Output the number of blanks in CX
TAB:
CALL BLANK
LOOP TAB
RET
;Scan for parameters of a command
SCANP:
CALL SCANB ;Get first non-blank
CMP AL,"," ;One comma between params OK
JNE EOLCHK ;If not comma, we found param
INC SI ;Skip over comma
;Scan command line for next non-blank character
SCANB:
LODSB
CMP AL," "
JZ SCANB ;Skip over blanks
cmp al,9
jz ScanB
DEC SI ;Back up to first non-blank
EOLCHK:
CMP AL,13
RET
;Print out 16-bit value in DX in hex
OUT16:
MOV AL,DH ;High-order byte first
CALL HEX
MOV AL,DL ;Then low-order byte
;Output byte in AL as two hex digits
HEX:
MOV AH,AL ;Save for second digit
;Shift high digit into low 4 bits
PUSH CX
MOV CL,4
SHR AL,CL
POP CX
CALL DIGIT ;Output first digit
HIDIG:
MOV AL,AH ;Now do digit saved in AH
DIGIT:
AND AL,0FH ;Mask to 4 bits
;Trick 6-byte hex conversion works on 8086 too.
ADD AL,90H
DAA
ADC AL,40H
DAA
jmp OutCh
;Check if next character in the input buffer is a hex digit
;and convert it to binary if it is. Carry set if not.
HEXIN:
MOV AL,[SI]
;Check if AL has a hex digit and convert it to binary if it
;is. Carry set if not.
HEXCHK:
SUB AL,"0" ;Kill ASCII numeric bias
JC RET2
CMP AL,10
CMC
JNC RET2 ;OK if 0-9
AND AL,5FH ;Convert to upper case
SUB AL,7 ;Kill A-F bias
CMP AL,10
JC RET2
CMP AL,16
CMC
Ret2: RET
;Get an address in Segment:Offset format. Segment may be ommitted
;and a default (kept in BP) will be used, or it may be a segment
;register (DS, ES, SS, CS). Return with segment in AX, Offset in DX.
ADDRESS:
CALL SCANP
CMP byte ptr [SI+1],"S" ;Is second character "S"?
JZ SEGREG
MOV CX,4
CALL GETHEX ;Get number--may be segment or offset
MOV AX,BP ;Get default segment
CMP byte ptr [SI],":" ;Segment specification?
JNZ RET3
PUSH DX ;Save segment while we get offset
GETDISP:
INC SI ;Skip over ":"
MOV CX,4
CALL GETHEX
POP AX ;Bring segment back
Ret3: RET
SEGREG:
LODSB ;First letter of segment register
MOV DI,offset DGroup:SEGLET-1
MOV CX,4
CSSCAN:
INC DI
CMP AL,CS:[DI]
LOOPNZ CSSCAN
JNZ PERR
INC SI ;Skip second letter ("S")
SHL CX,1
MOV BX,CX
CMP byte ptr [SI],":"
JNZ ErrorJ
PUSH [BX+DSSave]
jmp GETDISP
SEGLET DB "CSED"
;Get the next parameter, which must be a hex number.
;CX is maximum number of digits the number may have.
GETHEX:
CALL SCANP ;Scan to next parameter
GETHEX1:
XOR DX,DX ;Initialize the number
MOV AH,DH
CALL HEXIN ;Get a hex digit
JC ErrorJ ;Must be one valid digit
MOV DL,AL ;First 4 bits in position
GETLP:
INC SI ;Next char in buffer
DEC CX ;Digit count
CALL HEXIN ;Get another hex digit?
JC RET2 ;All done if no more digits
JCXZ ErrorJ ;Too many digits?
SHL DX,1 ;Multiply by 16
SHL DX,1
SHL DX,1
SHL DX,1
OR DL,AL ;and combine new digit
jmp GETLP ;Get more digits
ErrorJ: jmp Error
;Make sure there is nothing more on the line except for
;blanks and carriage return. If there is, it is an
;unrecognized parameter and an error.
GETEOL:
PUSH AX
CALL SCANB ;Skip blanks
POP AX
JNZ ErrorJ ;Better be a RETURN
RET
;Physical backspace - blank, backspace, blank
Backup:
mov si,offset DGroup:BacMes
;Print ASCII message. Last char has bit 7 set
PrintMes:
push cs
pop ds
PrintLp:
lodsb ;Get char to print
call OutCh
shl al,1 ;High bit set?
jnc PrintLp
push es
pop ds
ret
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -