Не работает деление
format pe console
include 'C:\Program Files\FASM\INCLUDE\win32ax.inc'
include 'C:\Program Files\FASM\INCLUDE\api\kernel32.inc'
entry start
.data
Num1 dd 0 ;Первое
Num2 dd 0 ;Второе число
Act db 0 ;Операция
.code
start: cinvoke printf, <'It is console calculator%c+ addition%c- subtraction%c* multiplication%c/ devision%c%c'>, 10, 10, 10, 10, 10, 10
begin:
cinvoke printf, <'First number: '> ;Ввод пользователем чисел и операции
cinvoke scanf, <'%d'>, Num1
cinvoke printf, <'Second number: '>
cinvoke scanf, <'%d'>, Num2
cinvoke printf, <'Operation: '>
cinvoke scanf, <'%s'>, Act
cmp byte [Act], '+' ;Проверка на сложение
jne notAdd ;Если не сложение, то перейти в notAdd
mov eax, dword [Num1] ;Сложение
add eax, dword [Num2]
cinvoke printf, <'Result: %d'>, eax ;Вывод результата
cinvoke getch
cinvoke printf, <'%c%c'>, 10, 10 ;Пропуск 2 строк
jmp begin ;Переход в начало
notAdd: cmp byte [Act], '-' ;Проверка на вычитание
jne notSub ;Если не вычитание, то перейти в notSub
mov eax, dword [Num1] ;Вычитание
sub eax, dword [Num2]
cinvoke printf, <'Result: %d'>, eax ;Вывод результата
cinvoke getch
cinvoke printf, <'%c%c'>, 10, 10 ;Пропуск 2 строк
jmp begin ;Переход в начало
notSub: cmp byte [Act], '*' ;Проверка на умножение
jne notMul ;Если не умножение, то перейти в notMul
mov eax, dword [Num1] ;Умножение
imul dword [Num2]
cinvoke printf, <'Result: %d'>, eax ;Вывод результата
cinvoke getch
cinvoke printf, <'%c%c'>, 10, 10 ;Пропуск 2 строк
jmp begin ;Переход в начало
notMul: cmp byte [Act], '/' ;Проверка на деление
jne notDiv ;Если не деление, то перейти в notDiv
cmp dword [Num2], 0 ;Проверка на деление на ноль
je divisionByZero ;Если деление на ноль, то перейти в divisionByZero
mov eax, dword [Num1] ;Деление
idiv dword [Num2]
cinvoke printf, <'Result: %d'>, eax ;Вывод результата
cinvoke getch
cinvoke printf, <'%c%c'>, 10, 10 ;Пропуск 2 строк
jmp begin ;Переход в начало
notDiv: cinvoke printf, <'Invailid operation'>
cinvoke getch
cinvoke printf, <'%c%c'>, 10, 10 ;Пропуск 2 строк
jmp begin ;Переход в начало
divisionByZero: cinvoke printf, <'Infinity'>
cinvoke getch
cinvoke printf, <'%c%c'>, 10, 10 ;Пропуск 2 строк
jmp begin ;Переход в начало
section '.idata' import data readable
library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll'
import msvcrt, printf, 'printf', getch, '_getch', scanf, 'scanf'
Я написал калькулатор, где вводятся 2 числа и действие. Сначала проверяется, нужно ли числа сложить. Если действие - не сложение, то проверяется, нужно ли числа вычесть. Потом идёт умножение и деление. Если не деление, то выводится информация о том, что действие неправильное. У меня есть 2 проблемы:
1 Если умножать большие числа, то ответ получается неправильный. Результат разделяется на 2 половины одна записывается в edx, а другая в eax. Я не знаю, как их соединить.
2 Если делить на любое, отличное от 0 число, то приложение вылетает.
Ответы (2 шт):
Автор решения: Илья К
→ Ссылка
- их нельзя соединить, это уже длинная математика и тебе либо нужно самостоятельно превратить их строку которую передать для вывода или выдать ответ что входные денные выходят за допустимый диапазон значений.
Автор решения: PRODIGY
→ Ссылка
- Для больших чисел (да и вообще для любых в калькуляторах) обычно используют сопроцессор FPU.
- При операциях деления, делимое находится не в
EAX, а в пареEDX:EAX. Поэтому нужно взять за правило, перед инструкциейDIVвсегда очищатьEDX=xor edx,edx. На выходе, в регистреEAXполучим целое, аEDXостаток от деления. При операциях умножения результат так-же в пареEDX:EAX, и выводить эту пару можно только в виде HEX, или тем-же сопром FPU. Вот пример:
format pe console
include 'win32ax.inc'
entry start
;//----------
.data
Num1 dd 0
Num2 dd 0
Result dq 0 ;// 8-байт результ для FPU
;//----------
.code
start: cinvoke printf,<10,10,' First number.: '>
cinvoke scanf, <'%d'>, Num1
cinvoke printf,<' Second number: '>
cinvoke scanf, <'%d'>, Num2
cinvoke printf,<' Operation....: '>
cinvoke getch ;//<---- символ в EAX (AL)
finit ;// очистить регистры сопра
fild [Num1] ;// загрузить число в регистр ST0
cmp al,'+'
jne @f
cinvoke printf,<'+'>
fiadd [Num2] ;// прибавить к ST0 переменную
jmp @getResult
@@: cmp al,'-'
jne @f
cinvoke printf,<'-'>
fisub [Num2] ;//<--- операция
jmp @getResult
@@: cmp al,'*'
jne @f
cinvoke printf,<'*'>
fimul [Num2] ;//<--- операция
jmp @getResult
@@: cmp al,'/'
jne @f
cinvoke printf,<'/'>
cmp [Num2],0
je @f
fidiv [Num2] ;//<--- операция
jmp @getResult
@@: cinvoke printf,<10,' Error!!!',0>
jmp start
;//<--- Вывод результата [%.3f] = три знака после запятой
@getResult:
fstp [Result] ;// сохранить число FPU в переменной
cinvoke printf,<10,' Result.......: %.3f',0>,dword[Result],dword[Result+4]
jmp start
@exit: cinvoke getch
cinvoke exit,0
;//------------
section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',getch,'_getch',scanf,'scanf',exit,'exit'