Потребовалось в двоичной системе разделить +117/-13. Если бы делилось 117 на 13, то тут всё просто, использовались бы вычитания и сдвиги а вот как разделить 01110101 на 11110011 чтобы в результате получилось 11110111 при этом используя элементарные операции (сдвиги, сложение. вычитание)?
rmn, это первое, что приходит в голову, но как-то "некузяво". Я понимаю, что нужно искать литературу по intel8080 или микроконтроллерам и смотреть там, но пока ничего под руками нет
Mikl___, p.184 Довольно тяжело воспринимается(два регистровых набора) впрочем это матан иначе не может быть. Мантиссы и тп твоя тема.
Никогда не видел чтобы деление обобщали на знаковые числа без анализа знаков делимого и делителей с переводом в беззнаковые и коррекцией результата. Собственно это то же самое, что мы делаем в столбик. Да это ж оверкилл с вещественными числами. Если уж нужен кусок кода на Z80 (с беззнаковыми!), то вот: Код (Text): ; H_div_L - деление h / l ; in: h - делимое ; l - делитель ; out: h <- h / l (результат) ; a <- h % l (остаток) H_div_L push bc ld b, 8 xor a .loop sla h rla cp l jr c, .skip inc h sub l .skip djnz .loop pop bc ret Это всё то же самое деление в столбик, но с небольшими оптимизациями - результат сразу же замещает делимое в регистре h по ходу процесса. Но при делении на константы возможны дополнительные трюки. На x86 стал излюбленным трюк когда переводят в вещественные, умножают на константу и одним сдвигом выбивают возможную ошибку из нижних разрядов.
Практического смысла гораздо больше в варианте rmn, но ради "кузявости": Ваше 117/13 = 117 - 13 * 8 - 13 * 1 отнять положительное, это тоже самое, что прибавить отрицательное: 117/(-13) = 117 + (-13 * 8) + (-13 * 1) = 117 + (11110011b * 8) + (11110011b * 1) = 01110101b + 10011ooob + 11110011b Чтоб совсем просто: деление столбиком - это один интеллектуальный шажочек от совсем тупого варианта: Отняли делитель, инкрементировали счётчик(он же, будущее частное) и так в цикле, пока >= 0. Просто отнимают не делитель * 1, А делитель * 2, или/и делитель * 4, или/и делитель * 8, и т. д. И соотв-но, +2 к результату, или +4 или +8 ....
почему для правильного результата +117/-13=-9 мне нужно сдвинуть +117 влево на 9 разрядов и добавить +117? Магия? -13=243 -9=247 243*247=60021=117*513 ?
Совпадение. Если взять за делимое 104 которое прекрасно на 13 делится, то этот же "трюк" не приводит ни к чему хорошему. 104*512+104=53352/243=219,55555... Вообще даже само количество и качество доп-действий тут уже заметно сложнее классического анализа знаков.
Код (Text): _117 3 09 39 _27 27 0 Деление столбиком это деление числа по частям, используя то свойство основания системы счисления, что позиция разряда есть его множитель: 117=1x102+1x101+7x100, 39=30x101+9x100. Таким образом из 117 отнимают 3*30=90, 27 в остатке дает 9. Операция negate и кодирование знака в MSB эксплуатирует свойство переноса разряда в плюс бесконечность (когда имеешь дело не с числом, а с полем фиксированной длины, на это плевать): Код (Text): 11110011 + 00001101 =0 И ИМХО ни малейшего арифметического смысла у этой формы записи числа, продленного единицами в плюс бесконечность, нет. Даже школьники, деля числа в десятичной системе, знак отбрасывают.
Термин "отрицательное число", имхо неудачен. Лучше мыслить и оперировать понятием "дополнение до числа 2N", где N - число разрядов в выбранной разрядной сетке. Каждый множитель - "отрицательное число", приводить к "дополнению до числа 2N", и результат будет корректен только в битах, находящихся в пределах выбранной разрядной сетки. Если смотреть на вопрос под этим, правильным углом, то вся "магия" рассосётся.
Интересно, что механические калькуляторы разных типов лажают при попытке поделить на ноль зацикливаясь в процессе: Но если взять целочисленный алгоритм деления приведённый выше - "битовый столбик": Код (Text): ; H_div_L - деление h / l ; in: h - делимое ; l - делитель ; out: h <- h / l (результат) ; a <- h % l (остаток) H_div_L push bc ld b, 8 xor a .loop sla h rla cp l jr c, .skip inc h sub l .skip djnz .loop pop bc ret то нетрудно заметить (владея ассемблером Z80 конечно же), что количество циклов алгоритма лимитировано битностью результата и он точно выдаст некий результат. Какой же, если поделить некое X на 0? Ответ забавен: результат получится целиком забит единицами, т.е. максимальное целочисленное число влазящее в данную разрядную сетку, а в качестве остатка вернётся само число X. X/0=11111111 остаток X Это забавно потому что если мы теперь "проверим" результат деления обратным действитем, то получим 11111111*0+X=X... Оппа, единицы уничтожились при умножении на ноль и поэтому остаток равный делимому согласует равенство! Т.е. алгоритм с одной стороны "попытался" в результате получить максимально большое числое (максимально близкое к бесконечности), а с другой стороны манипулируя остатком "прикрыл" себе жопу для проверки результата. В чём то даже гениально.
После того как впервые обратил внимание на этот прикол, ещё подумал: "Встретится ли мне когда-нибудь подобное???" Блин!!! Оно в функции memset!!!:lol: ..... ..... movzx edx, dl mov r9, 101010101010101h imul rdx, r9 ..... ....