SQUAREROOT--A APPROACH BY BINARY SEARCH(2)

1¡£Improved edition.

It improved in several ways.  It expand input limit to up to 65535. It uses a general "divide" function to generalize the call, deleting all those jump for 8bit and 16bit div. A modest improvement after all.

2. Main function

    All other function remains the same as before except some simplicity by using "divide" function call.

    A. divide

    input: by stack dividant, divisor

    output: by stack remainder, quotient

3. Problems & Doubts

    It took me almost half painful day to debug a simple dividing problem: when the divisor is a quite small number, say 2, and it seems the assembler try to use 8bit div instead of 16bit even though the ax is a 16bit number. Because it continually give "divide overflow" error. It bothered me so painfully! And in book it only gives a vaguely explanation that this will trigger a 00h interrupt which is a hardware interrupt, it suggested that some application programmer may want to adapt this kind of error. But why? How can MASM assembler make this kind of mistake?

    Personally I am still not 100% sure about this is the real reason. However, I called ChunMing and he hinted me to use shift to get round of this problem. 

    Another doubt is the previous program size is more than 2k, and now it is less 1k. It seems there is a big difference in assembling the two program.  

¡¡

4. My program

.DOSSEG
.MODEL SMALL
.STACK 200H
.DATA

MSG DB "THIS IS TRUE", "$"
MSG1 DB "THIS IS QUOTIENT", "$"
MSG2 DB "THIS IS REMAINDER", "$"
.CODE
START:

	MOV AX, @DATA
	MOV DS, AX



	CALL INPUTNUMBER

	CALL SQUAREROOT
	CALL CHANGELINE
	CALL DISPLAYNUMBER

	MOV AX, 4C00H
	INT 21H


;PASS DIVIDANT, DIVISOR BY STACK
;GET QUOTIENT FROM STACK
QUOTIENT    PROC
	PUSH BP
	MOV BP, SP
	PUSH AX
	MOV AX, [BP+6]
	PUSH AX
	MOV AX, [BP+4]
	PUSH AX
	CALL DIVIDE
	POP AX; USELESS REMAINDER, ONLY POP
	POP AX; THIS IS QUOTIENT
	MOV [BP+6], AX
	POP AX; THE ORIGINAL AX SAVED
	POP BP
	RET 2
QUOTIENT    ENDP

;PASS DIVIDANT, DIVISOR BY STACK
;GET MODULOS FROM STACK
MODULE	PROC
	PUSH BP
	MOV BP, SP
	PUSH AX
	MOV AX, [BP+6]
	PUSH AX
	MOV AX, [BP+4]
	PUSH AX
	CALL DIVIDE
	POP AX; THIS IS REMAINDER
	MOV [BP+6], AX
	POP AX; USELESS QUOTIENT, BUT HAVE TO POP OUT TO CLEAR STACK
	POP AX; ORIGINAL AX SAVED
	POP BP
	RET 2
MODULE	ENDP



;USE STACK TO PASS DIVIDANT AND DIVISOR
;USE STACK TO RETURN QUOTIENT AND REMAINDER
DIVIDE	PROC
	PUSH BP
	MOV BP, SP
	PUSH AX
	PUSH BX
	PUSH DX

	MOV AX, [BP+6]; THE DIVIDANT
	MOV BX, [BP+4]; THE DIVISOR
	CMP BH, 0; CHECK IF IT IS A 16BIT DIVIDE OR NOT
	JNE SIXTEENDIV
	CMP AH, 0
	JNE SIXTEENDIV
EIGHTDIV:
	DIV BL; 8BIT DIV
	MOV [BP+6], AL; THE QUOTIENT;
	MOV [BP+4], AH; THE REMAINDER
	JMP ENDDIV
SIXTEENDIV:
	DIV BX	 ; 16BIT DIV
	MOV [BP+6], AX; THE QUOTIENT
	MOV [BP+4], DX; THE REMAINDER
