Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- DATA SEGMENT
- ; --- Новий текст із описом функції ---
- messtr DB 0Dh,0Ah, "Welcome! Let`s solve the piecewise function Z with your X value", 0Dh,0Ah,"$"
- ; Опис нової функції
- funct DB "Z = { x-1, if x < 10", 0Dh,0Ah, " { (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 -32768...32767) -> $"
- ; Буфер для введення X
- ; Замість 7,?,7 => 7,0,7. Перший байт = максимально дозволена довжина,
- ; другий = актуальна довжина (0 поки що), решта 7 символів = місце для вводу
- xinmes DB 7,0,7 DUP(" ")
- ; Прапорець знаку
- sign_flag DB 0
- ; Змінні, у яких зберігається вхідне X
- 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,"$"
- ostacha_msg DB " reminder $"
- end_msg DB "Do you want to continue? (y/n): $"
- ; Змінні для зберігання проміжних результатів
- result DW ?
- remainder DW ?
- numerator DW ?
- denominator DW ?
- ; Буфер для 'y/n' (так само замінюємо ? на 0)
- menuhold DB 2,0,2 DUP(" ")
- 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
- ; Вітання і читання X
- CALL WELC_PROC
- ; Обчислення нашої кусочної функції
- CALL FUNC
- ; Виведення результату
- CALL PRINTING
- ; Запит на продовження або вихід
- CALL END_PROGRAM
- ; Повернення управління в DOS
- MOV AH, 10
- INT 21h
- ;----------------------------------------
- ; Процедура вітання і зчитування X
- ;----------------------------------------
- WELC_PROC PROC
- ; Вивести вітальний рядок
- MOV DX, OFFSET messtr
- MOV AH, 9
- INT 21h
- ; Вивести опис функції
- MOV DX, OFFSET funct
- MOV AH, 9
- INT 21h
- ; Запропонувати ввести X
- MOV DX, OFFSET xreadmes
- MOV AH, 9
- INT 21h
- ; Зчитати X (рядок)
- MOV DX, OFFSET xinmes
- MOV AH, 10
- INT 21h
- ; Перевірка, чи коректний введений рядок
- CALL CHECK_INPUT
- ; Конвертувати з ACSII у число xvalue
- MOV SI, OFFSET xinmes
- ADD SI, 2
- CALL CONVERT
- MOV xvalue, BX
- ; Перехід на новий рядок
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- RET
- WELC_PROC ENDP
- ;----------------------------------------
- ; Перевірка введених символів на коректність
- ;----------------------------------------
- CHECK_INPUT PROC
- MOV SI, DX ; DX = OFFSET xinmes
- MOV CL, [SI+1] ; CL = довжина введеного рядка
- 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:
- 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 START
- END_CHECK:
- RET
- CHECK_INPUT ENDP
- ;----------------------------------------
- ; Процедура перевірки X на вихід за межі
- ;----------------------------------------
- CHECK_RANGE PROC
- ; -32768 <= AX <= 32767
- CMP AX, 32767
- JG RANGE_ERROR ; якщо AX > 32767 => помилка
- CMP AX, -32768
- JL RANGE_ERROR ; якщо AX < -32768 => помилка
- RET
- RANGE_ERROR:
- MOV DX, OFFSET range_err
- MOV AH, 9
- INT 21h
- 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
- ;----------------------------------------
- ; Перетворення введеної ASCII-послідовності
- ; в число (AX)
- ;----------------------------------------
- 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
- 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:
- ; ОДИН раз робимо NEG BX, якщо sign_flag=1
- 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
- ;----------------------------------------
- ; Основна процедура обчислення Z
- ;----------------------------------------
- FUNC PROC
- XOR AX, AX
- MOV AX, xvalue
- ; Перевіряємо, де ми знаходимося
- CMP AX, 10
- JL CASE_X_LT_10 ; x < 10
- JE CASE_X_EQ_10 ; x = 10
- JG CASE_X_GT_10 ; x > 10
- CASE_X_LT_10:
- ; Z = x - 1
- MOV AX, xvalue
- DEC AX
- MOV result, AX
- MOV remainder, 0
- JMP END_FUNC
- CASE_X_EQ_10:
- ; Z = (3x^2 + 4)/(x - 2), при x=10
- ; Чисельник = 3*(10^2) + 4 = 304
- ; Знаменник = 10 - 2 = 8
- MOV AX, xvalue
- IMUL xvalue
- MOV BX, 3
- IMUL BX
- ADD AX, 4
- MOV numerator, AX
- MOV AX, 10
- SUB AX, 2
- MOV denominator, AX
- MOV AX, numerator
- CWD
- MOV BX, denominator
- IDIV BX
- MOV result, AX
- MOV remainder, DX
- CALL CHECK_RANGE_RESULT
- JMP END_FUNC
- CASE_X_GT_10:
- ; Z = (7x^2 - 56)/(2x - 5)
- MOV AX, xvalue
- IMUL xvalue ; x^2
- MOV BX, 7
- IMUL BX ; 7*x^2
- SUB AX, 56 ; 7x^2 - 56
- MOV numerator, AX
- MOV AX, xvalue
- SHL AX, 1 ; 2*x
- SUB AX, 5 ; 2x - 5
- MOV denominator, AX
- MOV AX, numerator
- CWD
- MOV BX, denominator
- IDIV BX
- MOV result, AX
- MOV remainder, DX
- CALL CHECK_RANGE_RESULT
- JMP END_FUNC
- END_FUNC:
- RET
- FUNC ENDP
- ;----------------------------------------
- ; Друк результату
- ;----------------------------------------
- PRINTING PROC
- ; Перенос на новий рядок
- MOV DX, OFFSET newline
- MOV AH, 9
- INT 21h
- ; "Result:"
- MOV DX, OFFSET outmes
- MOV AH, 9
- INT 21h
- ; Якщо remainder=0, це ціле
- 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
- PRINT_MAIN_NUMBER:
- CALL PRINT_NUM
- JMP END_PRINTING
- PRINT_FRACTION:
- ; Виводимо вигляд: numerator / denominator = result reminder remainder
- MOV AX, numerator
- CMP AX, 0
- JGE PRINT_NUMERATOR
- MOV DL, '-'
- MOV AH, 2
- INT 21h
- PRINT_NUMERATOR:
- CALL PRINT_NUM
- MOV DL, '/'
- MOV AH, 2
- INT 21h
- MOV AX, 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
- PRINT_RES_NUMBER:
- CALL PRINT_NUM
- MOV DX, OFFSET ostacha_msg
- MOV AH, 9
- INT 21h
- MOV AX, remainder
- CMP AX, 0
- JL NEG_NUM
- CALL PRINT_NUM
- JMP END_PRINTING
- NEG_NUM:
- NEG AX
- CALL PRINT_NUM
- END_PRINTING:
- RET
- PRINTING ENDP
- ;----------------------------------------
- ; Процедура PRINT_NUM: виводить число (AX)
- ;----------------------------------------
- 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
- RET
- END_PROGRAM ENDP
- ; Псевдо "повернення" у START
- RET_PROC PROC
- CALL START
- RET
- RET_PROC ENDP
- CODE ENDS
- END START
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement