LINUX.ORG.RU

Десятичное представление числа, не помещающегося в один регистр, в ассемблере NASM

 ,


0

1

Добрый день!

Если у нас есть число, сохранённое в регистре, и нам нужно получить значения разрядов его десятичного представления - то всё довольно просто: только то и нужно, что делить его на 10 и сохранять полученные остатки.

lp:     cmp     eax, 0  ; have we finished?
        je      prinrt
        inc     ecx
        div     dword [divider]
        mov     [result + ecx - 1], dl
        xor     edx, edx
        jmp     lp

А как поступить, если число не помещается в одном регистре? Допустим, была выполнена команда mul ebx и итоговое число слишком большое, чтобы поместиться в 32 бита, и теперь хранится в edx:eax?



Последнее исправление: KOMMUNIST90 (всего исправлений: 2)

деление жеж в качестве делимого может принимать два регистра. а делитель - один регистр. так спокон веков было на всех архитектурах(ну на многих). то есть ты можешь в 32 битной архитектуре делить 64 бита на 32. соответственно результат произведения двух регистров, как обратная операция хранится в двух регистрах.

теперь хранится в edx:eax?

вот как раз деление на ebx например, будет делить содержимое edx:eax на ebx. читай описание команд проца.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)

Точно так же делить на 10. Но если 32-битное деление делается одной инструкцией, то для 64-битного на 32-битной системе тебе придётся писать маленькую подпрограмму - сначала делишь старшие 32 бита, затем остаток от деления и младшие 32 бита кладешь в регистры и делишь ещё раз. Два полученных ответа это старшие и младшие 32 бита результата деления, а остаток от второго - это остаток.

Так можно делить число любой разрядности, главное чтобы делитель влезал в 1 регистр. А вот если делитель тоже больше 32 бит то всё ещё хуже и подпрограмма получается сложная и не совсем очевидная.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от alysnix

вот как раз деление на ebx например, будет делить содержимое edx:eax на ebx. читай описание команд проца.

Ну расскажи тогда как ты командой проца поделишь 0x00001234:0x12345678 на 10.

Надо не только читать но и голову применять.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

вопрос как стоял?

Допустим, была выполнена команда mul ebx и итоговое число слишком большое, чтобы поместиться в 32 бита, и теперь хранится в edx:eax?

ответ - прям делишь и не паришься. а вот если РЕЗУЛЬТАТ от деления не лезет в один регистр - это уже вопрос другой. гы

alysnix ★★★
()
Ответ на: комментарий от alysnix

Очень круто давать советы, которые рандомно то работают то кидают исключение переполнения деления. Из слов автора никак не следует, что есть какие-то предположения о разрядности результата деления. mul ebx это очевидно умножение не на 10, а на какое-то другое число (иначе смысла в делении нет), да и приведено оно только для примера.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Очень круто давать советы, которые рандомно то работают то кидают исключение переполнения деления.

автора точно заботит - как разделить два регистра на один. я еще раз перечитал его текст. вопрос - а если результат деления не лезет в регистр у него не стоит ником образом. видимо он просто до него еще не дошел.

но предугадывать чужие проблемы - не наш путь. проблемы решаются по мере их поступления… может он одумается и все напишет хотя бы на си, избавившись от асма и все решится само собой? чего ему и желаем, поскольку это самое верное решение.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Решал задачку 3.21 из данного задачника:

http://stolyarov.info/books/programming_intro/taskbook

«Напишите программу, которая читает из потока стандартного ввода строки, каждая из которых содержит десятичную запись первого числа, знак арифметического действия (+, -, *, /) и десятичную запись второго числа (без пробелов). В ответ на каждую прочитанную строку программа должна напечатать результат выполнения указанного действия над числами (деление считать целочисленным) и сделать перевод строки; при наступлении ситуации «конец файла» - завершить работу. Если очередная строка не соответствует условиям задачи, следует напечатать слово «Error» и перевод строки, работу продолжить».

Задачку решил, но стало интересно что будет, если выбрать два числа достаточно большими, чтобы результат их умножения не помещался в один разряд. Тем более автор не указал в условиях, входит ли обработка этого специального случая в решение задачи или нет. Ознакомившись с ответами понял, что автор врядли имел ввиду этот особый случай. А поскольку сам я ассемблер изучаю по его же книжке, в рамках обзорного курса знакомства с принципами работы ЦПУ и памяти, детальное знакомство с длинной арифметикой я решил пока отложить.

KOMMUNIST90
() автор топика
Ответ на: комментарий от KOMMUNIST90

а нужно задачку на асме решить? знания си будут получше знания асма, если честно. асм нужен только по делу и очень редко, ну или для совсем детального понимания работы проца. опять же в либах должны быть функция вывода десятичного числа, такие рутинные функции никто ручками не пишет.

alysnix ★★★
()
Ответ на: комментарий от alysnix

Ты прикалываешься? По твоему совету он сделает кое-как работающий мусор, который падает на не совсем ожиданных входных данных. Впрочем я знаю, сейчас многие так и делают и считают что всё правильно. Но не надо эту пакость тут распространять.

firkax ★★★★★
()