ENDDIV:
	POP DX
	POP BX
	POP AX
	POP BP
	RET
DIVIDE ENDP


CHANGELINE   PROC
	PUSH AX
	PUSH DX
	MOV AH, 02
	MOV DL, 0DH
	INT 21H
	MOV DL, 0AH
	INT 21H
	POP DX
	POP AX
	RET
CHANGELINE  ENDP


DISPLAYNUMBER	PROC
	PUSH BX
	PUSH CX
	PUSH DX
	MOV BX, 10
	MOV CX, 0
BEGINDIVIDE:
	CMP AX, 0
	JE SHOWRESULT
	PUSH AX
	PUSH BX
	CALL DIVIDE
	POP DX
	POP AX
	INC CX
	ADD DX, 30H
	PUSH DX
	JMP BEGINDIVIDE

SHOWRESULT:
	CMP CX, 0
	JE  ENDDISPLAY
DISPLAYLOOP:
	MOV AH, 02H
	POP DX
	INT 21H
	LOOP DISPLAYLOOP
ENDDISPLAY:
	POP DX
	POP CX
	POP BX
	RET
DISPLAYNUMBER	ENDP


SQUAREROOT  PROC
	PUSH BX
	PUSH CX
	PUSH DX
	PUSH SI
	PUSH DI
	MOV CX, 00H
	MOV BX, AX; BX SAVE THE NUMBER

	CMP BX, 255; THE BIGGEST ROOT OF 16BIT
	JG  LOCAL1
	MOV DI, BX
	JMP LOCAL2
LOCAL1:
	MOV DI, 255; THIS IS UPPER BOUND OF 16BIT ROOT
LOCAL2:

	MOV SI, 1; LOWBOUND

CHECKRESULT:
	MOV AX, SI
	ADD AX, DI ; AX IS THE SUM OF LOW AND HIGH BOUND
	MOV DX, 02H
	SHR AX, 1
	MOV CX, AX
	MUL AX; AX IS THE SQUARE OF CX
COMPARE:
	CMP AX, BX
	JE  FINDRESULT
	CMP AX, BX
	JB  SMALLER

BIGGERR:
	DEC CX
	CMP CX, SI; COMPARE LOWBOUND
	JL  FINDRESULT; EXCEED LOW BOUND
	MOV DI, CX;NEW HIGH BOUND
	JMP NEXT

SMALLER:
	INC CX
	CMP CX, DI; COMPARE HIGHBOUND
	JG FINDRESULT  ; EXCEED LOW BOUND
	MOV SI, CX; NEW LOW BOUND
	JMP NEXT
NEXT:

	JMP CHECKRESULT
FINDRESULT:
	MOV AX, CX; RESULT IS RETURN IN AX
	POP DI
	POP SI
	POP DX
	POP CX
	POP BX
	RET
SQUAREROOT  ENDP


INPUTNUMBER PROC
	PUSH BX
	PUSH CX
	MOV AX, 00H
	MOV BX, 00H
	MOV CX, 00H

CHECK:
	MOV AH, 01H
	INT 21H
	CMP AL, 0DH
	JE ENDINPUT
	MOV CL, AL; SAVE INPUT IN CX
	MOV AX, 10; PREPARE MUL
	MUL BX	  ; OLD DATA IN BX
	SUB CX, 30H; CX TO BE NUBMERS
	ADD AX, CX
	MOV BX, AX; SAVE DATA IN BX
	JMP CHECK

ENDINPUT:
	MOV AX, BX; RETURN VALUE IN AX
	POP CX
	POP BX
	RET
INPUTNUMBER ENDP

END START
END

¡¡

Click here to download the execute file to have a try. Just run and key in a number smaller than 65535 ended by return and you get the approximate answer or exact answer, depending if the number has an integer root or not. 

                                                        back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)

Hosted by www.Geocities.ws

1