Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- DATA SEGMENT
- messtr DB 0Dh, 0Ah, "Hello! Let`s solve piecewise function with your values", 0Dh, 0Ah, "$"
- funct DB " { x-1, if x < 10", 0Dh, 0Ah, "Z= { (3x^2+4)/(x-2), if x = 10", 0Dh, 0Ah, " { (7x^2-56)/(2x-5), if x > 10", 0Dh, 0Ah, "$"
- xreadmes DB "Input value of x (in range -32767...32767) -> $"
- xinmes DB 7,?, 7 DUP (" ")
- menuhold DB 2,?, 2 DUP (" ")
- xvalue DW ?
- outmes DB "Result: $"
- newline DB 0Dh,0Ah,"$"
- errmsg DB 0Dh, 0Ah, "Invalid input!", 0Dh, 0Ah, "$"
- range_err DB "Number out of range!", 0Dh, 0Ah, "$"
- overflow_err DB "Calculation overflow occurred!", 0Dh, 0Ah, "$"
- ostacha_msg DB " reminder $"
- end_msg DB "Do you want to continue? (y/n): $"
- result DW ?
- remainder DW ?
- numerator DW ?
- denominator DW ?
- sign_flag DB 0
- temp_reg DW ? ; Added temporary register to handle larger calculations
- DATA ENDS
- STSEG SEGMENT PARA STACK "STACK"
- DB 64 DUP ( "STACK" )
- STSEG ENDS
- CODE SEGMENT
- ASSUME CS:CODE, DS:DATA, SS:STSEG
- START:
- MOV AX, DATA
- MOV DS, AX
- CALL WELC_PROC
- CALL FUNC
- CALL PRINTING
- CALL END_PROGRAM
- MOV AH, 10
- INT 21h
- WELC_PROC PROC
- MOV DX, OFFSET messtr
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET funct
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET xreadmes
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET xinmes
- MOV AH, 10
- INT 21h
- CALL CHECK_INPUT
- MOV SI, OFFSET xinmes
- ADD SI, 2
- CALL CONVERT
- MOV xvalue, BX
- MOV sign_flag, 0
- RET
- WELC_PROC ENDP
- CHECK_INPUT PROC
- MOV SI, DX
- MOV CL, [SI+1]
- MOV BL, 0
- ADD SI, 2
- MOV AL, [SI]
- CMP AL, '-'
- JNE CHECK_DIGITS
- MOV sign_flag, 1
- INC SI
- DEC CX
- JZ INVALID_INPUT
- CHECK_DIGITS:
- MOV AL, [SI]
- CMP CX, 0
- JZ END_CHECK
- CHECK_LOOP:
- MOV AL, [SI]
- CMP AL, '0'
- JB INVALID_INPUT
- CMP AL, '9'
- JA INVALID_INPUT
- INC BL
- INC SI
- DEC CX
- JNZ CHECK_LOOP
- CMP BL, 0
- JZ INVALID_INPUT
- JMP END_CHECK
- INVALID_INPUT:
- MOV DX, OFFSET errmsg
- MOV AH, 9
- INT 21h
- JMP END_ERROR
- END_ERROR:
- JMP START
- END_CHECK:
- RET
- CHECK_INPUT ENDP
- CHECK_RANGE PROC
- CMP sign_flag, 0
- JE CHECK_NEGATIVE
- NEG AX
- CMP remainder, 0
- JNE CHECK_NEGATIVE
- CMP DX, 0
- JNE RANGE_ERROR
- CHECK_NEGATIVE:
- CMP AX, 32767
- JA RANGE_ERROR
- CMP sign_flag, 0
- JNE NEG_N
- RET
- RANGE_ERROR:
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET range_err
- MOV AH, 9
- INT 21h
- CALL END_PROGRAM
- NEG_N:
- NEG AX
- RET
- CHECK_RANGE ENDP
- CHECK_RANGE_RESULT PROC
- MOV AX, result
- CMP AX, -32768
- JA RANGE_ERROR_RES
- CMP AX, 32752
- JG RANGE_ERROR_RES
- RET
- RANGE_ERROR_RES:
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET range_err
- MOV AH, 9
- INT 21h
- JMP START
- CHECK_RANGE_RESULT ENDP
- CONVERT PROC
- XOR AX, AX
- XOR BX, BX
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- MOV BX, 0
- CMP sign_flag, 1
- JNE CONVERT_LOOP
- INC SI
- DEC CX
- CONVERT_LOOP:
- MOV AL, [SI]
- CMP AL, '0'
- JB CONVERT_END
- CMP AL, '9'
- JA CONVERT_END
- SUB AL, '0'
- MOV AH, 0
- PUSH AX
- MOV AX, BX
- MOV CX, 10
- MUL CX
- CMP DX, 0
- JNE OVERFLOW_ERROR
- MOV BX, AX
- POP AX
- ADD BX, AX
- INC SI
- JMP CONVERT_LOOP
- OVERFLOW_ERROR:
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET range_err
- MOV AH, 9
- INT 21h
- JMP START
- CONVERT_END:
- CMP sign_flag, 1
- JNE CONVERT_FINISH
- NEG BX
- CONVERT_FINISH:
- MOV AX, BX
- CALL CHECK_RANGE
- POP DX
- POP CX
- POP BX
- MOV BX, AX
- POP AX
- RET
- CONVERT ENDP
- RET_PROC PROC
- CALL START
- RET_PROC ENDP
- FUNC PROC
- XOR AX, AX
- MOV AX, xvalue
- ; Compare x with 10
- CMP AX, 10
- JL CASE_LESS_THAN_10 ; If x < 10
- JE CASE_EQUAL_10 ; If x = 10
- JG CASE_GREATER_THAN_10 ; If x > 10
- CASE_LESS_THAN_10:
- ; Calculate Z = x - 1
- MOV AX, xvalue
- SUB AX, 1
- MOV result, AX
- MOV remainder, 0
- JMP END_FUNC
- CASE_EQUAL_10:
- ; Calculate Z = (3x^2 + 4) / (x - 2)
- ; First calculate x^2
- MOV AX, xvalue
- IMUL xvalue ; DX:AX = x^2
- ; Calculate 3x^2
- MOV BX, 3
- IMUL BX ; DX:AX = 3x^2
- ; Add 4: AX = 3x^2 + 4
- ADD AX, 4
- MOV numerator, AX
- ; Calculate denominator: (x-2)
- MOV BX, xvalue
- SUB BX, 2
- MOV denominator, BX
- ; Perform division
- MOV AX, numerator
- CWD ; Convert word to double word for division
- IDIV denominator
- MOV result, AX
- MOV remainder, DX
- JMP END_FUNC
- CASE_GREATER_THAN_10:
- ; Calculate Z = (7x^2 - 56) / (2x - 5)
- MOV AX, xvalue
- MOV temp_reg, AX ; Store x in temp_reg
- ; Calculate x^2 carefully using a loop for large values
- MOV AX, xvalue
- IMUL xvalue ; DX:AX = x^2
- ; If overflow occurred, use manual multiplication
- CMP DX, 0
- JNE CALC_OVERFLOW
- ; Calculate 7x^2
- MOV BX, 7
- MUL BX ; DX:AX = 7x^2
- ; Check for overflow
- CMP DX, 0
- JNE CALC_OVERFLOW
- ; Subtract 56: AX = 7x^2 - 56
- SUB AX, 56
- MOV numerator, AX
- ; Calculate denominator: (2x-5)
- MOV AX, temp_reg ; Retrieve x from temp_reg
- MOV BX, 2
- IMUL BX ; AX = 2x
- SUB AX, 5 ; AX = 2x - 5
- MOV denominator, AX
- ; Check if denominator is 0
- CMP AX, 0
- JE RANGE_ERROR_FUNC
- ; Perform division - ensure signs are handled correctly
- MOV AX, numerator
- MOV BX, denominator
- ; Check if numerator is negative
- CMP AX, 0
- JGE CHECK_DENOM_SIGN
- ; Numerator is negative
- NEG AX
- XOR SI, SI ; SI=0 means positive result initially
- INC SI ; SI=1 means need to negate result
- JMP PERFORM_DIV
- CHECK_DENOM_SIGN:
- XOR SI, SI ; SI=0 means positive result
- ; Check if denominator is negative
- CMP BX, 0
- JGE PERFORM_DIV
- ; Denominator is negative
- NEG BX
- INC SI ; Toggle result sign
- PERFORM_DIV:
- MOV numerator, AX ; Update with absolute values
- MOV denominator, BX
- ; Perform division with absolute values
- CWD ; Convert word to double word for division
- IDIV BX
- MOV result, AX
- MOV remainder, DX
- ; Apply sign if needed
- CMP SI, 0
- JE END_FUNC
- NEG result ; Negate result if signs were different
- NEG remainder ; Negate remainder too when result is negative
- JMP END_FUNC
- CALC_OVERFLOW:
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET overflow_err
- MOV AH, 9
- INT 21h
- JMP START
- END_FUNC:
- RET
- RANGE_ERROR_FUNC:
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET range_err
- MOV AH, 9
- INT 21h
- JMP START
- FUNC ENDP
- PRINTING PROC
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET outmes
- MOV AH, 9
- INT 21h
- MOV AX, remainder
- CMP AX, 0
- JNE PRINT_FRACTION
- MOV AX, result
- CMP AX, 0
- JGE PRINT_MAIN_NUMBER
- MOV DL, '-'
- MOV AH, 2
- INT 21h
- MOV AX, result
- NEG AX
- PRINT_MAIN_NUMBER:
- CALL PRINT_NUM
- JMP END_PRINTING
- PRINT_FRACTION:
- MOV AX, numerator
- CMP AX, 0
- JGE PRINT_NUMERATOR
- MOV DL, '-'
- MOV AH, 2
- INT 21h
- MOV AX, numerator
- NEG AX
- PRINT_NUMERATOR:
- CALL PRINT_NUM
- MOV DL, '/'
- MOV AH, 2
- INT 21h
- MOV AX, denominator
- CMP AX, 0
- JGE PRINT_DENOMINATOR
- MOV DL, '-'
- MOV AH, 2
- INT 21h
- MOV AX, denominator
- NEG AX
- PRINT_DENOMINATOR:
- CALL PRINT_NUM
- MOV DL, ' '
- MOV AH, 2
- INT 21h
- MOV DL, '='
- INT 21h
- MOV DL, ' '
- INT 21h
- MOV AX, result
- CMP AX, 0
- JGE PRINT_RES_NUMBER
- MOV DL, '-'
- MOV AH, 2
- INT 21h
- MOV AX, result
- NEG AX
- PRINT_RES_NUMBER:
- CALL PRINT_NUM
- MOV DX, OFFSET ostacha_msg
- MOV AH, 9
- INT 21h
- MOV AX, remainder
- CMP AX, 0
- JL NEG_REM
- CALL PRINT_NUM
- JMP END_PRINTING
- NEG_REM:
- MOV DL, '-'
- MOV AH, 2
- INT 21h
- MOV AX, remainder
- NEG AX
- CALL PRINT_NUM
- END_PRINTING:
- RET
- PRINTING ENDP
- PRINT_NUM PROC
- PUSH result
- PUSH CX
- PUSH DX
- XOR CX, CX
- MOV BX, 10
- CONVERT_TO_STR:
- XOR DX, DX
- DIV BX
- ADD DL, '0'
- PUSH DX
- INC CX
- TEST AX, AX
- JNZ CONVERT_TO_STR
- PRINT_LOOP:
- POP DX
- MOV AH, 2
- INT 21h
- LOOP PRINT_LOOP
- POP DX
- POP CX
- POP result
- RET
- PRINT_NUM ENDP
- END_PROGRAM PROC
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET end_msg
- MOV AH, 9
- INT 21h
- MOV DX, OFFSET menuhold
- MOV AH, 0Ah
- INT 21h
- MOV AL, menuhold+2
- CMP AL, 'y'
- JE RETURN
- CMP AL, 'n'
- JE EXIT_PROGRAM
- MOV DX, OFFSET errmsg
- MOV AH, 9
- INT 21h
- JMP END_PROGRAM
- EXIT_PROGRAM:
- MOV AH, 4Ch
- INT 21h
- RETURN:
- XOR AX, AX
- XOR BX, BX
- XOR CX, CX
- XOR DX, DX
- XOR SI, SI
- MOV result, 0
- MOV remainder, 0
- MOV numerator, 0
- MOV denominator, 0
- MOV sign_flag, 0
- CALL RET_PROC
- END_PROGRAM ENDP
- CODE ENDS
- END START
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement