home *** CD-ROM | disk | FTP | other *** search
- ; Copyright (C) 2002 emu8086, Inc.
- ; http://www.emu8086.com
- ; info@emu8086.com
- ; All rights reserved.
-
-
- ; 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
-
- skip_proc_print_string:
-
- DEFINE_PRINT_STRING ENDM
- ;***************************************************************
-
-
- ;***************************************************************
- ; This macro defines a procedure to print a null terminated
- ; string at current cursor position.
- ; The ZERO TERMINATED string should be defined just after
- ; the CALL. For example:
- ;
- ; CALL PTHIS
- ; db 'Hello World!', 0
- ;
- ; Address of string is stored in the Stack as return address.
- ; Procedure updates value in the Stack to make return
- ; after string definition.
- DEFINE_PTHIS MACRO
- LOCAL next_char, printed, skip_proc_pthis, temp1
-
- ; protect from wrong definition location:
- JMP skip_proc_pthis
-
- PTHIS PROC NEAR
-
- MOV CS:temp1, SI ; re-store SI register.
-
- POP SI ; get return address (IP).
-
- PUSH AX ; store AX register.
-
- next_char:
- MOV AL, CS:[SI]
- INC SI ; next byte.
- CMP AL, 0
- JZ printed
- MOV AH, 0Eh ; teletype function.
- INT 10h
- JMP next_char ; loop.
- printed:
-
- POP AX ; re-store AX register.
-
- ; SI should point to next command after
- ; the CALL instruction and string definition:
- PUSH SI ; save new return address into the Stack.
-
- MOV SI, CS:temp1 ; re-store SI register.
-
- RET
- temp1 DW ? ; variable to store original value of SI register.
- PTHIS ENDP
-
- skip_proc_pthis:
-
- DEFINE_PTHIS ENDM
- ;***************************************************************
-
-
- ;***************************************************************
- ; This macro defines a procedure to get a null terminated
- ; string from user, the received string is written to buffer
- ; at DS:DI, buffer size should be in DX.
- ; Procedure stops the input when 'Enter' is pressed.
- DEFINE_GET_STRING MACRO
- LOCAL empty_buffer, wait_for_key, skip_proc_get_string
- LOCAL exit, add_to_buffer
-
- ; protect from wrong definition location:
- JMP skip_proc_get_string
-
- GET_STRING PROC NEAR
- PUSH AX
- PUSH CX
- PUSH DI
- PUSH DX
-
- MOV CX, 0 ; char counter.
-
- CMP DX, 1 ; buffer too small?
- JBE empty_buffer ;
-
- DEC DX ; reserve space for last zero.
-
-
- ;============================
- ; Eternal loop to get
- ; and processes key presses:
-
- wait_for_key:
-
- MOV AH, 0 ; get pressed key.
- INT 16h
-
- CMP AL, 13 ; 'RETURN' pressed?
- JZ exit
-
-
- CMP AL, 8 ; 'BACKSPACE' pressed?
- JNE add_to_buffer
- JCXZ wait_for_key ; nothing to remove!
- DEC CX
- DEC DI
- PUTC 8 ; backspace.
- PUTC ' ' ; clear position.
- PUTC 8 ; backspace again.
- JMP wait_for_key
-
- add_to_buffer:
-
- CMP CX, DX ; buffer is full?
- JAE wait_for_key ; if so wait for 'BACKSPACE' or 'RETURN'...
-
- MOV [DI], AL
- INC DI
- INC CX
-
- ; print the key:
- MOV AH, 0Eh
- INT 10h
-
- JMP wait_for_key
- ;============================
-
- exit:
-
- ; terminate by null:
- MOV [DI], 0
-
- empty_buffer:
-
- POP DX
- POP DI
- POP CX
- POP AX
- RET
- GET_STRING ENDP
-
-
- skip_proc_get_string:
-
- DEFINE_GET_STRING ENDM
- ;***************************************************************
-
- ;***************************************************************
- ; this macro defines procedure to clear the screen,
- ; (done by scrolling entire screen window),
- ; and set cursor position to top of it:
- DEFINE_CLEAR_SCREEN MACRO
- LOCAL skip_proc_clear_screen
-
- ; protect from wrong definition location:
- JMP skip_proc_clear_screen
-
- CLEAR_SCREEN PROC NEAR
- PUSH AX ; store registers...
- PUSH DS ;
- PUSH BX ;
- PUSH CX ;
- PUSH DI ;
-
- MOV AX, 40h
- MOV DS, AX ; for getting screen parameters.
- MOV AH, 06h ; scroll up function id.
- MOV AL, 0 ; scroll all lines!
- MOV BH, 07 ; attribute for new lines.
- MOV CH, 0 ; upper row.
- MOV CL, 0 ; upper col.
- MOV DI, 84h ; rows on screen -1,
- MOV DH, [DI] ; lower row (byte).
- MOV DI, 4Ah ; columns on screen,
- MOV DL, [DI]
- DEC DL ; lower col.
- INT 10h
-
- ; set cursor position to top
- ; of the screen:
- MOV BH, 0 ; current page.
- MOV DL, 0 ; col.
- MOV DH, 0 ; row.
- MOV AH, 02
- INT 10h
-
- POP DI ; re-store registers...
- POP CX ;
- POP BX ;
- POP DS ;
- POP AX ;
-
- RET
- CLEAR_SCREEN ENDP
-
- skip_proc_clear_screen:
-
- DEFINE_CLEAR_SCREEN ENDM
- ;***************************************************************
-
-
- ;***************************************************************
-
- ; This macro defines a procedure that prints number in AX,
- ; used with PRINT_NUM_UNS to print signed numbers:
- ; Requires DEFINE_PRINT_NUM_UNS !!!
- DEFINE_PRINT_NUM MACRO
- LOCAL not_zero, positive, printed, skip_proc_print_num
-
- ; protect from wrong definition location:
- JMP skip_proc_print_num
-
- PRINT_NUM PROC NEAR
- PUSH DX
- PUSH AX
-
- CMP AX, 0
- JNZ not_zero
-
- PUTC '0'
- JMP printed
-
- not_zero:
- ; the check SIGN of AX,
- ; make absolute if it's negative:
- CMP AX, 0
- JNS positive
- NEG AX
-
- PUTC '-'
-
- positive:
- CALL PRINT_NUM_UNS
- printed:
- POP AX
- POP DX
- RET
- PRINT_NUM ENDP
-
- skip_proc_print_num:
-
- DEFINE_PRINT_NUM ENDM
-
- ;***************************************************************
-
- ; This macro defines a procedure that prints out an unsigned
- ; number in AX (not just a single digit)
- ; allowed values from 0 to 65535 (0FFFFh)
- DEFINE_PRINT_NUM_UNS MACRO
- LOCAL begin_print, calc, skip, print_zero, end_print, ten
- LOCAL skip_proc_print_num_uns
-
- ; protect from wrong definition location:
- JMP skip_proc_print_num_uns
-
- PRINT_NUM_UNS PROC NEAR
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- ; flag to prevent printing zeros before number:
- MOV CX, 1
-
- ; (result of "/ 10000" is always less or equal to 9).
- MOV BX, 10000 ; 2710h - divider.
-
- ; AX is zero?
- CMP AX, 0
- JZ print_zero
-
- begin_print:
-
- ; check divider (if zero go to end_print):
- CMP BX,0
- JZ end_print
-
- ; avoid printing zeros before number:
- CMP CX, 0
- JE calc
- ; if AX<BX then result of DIV will be zero:
- CMP AX, BX
- JB skip
- calc:
- MOV CX, 0 ; set flag.
-
- MOV DX, 0
- DIV BX ; AX = DX:AX / BX (DX=remainder).
-
- ; print last digit
- ; AH is always ZERO, so it's ignored
- ADD AL, 30h ; convert to ASCII code.
- PUTC AL
-
-
- MOV AX, DX ; get remainder from last div.
-
- skip:
- ; calculate BX=BX/10
- PUSH AX
- MOV DX, 0
- MOV AX, BX
- DIV CS:ten ; AX = DX:AX / 10 (DX=remainder).
- MOV BX, AX
- POP AX
-
- JMP begin_print
-
- print_zero:
- PUTC '0'
-
- end_print:
-
- POP DX
- POP CX
- POP BX
- POP AX
- RET
- ten DW 10 ; used as divider.
- PRINT_NUM_UNS ENDP
-
- skip_proc_print_num_uns:
-
- DEFINE_PRINT_NUM_UNS ENDM
- ;***************************************************************
-