📄 8086.inc
字号:
; Note, that some declarations of "8086.inc"
; are macro procedure declarations, and you
; have to use "DEFINE_..." macro somewhere
; in your program if you want to use
; these functions:
; CALL SCAN_NUM
; CALL PRINT_STRING
; CALL PTHIS
; CALL GET_STRING
; CALL CLEAR_SCREEN
; CALL PRINT_NUM
; CALL PRINT_NUM_UNS
; You can define all these procedures in your
; source code, but compilation time may slow down
; sufficiently because of that, only declare
; functions that you plan to use:
; DEFINE_SCAN_NUM
; DEFINE_PRINT_STRING
; DEFINE_PTHIS
; DEFINE_GET_STRING
; DEFINE_CLEAR_SCREEN
; DEFINE_PRINT_NUM
; DEFINE_PRINT_NUM_UNS
; The above declarations should be made in
; your code once only! Better somewhere
; in the end of your file, but before "END"
; directive. You can also declare them
; in the beginning of the file, but it should
; be after "ORG 100h" directive (for COM files).
; this macro prints a
; char in AL and advances
; the current cursor
; position:
PUTC MACRO char
PUSH AX
MOV AL, char
MOV AH, 0Eh
INT 10h
POP AX
ENDM
; this macro prints a string that is
; given as a parameter, example:
; PRINT 'hello world!'
; (new line is NOT added).
PRINT MACRO sdat
LOCAL next_char, s_dcl, printed, skip_dcl
PUSH AX ; store registers...
PUSH SI ;
JMP skip_dcl ; skip declaration.
s_dcl DB sdat, 0
skip_dcl:
LEA SI, s_dcl
next_char:
MOV AL, CS:[SI]
CMP AL, 0
JZ printed
INC SI
MOV AH, 0Eh ; teletype function.
INT 10h
JMP next_char
printed:
POP SI ; re-store registers...
POP AX ;
ENDM
; this macro prints a string that is
; given as a parameter, example:
; PRINTN 'hello world!'
; (the same as PRINT, but
; new line is automatically added).
PRINTN MACRO sdat
LOCAL next_char, s_dcl, printed, skip_dcl
PUSH AX ; store registers...
PUSH SI ;
JMP skip_dcl ; skip declaration.
s_dcl DB sdat, 13, 10, 0
skip_dcl:
LEA SI, s_dcl
next_char:
MOV AL, CS:[SI]
CMP AL, 0
JZ printed
INC SI
MOV AH, 0Eh ; teletype function.
INT 10h
JMP next_char
printed:
POP SI ; re-store registers...
POP AX ;
ENDM
; turns off the cursor:
CURSOROFF MACRO
PUSH AX
PUSH CX
MOV AH, 1
MOV CH, 28h
MOV CL, 09h
INT 10h
POP CX
POP AX
ENDM
; turns on the cursor:
CURSORON MACRO
PUSH AX
PUSH CX
MOV AH, 1
MOV CH, 08h
MOV CL, 09h
INT 10h
POP CX
POP AX
ENDM
; sets current cursor
; position:
GOTOXY MACRO col, row
PUSH AX
PUSH BX
PUSH DX
MOV AH, 02h
MOV DH, row
MOV DL, col
MOV BH, 0
INT 10h
POP DX
POP BX
POP AX
ENDM
;***************************************************************
; This macro defines a procedure that
; gets the multi-digit SIGNED number from the keyboard,
; and stores the result in CX register:
DEFINE_SCAN_NUM MACRO
LOCAL make_minus, ten, next_digit, set_minus
LOCAL too_big, backspace_checked, too_big2
LOCAL stop_input, not_minus, skip_proc_scan_num
LOCAL remove_not_digit, ok_AE_0, ok_digit, not_cr
; protect from wrong definition location:
JMP skip_proc_scan_num
SCAN_NUM PROC NEAR
PUSH DX
PUSH AX
PUSH SI
MOV CX, 0
; reset flag:
MOV CS:make_minus, 0
next_digit:
; get char from keyboard
; into AL:
MOV AH, 00h
INT 16h
; and print it:
MOV AH, 0Eh
INT 10h
; check for MINUS:
CMP AL, '-'
JE set_minus
; check for ENTER key:
CMP AL, 13 ; carriage return?
JNE not_cr
JMP stop_input
not_cr:
CMP AL, 8 ; 'BACKSPACE' pressed?
JNE backspace_checked
MOV DX, 0 ; remove last digit by
MOV AX, CX ; division:
DIV CS:ten ; AX = DX:AX / 10 (DX-rem).
MOV CX, AX
PUTC ' ' ; clear position.
PUTC 8 ; backspace again.
JMP next_digit
backspace_checked:
; allow only digits:
CMP AL, '0'
JAE ok_AE_0
JMP remove_not_digit
ok_AE_0:
CMP AL, '9'
JBE ok_digit
remove_not_digit:
PUTC 8 ; backspace.
PUTC ' ' ; clear last entered not digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for next input.
ok_digit:
; multiply CX by 10 (first time the result is zero)
PUSH AX
MOV AX, CX
MUL CS:ten ; DX:AX = AX*10
MOV CX, AX
POP AX
; check if the number is too big
; (result should be 16 bits)
CMP DX, 0
JNE too_big
; convert from ASCII code:
SUB AL, 30h
; add AL to CX:
MOV AH, 0
MOV DX, CX ; backup, in case the result will be too big.
ADD CX, AX
JC too_big2 ; jump if the number is too big.
JMP next_digit
set_minus:
MOV CS:make_minus, 1
JMP next_digit
too_big2:
MOV CX, DX ; restore the backuped value before add.
MOV DX, 0 ; DX was zero before backup!
too_big:
MOV AX, CX
DIV CS:ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10
MOV CX, AX
PUTC 8 ; backspace.
PUTC ' ' ; clear last entered digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for Enter/Backspace.
stop_input:
; check flag:
CMP CS:make_minus, 0
JE not_minus
NEG CX
not_minus:
POP SI
POP AX
POP DX
RET
make_minus DB ? ; used as a flag.
ten DW 10 ; used as multiplier.
SCAN_NUM ENDP
skip_proc_scan_num:
DEFINE_SCAN_NUM ENDM
;***************************************************************
;***************************************************************
; this macro defines a procedure to print a null terminated
; string at current cursor position,
; receives address of string in DS:SI
; register:
DEFINE_PRINT_STRING MACRO
LOCAL next_char, printed, skip_proc_print_string
; protect from wrong definition location:
JMP skip_proc_print_string
PRINT_STRING PROC NEAR
PUSH AX ; store registers...
PUSH SI ;
next_char:
MOV AL, [SI]
CMP AL, 0
JZ printed
INC SI
MOV AH, 0Eh ; teletype function.
INT 10h
JMP next_char
printed:
POP SI ; re-store registers...
POP AX ;
RET
PRINT_STRING ENDP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -