Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .386
- .MODEL FLAT, STDCALL
- EXTERN GetStdHandle@4 : PROC ; Получение дескриптора.
- EXTERN WriteConsoleA@20 : PROC ; Вывод в консоль.
- EXTERN CharToOemA@8 : PROC ; Строку в OEM кодировку.
- EXTERN ReadConsoleA@20 : PROC ; Ввод с консоли.
- EXTERN ExitProcess@4 : PROC ; Функция выхода из программы.
- EXTERN lstrlenA@4 : PROC ; Функция определения длины строки.
- .DATA
- STR1 DB "Введите первое число, а затем второе в шестнадцатеричной системе: ", 10, 0
- STR2 DB "Результат разности в десятичной системе: ", 0
- STR_ERR DB "Ошибка. Нужно не менее 3-х знаков и не слишком большие числа.", 0
- STR3 DQ " "
- DIN DD ? ; Дескриптор ввода, 4 байта.
- DOUT DD ? ; Дескриптор вывода, 4 байта.
- BUF DB 200 dup (?) ; Буфер для строк длиной 200 байт.
- LENS DD ? ; Для количества выведенных символов.
- FIRST DD 0
- SECOND DD 0
- S_16 DD 16
- F_SIGN DB 0
- S_SIGN DB 0
- .CODE
- START proc
- ; Перекодировка STR1.
- MOV EAX, OFFSET STR1
- PUSH EAX
- PUSH EAX
- CALL CharToOemA@8 ;
- ; Перекодировка STR2.
- MOV EAX, OFFSET STR2
- PUSH EAX
- PUSH EAX
- CALL CharToOemA@8
- ; Перекодировка STR_ERR.
- MOV EAX, OFFSET STR_ERR
- PUSH EAX
- PUSH EAX
- CALL CharToOemA@8
- ; Помещаем декриптор ввода в DIN.
- PUSH -10
- CALL GetStdHandle@4
- MOV DIN, EAX
- ; Помещаем декриптор вывода в DOUT.
- PUSH -11
- CALL GetStdHandle@4
- MOV DOUT, EAX
- ; Выводим приглашение для ввода на экран консоли.
- PUSH OFFSET STR1
- CALL lstrlenA@4 ; Помещаем в EAX количество символов в строке STR1.
- PUSH 0 ; Резервный параметр
- PUSH OFFSET LENS ; Берет адрес строки для вывода действительно выведенных символов (для длины)
- PUSH EAX ; Объявление временного буфера (сколько символов)
- PUSH OFFSET STR1 ; Берет адрес строки
- PUSH DOUT ; Указывает на стандартную библиотеку вывода
- CALL WriteConsoleA@20 ; Вызов функции
- ; Ввод первого числа.
- PUSH 0 ; Помещаем 5-й аргумент в стек (резерв).
- PUSH OFFSET LENS ; Помещаем 4-й аргумент в стек (адрес переменной для количества символов).
- PUSH 200 ; Помещаем 3-й аргумент в стек (максимальное количество символов).
- PUSH OFFSET BUF ; Помещаем 2-й аргумент в стек (адрес начала строки для ввода).
- PUSH DIN ; Помещаем 1-й аргумент в стек (дескриптор ввода).
- CALL ReadConsoleA@20
- ; Перевод из строки в первое число, а также проверка.
- SUB LENS, 2 ; Определяем длину строки без управляющих символов.
- CMP LENS, 3 ; Число должно содержать не меньше 3 знаков.
- JB ERROR
- CMP LENS, 8 ; Число должно содержать не больше 8 знаков.
- JA ERROR
- MOV ECX, LENS
- MOV ESI, OFFSET BUF
- XOR EBX, EBX
- XOR EAX, EAX
- ; Проверяем, отрицательно ли первое число.
- MOV BL, [ESI]
- CMP BL, '-'
- JNE CONVERT_FIRST ; Если не минус, то переход сразу к конвертированию.
- SUB LENS, 1 ; Если минус, то уменьшить длину строки на 1.
- MOV ECX, LENS
- MOV F_SIGN, 1 ; Установить флаг отрицательности на 1 (true).
- INC ESI ; Переход на следующий символ строки (цифру).
- CONVERT_FIRST:
- MOV BL, [ESI]
- SUB BL, '0' ; 0 в ASCII коде = 48
- CMP BL, 10 ;
- JA CHECK_16_1 ; Если цифра больше 9, нужно проверить на принадлежность [A , ... , E]
- SHL EAX, 4
- ADD EAX, EBX
- INC ESI
- JMP CONTINUE_1
- CHECK_16_1:
- SUB BL, 7
- CMP BL, 16 ; если цифра больше 15 (больше F).
- JAE ERROR
- CMP BL, 10 ; если цифра меньше 10 (служебные символы).
- JB ERROR
- SHL EAX, 4
- ADD EAX, EBX
- INC ESI
- CONTINUE_1:
- LOOP CONVERT_FIRST
- ADD FIRST, EAX
- JC ERROR
- CMP F_SIGN, 1 ; Если изначально число отрицательное,
- JNE SIGN_NEG_1
- NEG FIRST ; то умножаем его на -1.
- SIGN_NEG_1:
- ; Ввод второго числа.
- PUSH 0
- PUSH OFFSET LENS
- PUSH 200
- PUSH OFFSET BUF
- PUSH DIN
- CALL ReadConsoleA@20
- ; Перевод из строки второго числа и проверки.
- SUB LENS, 2
- CMP LENS, 3
- JB ERROR
- CMP LENS, 8
- JA ERROR
- MOV ECX, LENS
- MOV ESI, OFFSET BUF
- XOR EBX, EBX
- XOR EAX, EAX
- ; Проверяем отрицательно ли второе число.
- MOV BL, [ESI]
- CMP BL, '-'
- JNE CONVERT_SECOND ; Если не минус, то переход к конвертации.
- SUB LENS, 1 ; Если минус, то уменьшить длину строки на 1.
- MOV ECX, LENS
- MOV S_SIGN, 1 ; Установить флаг отрицательности на 1 (true).
- INC ESI ; Переход на следующий символ строки (цифру).
- CONVERT_SECOND:
- MOV BL, [ESI]
- SUB BL, '0'
- CMP BL, 10
- JA CHECK_16_2 ; Если цифра больше 9, нужно проверить на принадлежность [A , ... , E]
- SHL EAX, 4
- ADD EAX, EBX
- INC ESI
- JMP CONTINUE_2
- CHECK_16_2:
- SUB BL, 7
- CMP BL, 16 ; Если цифра больше 15 (больше F).
- JAE ERROR
- CMP BL, 10 ; Если цифра меньше 10 (служебный символ).
- JB ERROR
- SHL EAX, 4
- ADD EAX, EBX
- INC ESI
- CONTINUE_2:
- LOOP CONVERT_SECOND
- ADD SECOND, EAX
- JC ERROR
- ; Проверяем необходимость смены знака.
- CMP S_SIGN, 1
- JNE SIGN_NEG_2
- NEG SECOND
- SIGN_NEG_2:
- ; Вычитание чисел
- MOV S_SIGN, 0 ; Предположение, что число положительное.
- MOV EAX, SECOND
- SUB FIRST, EAX ; Вычитание.
- CMP FIRST, 0 ; Сверка с нулем.
- JGE SUM_0
- MOV S_SIGN, 1 ; Если отрицательное, поменять знак.
- NEG FIRST
- SUM_0:
- ; Перевод десятичного числа в строку.
- XOR EBX, EBX
- XOR EAX, EAX
- MOV ESI, OFFSET STR3
- CMP S_SIGN, 0 ; Если результат отрицательный,
- JE SIGN_POS ; то добавить в строку знак '-'.
- MOV AX, 45 ; 45 - код знака '-'.
- MOV [ESI], AX
- INC ESI
- SIGN_POS:
- XOR CX,CX ; Количество символов, обнуляется.
- MOV EBX, 10 ; Делитель в 16битовый регистр.
- MOV EAX, FIRST ; EDX:EAX <- FIRST.
- XOR EDX, EDX
- JMP TO_STRING
- ; Выводим результат.
- OUTPUT:
- PUSH OFFSET STR2
- CALL lstrlenA@4
- PUSH 0
- PUSH OFFSET LENS
- PUSH EAX
- PUSH OFFSET STR2
- PUSH DOUT
- CALL WriteConsoleA@20
- PUSH OFFSET STR3
- CALL lstrlenA@4
- PUSH 0
- PUSH OFFSET LENS
- PUSH EAX
- PUSH OFFSET STR3
- PUSH DOUT
- CALL WriteConsoleA@20
- PUSH 0
- CALL ExitProcess@4 ; Выход
- ; В случае ошибки.
- ERROR:
- PUSH OFFSET STR_ERR
- CALL lstrlenA@4
- PUSH 0
- PUSH OFFSET LENS
- PUSH EAX
- PUSH OFFSET STR_ERR
- PUSH DOUT
- CALL WriteConsoleA@20
- PUSH 0
- CALL ExitProcess@4 ; выход
- START ENDP
- END START
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement