⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 float.asm

📁 介绍用Java解析网络数据的三种特殊方法
💻 ASM
字号:
          TITLE   CALCULATE EQUATION
          
;     AUTHOR  Yuri Margolin
;             http://mysoft.s5.com/

;     DATE    24/01/01
;     VERSION 1.12

; This program calculates
; linear equation: ax + b = 0
; The result is printed with
; floating point.
; For example: a = 7, b = 2
;              x = -0.28571428....

; Directive to select
; "make EXE" by default when
; source file is compiled:
   #MAKE_EXE#
   
   
DSEG    SEGMENT 'DATA'
CR              EQU     13
LF              EQU     10
NEW_LINE        EQU     13, 10, '$'
MESS0           DB      'Calculation of ax + b = 0', NEW_LINE
MESS1           DB      'ENTER a (-32768..32767)!', NEW_LINE
MESS2           DB      LF, CR, 'ENTER b (-32768..32767)!', NEW_LINE
MESS3           DB      CR, LF, CR, LF, 'Data:', '$'
MESS4           DB      CR, LF, ' a = ', '$'
MESS5           DB      CR, LF, ' b = ', '$'
MESS6           DB      CR, LF, 'Result: ', CR, LF, ' x = ', '$'
MESS7           DB      CR, LF, CR, LF, 'NO SOLUTION!', NEW_LINE
MESS8           DB      CR, LF, CR, LF, 'INFINITE NUMBER OF SOLUTIONS!', NEW_LINE
ERROR           DB      CR, LF, 'THE NUMBER IS OUT OF RANGE!', NEW_LINE
TWICE_NL        DB      NEW_LINE, NEW_LINE 
make_minus      DB      ?       ; used as a flag in procedures.
a               DW      ?
b               DW      ?
ten             DW      10      ; used as multiplier.
four            DW      4       ; used as divider.
DSEG    ENDS

SSEG    SEGMENT STACK   'STACK'
                DW      100h    DUP(?)
SSEG    ENDS

CSEG    SEGMENT 'CODE'

;*******************************************************************

START           PROC    FAR

; Store return address to OS:
                PUSH    DS
                XOR     AX, AX
                PUSH    AX
                
; Set segment registers:                
                MOV     AX, DSEG
                MOV     DS, AX
                MOV     ES, AX

; Welcome message:
                LEA     DX, MESS0
                CALL    PUTS            ; Display the message.

; Ask for 'a' :
                LEA     DX, MESS1
                CALL    PUTS            ; Display the message.
                CALL    SCAN_NUM        ; Input the number into CX.
                MOV     a, CX

; Ask for 'b' :
                LEA     DX, MESS2
                CALL    PUTS            ; Display the message.
                CALL    SCAN_NUM        ; Input the number into CX.
                MOV     b, CX

; Print the data:
                LEA     DX, MESS3
                CALL    PUTS

                LEA     DX, MESS4
                CALL    PUTS
                MOV     AX, a
                CALL    PRINT_NUM               ; print AX.

                LEA     DX, MESS5
                CALL    PUTS
                MOV     AX, b
                CALL    PRINT_NUM               ; print AX.


; Check data:
                CMP     a, 0
                JNE     soluble         ; jumps when a<>0.
                CMP     b, 0
                JNE     no_solution     ; jumps when a=0 AND b<>0.
                JMP     infinite        ; jumps when a=0 AND b=0.
soluble:

; Calculate the solution:
; ax + b = 0  ->  ax = -b  ->  x = -b/a

                NEG     b

                MOV     AX, b

                XOR     DX, DX

                ; check the sign, make DX:AX negative if AX is negative:
                CMP     AX, 0
                JNS     not_singned
                NOT     DX
not_singned:
                MOV     BX, a   ; divider is in BX.

                ; '-b' is in DX:AX.
                ; 'a' is in BX.

                IDIV    BX      ; AX = DX:AX / BX       (DX - remainder).

                ; 'x' is in AX.
                ; remainder is in DX.

                PUSH    DX      ; store the remainder.

                LEA     DX, MESS6
                CALL    PUTS

                POP     DX

                ; print 'x' as float:
                ; AX - whole part
                ; DX - remainder
                ; BX - divider
                CALL    PRINT_FLOAT

                JMP     end_prog
no_solution:
                LEA     DX, MESS7
                CALL    PUTS
                JMP     end_prog
infinite:
                LEA     DX, MESS8
                CALL    PUTS
end_prog:
                LEA     DX, TWICE_NL
                CALL    PUTS
                
                RET
 START          ENDP

;***************************************************************

; Prints number in AX and it's fraction in DX.
; used to print remainder of 'DIV/IDIV BX'.
; AX - whole part.
; DX - remainder.
; BX - the divider that was used to get the remainder from divident.
PRINT_FLOAT     PROC    NEAR
        PUSH    CX
        PUSH    DX

        ; because the remainder takes the sign of divident
        ; its sign should be inverted when divider is negative
        ; (-) / (-) = (+)
        ; (+) / (-) = (-)
        CMP     BX, 0
        JNS     div_not_signed
        NEG     DX              ; make remainder positive.
div_not_signed:

        ; PRINT_NUM procedure does not print the '-'
        ; when the whole part is '0' (even if the remainder is
        ; negative) this code fixes it:
        CMP     AX, 0
        JNE     checked         ; AX<>0
        CMP     DX, 0
        JNS     checked         ; AX=0 and DX>=0
        PUSH    DX
        MOV     DL, '-'
        CALL    WRITE_CHAR      ; print '-'
        POP     DX
checked:

        ; print whole part:
        CALL    PRINT_NUM

        ; if remainder=0, then no need to print it:
        CMP     DX, 0
        JE      done

        PUSH    DX
        ; print dot after the number:
        MOV     DL, '.'
        CALL    WRITE_CHAR
        POP     DX

        ; print digits after the dot:
        MOV     CX, 15  ; max digits after the dot.
        CALL    PRINT_FRACTION
done:
        POP     DX
        POP     CX
        RET
PRINT_FLOAT     ENDP

;***************************************************************

; Prints DX as fraction of division by BX.
; DX - remainder.
; BX - divider.
; CX - maximum number of digits after the dot.
PRINT_FRACTION  PROC    NEAR
        PUSH    AX
        PUSH    DX
next_fraction:
        ; check if all digits are already printed:
        CMP     CX, 0
        JZ      end_rem
        DEC     CX      ; decrease digit counter.

        ; when remainder is '0' no need to continue:
        CMP     DX, 0
        JE      end_rem

        MOV     AX, DX
        XOR     DX, DX
        CMP     AX, 0
        JNS     not_sig1
        NOT     DX
not_sig1:

        IMUL    ten             ; DX:AX = AX * 10

        IDIV    BX              ; AX = DX:AX / BX   (DX - remainder)

        PUSH    DX              ; store remainder.
        MOV     DX, AX
        CMP     DX, 0
        JNS     not_sig2
        NEG     DX
not_sig2:
        ADD     DL, 30h         ; convert to ASCII code.
        CALL    WRITE_CHAR      ; print DL.
        POP     DX

        JMP     next_fraction
end_rem:
        POP     DX
        POP     AX
        RET
PRINT_FRACTION  ENDP

;***************************************************************

; This procedure prints number in AX,
; used with PRINT_NUMX to print "0" and sign.
; this procedure also stores the original AX,
; that is modified by PRINT_NUMX.
PRINT_NUM       PROC    NEAR
        PUSH    DX
        PUSH    AX

        CMP     AX, 0
        JNZ     not_zero

        MOV     DL, '0'
        CALL    WRITE_CHAR
        JMP     printed

not_zero:
        ; the check SIGN of AX,
        ; make absolute if it's negative:
        CMP     AX, 0
        JNS     positive
        NEG     AX

        MOV     DL, '-'
        CALL    WRITE_CHAR
positive:
        CALL    PRINT_NUMX
printed:
        POP     AX
        POP     DX
        RET
PRINT_NUM       ENDP

;***************************************************************

; Prints out a number in AX (not just a single digit)
; allowed values from 1 to 65535 (FFFF)
; (result of /10000 should be the left digit or "0").
; modifies AX (after the procedure AX=0)
PRINT_NUMX      PROC    NEAR
        PUSH    BX
        PUSH    CX
        PUSH    DX

        ; flag to prevent printing zeros before number:
        MOV     CX, 1

        MOV     BX, 10000       ; 2710h - divider.

        ; Check if AX is zero, if zero go to end_show
        CMP     AX, 0
        JZ      end_show

begin_print:

        ; check divider (if zero go to end_show):
        CMP     BX,0
        JZ      end_show

        ; 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:
        XOR     CX, CX  ; set flag.

        XOR     DX, DX
        DIV     BX      ; AX = DX:AX / BX   (DX=remainder).

        ; print last digit
        ; AH is always ZERO, so it's ignored
        PUSH    DX
        MOV     DL, AL
        ADD     DL, 30h    ; convert to ASCII code.
        CALL    WRITE_CHAR
        POP     DX

        MOV     AX, DX  ; get remainder from last div.

skip:
        ; calculate BX=BX/10
        PUSH    AX
        XOR     DX, DX
        MOV     AX, BX
        DIV     ten     ; AX = DX:AX / 10   (DX=remainder).
        MOV     BX, AX
        POP     AX

        JMP     begin_print

end_show:

        POP     DX
        POP     CX
        POP     BX
        RET
PRINT_NUMX      ENDP

;***************************************************************

; Displays the message (DX-address)
PUTS    PROC    NEAR
        PUSH    AX
        MOV     AH, 09h
        INT     21h
        POP     AX
        RET
PUTS    ENDP

;*******************************************************************

; Reads char from the keyboard into AL
; (MODIFIES AX!!!)
READ_CHAR       PROC    NEAR
        MOV     AH, 01h
        INT     21h
        RET
READ_CHAR       ENDP

;***************************************************************

; Gets the multi-digit SIGNED number from the keyboard,
; Result is stored in CX
SCAN_NUM        PROC    NEAR
        PUSH    DX
        PUSH    AX

        XOR     CX, CX

        ; reset flag:
        MOV     make_minus, 0

next_digit:

        CALL    READ_CHAR

        ; check for MINUS:
        CMP     AL, '-'
        JE      set_minus

        ; check for ENTER key:
        CMP     AL, CR
        JE      stop_input

        ; multiply CX by 10 (first time the result is zero)
        PUSH    AX
        MOV     AX, CX
        MUL     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     out_of_range

        ; convert from ASCII code:
        SUB     AL, 30h

        ; add AL to CX:
        XOR     AH, AH
        ADD     CX, AX
        JC      out_of_range    ; jump if the number is too big.

        JMP     next_digit

set_minus:
        MOV     make_minus, 1
        JMP     next_digit

out_of_range:
        LEA     DX, ERROR
        CALL    PUTS

stop_input:
        ; check flag:
        CMP     make_minus, 0
        JE      not_minus
        NEG     CX
not_minus:

        POP     AX
        POP     DX
        RET
SCAN_NUM        ENDP

;***************************************************************

; Prints out single char (ascii code should be in DL)
WRITE_CHAR      PROC    NEAR
        PUSH    AX
        MOV     AH, 02h
        INT     21h
        POP     AX
        RET
WRITE_CHAR      ENDP

;***************************************************************

CSEG    ENDS
        END     START

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -