Не работает деление

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 шт):

Автор решения: Илья К
  1. их нельзя соединить, это уже длинная математика и тебе либо нужно самостоятельно превратить их строку которую передать для вывода или выдать ответ что входные денные выходят за допустимый диапазон значений.
→ Ссылка
Автор решения: PRODIGY
  1. Для больших чисел (да и вообще для любых в калькуляторах) обычно используют сопроцессор FPU.
  2. При операциях деления, делимое находится не в 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'
→ Ссылка