Скачиваний:
25
Добавлен:
02.05.2014
Размер:
36.66 Кб
Скачать

Assembler Source Code: emu8086.inc a:link {text-decoration: none} a:visited {text-decoration: none} a:hover {text-decoration: none; color:#ff0000}     ; emu8086.inc ; emu8086.inc - macro definitions library for easy input/output ; Note, that some declarations of "emu8086.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, ; or inside the code segment for EXE 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 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 ; 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. ;============================ ; 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 ;***************************************************************

; - Other Assembler Source Codes -

; - asm2html by emu8086 -

Соседние файлы в папке asm_files