home *** CD-ROM | disk | FTP | other *** search
- ;SQR_T.ASM 10-14-83
- ;
- ;PROGRAM TO TAKE KEYBOARD INPUT AND CALCULATE THE SQUARE
- ;ROOT USING THE SQ ROOT ROUTINE, THEN DISPLAY THE RESULT
- ;
- EXTRN ASCII_BIN:FAR ;EXTERNAL SUBROUTINE
- EXTRN BIN_ASCII:FAR ;EXTERNAL SUBROUTINE
- EXTRN DEC_ADJ:FAR ;EXTERNAL SUBROUTINE
- EXTRN PUT_DEC:FAR
- ;---------------------------------------
- STACK SEGMENT PARA STACK 'STACK'
- DB 256 DUP(0)
- STACK ENDS
- ;----------------------------------------
- DATA SEGMENT PARA 'DATA'
- ESC EQU 27 ;ESC USED TO RETURN TO DOS
- END_SYM EQU '\' ;SYMBOL AT END OF STRING
- SC_TITLE DB 'INTEGER SQUARE ROOT ROUTINE\'
- TYPE_NUM DB 'FOR A POSITIVE NUMBER FROM 0 TO 32767\'
- INPUT_NUM DB 'INPUT TEST NUMBER \'
- COL_HEADER DB 'TEST NUMBER SQ ROOT\'
- UNDERLINE DB '----------- --------\'
- ERR_MSG1 DB 'NOT VALID NUMBER - REDO \'
- ERR_MSG2 DB 'NUMBER TOO LARGE - REDO \'
- ERR_MSG3 DB 'NEGATIVE NUMBER - REDO\'
- BLANKS DB ' \' ;25 BLANKS
- TEST_STRING DB 10 DUP(0)
- TEST_NUMBER DW 0 ;THE TEST_STRING CONVERTED TO A NUMBER
- CHAR_COUNT DW 0 ;NO. OF CHARS IN A STRING - CX IN BIOS CALL
- SQ_ROOT_VALUE DW 0 ;CALUCLATED SQ ROOT VALUE
- SQ_ROOT_STRING DB ' \' ;STRING TO PUT CAL VALUE IN FOR DISP
- OFFSET_VALUE DW 0
- INPUT_LARGE DW 0 ;STATUS PASSING INDICATOR
- INPUT_STATUS DW 0 ;STATUS PASSING INDICATOR
- DEC_POINT DW 0
- test1 db 'test4\'
- test2 db 'test2\'
- test3 db 'test3\'
- TEST_NUM_CNT DB 10 DUP (0) ;STRING TO USE IN FINDING WHERE DECIMAL WAS
- TEST_NUMBER_SIZE DW 0 ;INDICATOR IF TEST_NUMBER <1 OR >1
- data ends
- ;----------------------------------------
- CODE SEGMENT PARA PUBLIC 'CODE'
- START PROC FAR
- ;
- ;STANDARD PROGRAM PROLOGUE
- ;
- ASSUME CS:CODE
-
- PUSH DS
- MOV AX,0
- PUSH AX
- MOV AX,DATA
- MOV DS,AX
- ASSUME DS:DATA
-
- CALL CLEAR_THE_SCREEN
- ;PUT STRING OF SCREEN
-
- ;IF COLOR GRAPHICS MAKE SURE IS MODE 2
- MOV AH,15
- INT 10H
- CMP AL,7 ;IS IT MONOCHROME?
- JE SCREEN_MODE_OK ;YES
- CMP AL,2 ;NOT MONO, IS MODE 2?
- JE SCREEN_MODE_OK ;YES
- MOV AH,0 ;NOT MODE 2 SO MAKE IT
- MOV AL,2 ; MODE 2
- INT 10H
- SCREEN_MODE_OK:
-
- ;SC_TITLE
- MOV AH,2 ;CALL TO SET CURSOR POSITION
- MOV DX,0112H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET SC_TITLE ;PUT SC_TITLE ADDRESS IN BX
- MOV OFFSET_VALUE,BX ;PUT ADDRESS IN VARIABLE
- CALL DISPLAY
-
- ;TYPE_NUM
- MOV AH,2
- MOV DX,0210H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET TYPE_NUM
- MOV OFFSET_VALUE,BX ;PUT ADDRESS IN VARIABLE
- CALL DISPLAY
-
- ;INPUT_NUM
- MOV AH,2
- MOV DX,0310H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET INPUT_NUM
- MOV OFFSET_VALUE,BX
- CALL DISPLAY
-
- ;COL_HEADER
- MOV AH,2 ;CALL TO SET CURSOR POSITION
- MOV DX,0510H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX, OFFSET COL_HEADER
- MOV OFFSET_VALUE,BX ;PUT ADDRESS IN VARIABLE
- CALL DISPLAY
-
- ;UNDERLINE
- MOV AH,2
- MOV DX,0610H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET UNDERLINE
- MOV OFFSET_VALUE,BX
- CALL DISPLAY
-
- ;POSITION CURSOR FOR KEYBOARD INPUT
- INPUT:
- ;CLEAR_INPUT_AREA
- MOV AH,2
- MOV DH,3
- MOV DL,25H
- MOV BH,0
- INT 10H
-
- MOV BH,0
- MOV CX,30 ;blank 30 spaces
- MOV AH,10 ;WRITE CHAR AT CURSOR LOCATION
- MOV AL,' ' ;BLANK
- INT 10H
-
- ;clear test_string
- LEA SI,TEST_STRING
- mov cx,10 ;TEST STRING IS 10 CHAR LONG
- next_char:
- MOV BYTE PTR [SI],' '
- inc SI
- dec cx
- cmp cx,0
- JA next_char
-
- ;SCROLL PART OF SCREEN DOWN TOO BET READY FOR NEXT INPUT
- MOV AH,7 ;SCROLL ACTIVE PAGE DOWN
- MOV AL,1 ;NUMBER OF LINES
- MOV CH,7 ;UPPER LINE TO SCROLL
- MOV CL,0 ;LEFT COLUMN OF SCROLL
- MOV DH,23 ;LOWER LINE OF SCROLL
- MOV DL,79 ;RIGHT COLUMN OF SCROLL
- MOV BH,0FH ;ATTRIBUTE OF BLANK LINE
- INT 10H ;DO IT
-
- MOV INPUT_LARGE,0 ;SET TO ZERO AT START-UNDER 65384
- MOV INPUT_STATUS,0 ;SET TO ZERO AT START-NUMBERS
- MOV AH,2
- MOV DX,0325H ;CURSOR POSITION
- MOV BH,0
- INT 10H
-
- CALL READ_KEYS
-
- ;PUT THE TEST_NUMBER UNDER THE TEST NUMBER COLUMN HEADING
- MOV AH,2
- MOV DX,0711H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET TEST_STRING
- MOV CX,10
- PUT_TEST_NUMBER:
- MOV AL,[BX] ;PUT STRING CHAR IN AX
- MOV AH,14 ;FUNCTION CODE FOR WRITE AND ADVANCE CURSOR
- INT 10H
- INC BX ;NEXT CHARACTER IN STRING
- LOOP PUT_TEST_NUMBER ;PUT ALL OF STRING + BLANKS
-
-
-
- ;PREPAIR TO CALL ASCII_BIN ROUTINE
- ;PUT STARTING ADDRESS OF STRING IN BX
- ;PUT CHARACTER COUNT IN CX
- MOV BX,OFFSET TEST_STRING
- MOV CX,CHAR_COUNT
-
- CALL ASCII_BIN ;CONVERT STRING TO NUMBER
-
-
- JC CARRY_SET ;GO CHECK WHY
- MOV TEST_NUMBER,AX ;SAVE TEST NUMBER
- MOV DEC_POINT,DX ;SAVE DECIMAL POINT
- CMP AX,0 ;CHECK FOR NEGATIVE
- JGE NUM_OK ;NUMBER IS GOOD-GO DO SQ ROOT
- MOV AH,2
- MOV DX,0730H ;CURSOR POSITION
- INT 10H
- MOV BX,OFFSET ERR_MSG3 ;NEGITIVE NUMBER
- MOV OFFSET_VALUE,BX
- CALL DISPLAY
-
- JMP INPUT ;NEXT KEYBOARD INPUT
-
- BAD_CHAR:
- MOV AH,2
- MOV DX,0730H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET ERR_MSG1 ;NOT VALID INPUT
- MOV OFFSET_VALUE,BX
- CALL DISPLAY
-
- JMP INPUT ;GO GET NEXT KEYBOARD INPUT
-
- CARRY_SET:
- cmp di,0ffh ;check for bad character
- jne bad_char
-
- MOV AH,2
- MOV DX,0730H ;CURSOR POSITION
- MOV BH,0
- INT 10H
- MOV BX,OFFSET ERR_MSG2
- MOV OFFSET_VALUE,BX
- CALL DISPLAY
-
- JMP INPUT ;NOT VALID, GO GET NEW INPUT
-
- NUM_OK:
-
- ;ADJUST NUMBER FOR SQUART ROOT ROUTING BY MAKING NUMBER AS LARGE AS
- ;POSSIBLE, BUT LESS THEN 32768, BY MULTIPLYING BY 10 AND CHANGINE
- ;DECIMAL POINT TO MATCH.
- ; CALL DEC_ADJ WITH AX = NUMBER - 16 BIT SIGNED
- ; CX = NUMBER OF CHARACTERS TO RIGHT OF DECIMAL POINT
- ;RETURN WITH AX = NUMBER AND CX = NUMBER OF CHARACTERS TO RIGHT
- ;OF DECIMAL POINT THAT TOGETHER = OLD NUMBER
- ; NOTE CX WILL BE A EVEN NUMBER
-
-
- MOV AX,TEST_NUMBER
- MOV CX,DEC_POINT
- CALL DEC_ADJ
-
- MOV TEST_NUMBER,AX
-
- ;NOW READY TO CALCULATE SQUARE ROOT. AX IS TO CONTAIN THE TEST
- ;NUMBER WHEN THE SQ_ROOT ROUTINE IS CALLED AND AX WILL CONTAIN
- ;THE CALCULATED SQ ROOT ON RET.
-
- MOV AX,CX ;PUT DEC POINT IN AX FOR DIVIDE
- CWD
- MOV BX,2
- DIV BX
- MOV DEC_POINT,AX ;STORE SQ ROOT OF DEC POINT
-
-
-
- MOV AX,TEST_NUMBER ;PUT NUMBER IN AX
- CALL SQ_ROOT
- MOV SQ_ROOT_VALUE,AX ;SAVE THE CALCULATED SQ ROOT VALUE
-
-
- ;CONVERT THE SQ_ROOT VALUE TO ASCII STRING AND PUT UNDER THE
- ;SQ ROOT HEADING
-
- ;CONVERT THE NUMBER TO A ASCII STRING
-
- MOV BX,OFFSET SQ_ROOT_STRING ;PLACE TO PUT RESULT
- CALL BIN_ASCII
-
- ;ON RETURN BX HOLDS ADDRESS OF THE STRING AND CX THE COUNT
-
- ;POSITION DECIMAL POINT IN SQ ROOT STRING
- ; CALL PUT_DEC WITH
- ; AX = 10 SIZE OF STRING
- ; BX = OFFSET OF ASCII STRING
- ; CX = NUMBER OF CHARACTERS IN STRING
- ; DX = NUMBER OF CHARACTERS TO RIGHT OF DECIMAL
- ;RETURN IS WITH DECIMAL IN STRING AT BX
-
- MOV AX,10
- MOV DX,DEC_POINT
- CALL PUT_DEC
-
- ;SQ_ROOT_STRING NOW CONTAINS THE ANSWER READY FOR DISPLAY
-
- MOV AH,2
- MOV DX,0728H ;CURSOR POSITION
- MOV BH,0
- INT 10H
-
- MOV BX,OFFSET SQ_ROOT_STRING
- MOV OFFSET_VALUE,BX
- CALL DISPLAY
-
- JMP INPUT ;READY FOR AN OTHER KEYBOARD INPUT
-
- START ENDP
- ;------------------------------------------
- CLEAR_THE_SCREEN PROC NEAR
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- STI ;ENABLE INTERRUPTS
- MOV AH,0 ;SELECT 80X25, B/W, ALPHANUMERIC
- INT 10H
- MOV AH,6 ;CLEAR THE SCREEN WITH THE SCROLL
- MOV AL,0 ; UP OPTION
- MOV CX,0
- MOV DH,24
- MOV DL,79
- MOV BH,7
- INT 10H
-
- POP DX
- POP CX
- POP BX
- POP AX
- RET ;RETURN TO CALLER
- CLEAR_THE_SCREEN ENDP
- ;------------------------------------------
- DISPLAY PROC NEAR
- ;GET THE CHARACTER COUNT
- MOV CHAR_COUNT,0 ;SET TO 0 FOR THIS STRING
- MOV BX,OFFSET_VALUE ;GET OFFSET OF STRING IN BX
- XOR AX,AX
- LOOP_COUNT:
- MOV AL,[BX] ;PUT STRING CHAR IN AL
- CMP AL,END_SYM ;IS THIS LAST SYMBOL IN STRING?
- JE DISP1
- INC BX ;ADDRESS OF NEXT CHARACTER IN STRING
- ADD CHAR_COUNT,1 ;COUNT OF CHARACTERS IN STRING
- JMP LOOP_COUNT ;DO UNTIL END_SYM ENCOUNTERED
-
- ;PUT THE STRING ON THE SCREEN
- DISP1: MOV BX,OFFSET_VALUE ;GET OFFSET OF STRING IN BX
- MOV CX,CHAR_COUNT ;NO. OF CHARACTERS IN STRING
- DISP2: MOV AL,[BX] ;GET NEXT CHARACTER
- CALL DISPCHAR
- INC BX ;POINT TO NEXT CHARACTER
- LOOP DISP2 ;DO IT CX TIMES
-
- RET
- DISPLAY ENDP
- ;---------------------------------------------------------
- DISPCHAR PROC NEAR
- PUSH BX
- MOV BX,0 ;SELECT DISPLAY PAGE 0
- MOV AH,14 ;FUNCTION CODE FOR 'WRITE'
- INT 10H ;CALL BIOS
- POP BX
- RET
- DISPCHAR ENDP
- ;--------------------------------------------------------
- READ_KEYS PROC NEAR
- PUSH AX
- PUSH DI
- STI ;ENABLE INTERRUPTS
- MOV AH,15 ;READ DISPLAY PAGE NUMBER INTO BX
- INT 10H
- MOV DI,0 ;SET KEY COUNT TO ZERO
- MOV CX,5 ;UP TO 5 KEY STROKES
- GET_KEY:
- MOV AH,0 ;READ NEXT KEY
-
- INT 16H
- CMP AL,ESC ;IS IT ESC?
- JE GO_EXIT ;RETURN TO DOS IN TWO STEPS(JE SHORT-LABEL ONLY)
- CMP AL,0DH ;IS IT A CARRIAGE RETURN?
- JE SAVE_CNT ;IF IT WAS A CARRIAGE RETURN THEN GO TO NEXT STEP
- MOV TEST_STRING[DI],AL ;STORE THE KEY INPUT
- INC DI ;INCREASE THE KEY COUNT
- MOV AH,14 ;DISPLAY THE CHARACTER
- PUSH DI ;SAVE REGISTER
- INT 10H
- POP DI
- LOOP GET_KEY ;GO GET NEXT KEY
- SAVE_CNT:
- MOV CX,DI ;PUT FINAL KEY COUNT IN CX
- MOV CHAR_COUNT,CX ;STORE NO OF CHARS IN STRING
- LEA BX,TEST_STRING ;BUFFER ADDRESS IN BX
- POP DI
- POP AX
- RET ;RETURN TO CALLER
- GO_EXIT:
- POP DI
- POP AX
- POP AX
- JMP EXIT ;RETURN TO DOS
-
- READ_KEYS ENDP
- ;----------------------------------------------------------
- ;-----------------------------------------------------------------
- ;
- ;-------------------------------------------------------------
- ;----------------------------------------------------------------
- ;INTEGER SQUARE ROOT
- ; CALL WITH AX = ARGUMENT
- ; RETURN AX = SQUARE ROOT
- ;
- SQ_ROOT PROC
- SQRT:
- PUSH BX
- PUSH CX
- PUSH DX
- MOV DX,AX ;ARGUMENT INTO DX
- MOV CX,8 ;NUMBER OF ITERATIONS
- XOR BX,BX ;CLEAR THE REMAINDER
- MOV AX,BX ;CLEAR TRIAL VALUE AND FINAL RESULT STORE
-
- SQRT1:
- SHL BX,1 ;DOUBLE PARTIAL RESULT
- INC BX ;GUESS NEXT BIT IS A 1
- SHL DX,1 ;FETCH 2 NEW BITS
- RCL AX,1 ; FROM ARGUMENT
- SHL DX,1
- RCL AX,1
- SUB AX,BX ;DO A TRIAL SUBTRACTION
- JNC SQRT2 ;GUESS WAS RIGHT
- ; APPEND A 1 BIT
- ADD AX,BX ;GUESS WAS WRONG, PUT IT BACK
- DEC BX ;AND CLEAN UP FOR NEXT PASS
- LOOP SQRT1
- JMP SQRT3 ;GO SCALE RESULT
- SQRT2:
- INC BX ;CONVERT xxxx01 to
- ;xxxx10, i.e. append a 1 bit
- loop sqrt1
- SQRT3:
- SAR BX,1 ;DIVIDE BY 2 TO GET
- ;ACTUAL SQUARE ROOT
- MOV AX,BX ;RETURN RESULT IN AX
-
- POP DX
- POP CX
- POP BX
-
- RET ;RETURN TO CALLER
-
- SQ_ROOT ENDP
- ;--------------------------------------------------------------------
- EXIT_TO_DOS PROC FAR
- EXIT: RET ;RETURN TO DOS
- EXIT_TO_DOS ENDP
- ;----------------------------------------------------------
-
- CODE ENDS
- END START