1 / 1 / 1
Регистрация: 26.12.2019
Сообщений: 87
1

Как сделать деление

25.11.2021, 12:35. Показов 895. Ответов 27

Как на ассемблере сделать деление через вычитание и сдвиг
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.11.2021, 12:35
Ответы с готовыми решениями:

Как сделать деление
Как правильно записать деление?(dil) И как сделать сокращение дробей? Не нашел годной инфы в гугле...

Как сделать запрос на деление отношений?
Никак не могу понять как сделать запрос на деление отношений? Добавлено через 1 час 12 минут...

Как сделать деление больших чисел в МК8051
Пожалуйста подскажите как правильно взять остаток отделения на 100,7,4 от больших чисел например...

Можно ли сделать в Ubuntu деление окон как в Windows 7?
В семерке есть очень удобная фишка - если при активном окне приложения (например текстового...

Как сделать пакетное деление при бекапе сайта wordpress
Суть вопроса в том, что сайт чуть расширился и хостинг не обрабатывает резервное копирование и...

27
26 / 53 / 8
Регистрация: 23.11.2021
Сообщений: 354
25.11.2021, 12:38 2
Деление можно реализовать через умножение и сдвиг, а вот через вычитание и сдвиг - никак. Разве что итерационно, но это жуть как долго.
0
1 / 1 / 1
Регистрация: 26.12.2019
Сообщений: 87
25.11.2021, 12:39  [ТС] 3
а как тогда через умножение?
0
Модератор
Эксперт CЭксперт С++
4992 / 4403 / 827
Регистрация: 07.10.2015
Сообщений: 9,181
25.11.2021, 12:41 4
ArtoriasDark, какой контроллер?
0
1 / 1 / 1
Регистрация: 26.12.2019
Сообщений: 87
25.11.2021, 12:47  [ТС] 5
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.data
.text
li t0, 23
li t1, 1
cycle:
addi t1, t1, 1
mv t2, t0
jal x1, delenie
bne t3, zero, cycle
beq t0, t1, simple
 
complex:
li a0, 0
j exit
 
simple:
li a0, 1
 
delenie:
# тут сама подпрограмма
ret
 
exit:
ecall
нужно дописать под программу хз на каком контролере, эта под программа должна делить если проще, а программа проверять на простое или сложное. результат возвращается в регистр а0
0
Модератор
Эксперт по электронике
8517 / 6332 / 858
Регистрация: 14.02.2011
Сообщений: 22,021
25.11.2021, 14:01 6
Цитата Сообщение от Eddy_Em Посмотреть сообщение
а вот через вычитание и сдвиг - никак.
а это что
Умножение и деление используя сдвиги
0
26 / 53 / 8
Регистрация: 23.11.2021
Сообщений: 354
25.11.2021, 14:10 7
ValeryS, ну и как разделить любое число на 100, используя вычитание и сдвиги?
А при помощи умножения и сдвига легко:
C
1
2
3
4
5
uint32_t div100(uint32_t x){
  uint64_t u = (0xffffffff / 100); // 0x28F5C29
  u *= (uint64_t) x;
  return (uint32_t)(u >> 32);
}
На микроконтроллерах без аппаратного деления деление на константу именно так и реализуется, это намного быстрей, чем использовать общую софтовую операцию деления.
0
Модератор
Эксперт CЭксперт С++
4992 / 4403 / 827
Регистрация: 07.10.2015
Сообщений: 9,181
25.11.2021, 14:16 8
Eddy_Em, а разделить на ЛЮБОЕ число?
К тому же на контроллере
0
26 / 53 / 8
Регистрация: 23.11.2021
Сообщений: 354
25.11.2021, 14:31 9
В этом случае придется применять стандартную процедуру софтового деления. Очень-очень много тактов…
Но через вычитание будет совсем долго.
0
Модератор
Эксперт по электронике
8517 / 6332 / 858
Регистрация: 14.02.2011
Сообщений: 22,021
25.11.2021, 14:39 10
Цитата Сообщение от Eddy_Em Посмотреть сообщение
ValeryS, ну и как разделить любое число на 100,
я это знаю насчет деления со времен 0x86, все дело в том что там есть регистр переполнения edx(dx) и все это это делается легко ассемблером
а вот расширение числа и считывание старшего слова на микроконтроллере(сферическом в вакууме) еще не известно сколько тактов это займет
Цитата Сообщение от Eddy_Em Посмотреть сообщение
return (uint32_t)(u >> 32);
сколько это тактов займет

Цитата Сообщение от Eddy_Em Посмотреть сообщение
На микроконтроллерах без аппаратного деления деление на константу именно так и реализуется, это намного быстрей, чем использовать общую софтовую операцию деления.
и что? где сказано что
Цитата Сообщение от Eddy_Em Посмотреть сообщение
а вот через вычитание и сдвиг - никак.

Цитата Сообщение от Eddy_Em Посмотреть сообщение
uint64_t u = (0xffffffff / 100); // 0x28F5C29
не ошибся?
вопрос про умножение а не про деление
0
26 / 53 / 8
Регистрация: 23.11.2021
Сообщений: 354
25.11.2021, 15:00 11
Цитата Сообщение от ValeryS Посмотреть сообщение
сколько это тактов займет
Деление на константу не так уж и много тактов занимает, мужики на "радиокоте" проверяли для STM32F0. Самая жирная операция - это софтовое деление на произвольное число, там чуть ли не под 1000 тактов уходит! Деление на константу через сдвиг и умножение, приведением к uint64_t, занимает не больше ста тактов (около восьмидесяти, что ли).
0
Модератор
Эксперт по электронике
8517 / 6332 / 858
Регистрация: 14.02.2011
Сообщений: 22,021
25.11.2021, 15:12 12
Цитата Сообщение от Eddy_Em Посмотреть сообщение
для STM32F0.
32разрядный камень, а что будет на 8051? или там AVR?
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Самая жирная операция - это софтовое деление на произвольное число,
ну и где же никак?
алгоритм бы посмотреть
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Деление на константу через сдвиг и умножение, приведением к uint64_t, занимает не больше ста тактов
так константа это не деление на любое число где константа для деления на 100? чему она равна? а на 10?
деление на 2n вообще за 1 делается
0
1934 / 1249 / 124
Регистрация: 04.01.2010
Сообщений: 4,507
25.11.2021, 16:31 13
Цитата Сообщение от liv Посмотреть сообщение
а разделить на ЛЮБОЕ число?
вот так написал (от балды):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
uint32_t div_val(uint32_t x, uint32_t divider){
    uint32_t res = 0;
    uint32_t pow2=1;
    uint32_t divider_pow = divider;
    // Get the x shifted on N bits right
    while (x > divider_pow) {
        divider_pow <<= 1;
        pow2 <<= 1;
        iterations++;
    }
    while (x) {
        if (x >= divider_pow) {
            x -= divider_pow;
            res += pow2;
        } else {
            divider_pow >>= 1;
            pow2 >>= 1;
        }
        iterations++;
    }
    return res;
}
https://onlinegdb.com/g-mQUEMUp

можно наверное, продолжить допиливать дальше, чтобы достичь ТЗ ТС. Если кто доделает - интересно будет посмотреть

Добавлено через 1 минуту
кстати, наверное, воспользовавшись примером показанным выше Eddy_Em, можно сделать сильно проще
0
Модератор
Эксперт CЭксперт С++
4992 / 4403 / 827
Регистрация: 07.10.2015
Сообщений: 9,181
25.11.2021, 16:44 14
Мой вариант:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
 
uint32_t bitwise_divisionA (uint32_t dividend, uint32_t divisor)
{
    uint32_t res;
    __asm {
        mov  eax, [dividend]
        mov  ecx, [divisor]
        mov  edx, 32
        mov  ebx, 0
div_loop:
        add  eax, eax
        adc  ebx, ebx
        cmp  ebx, ecx
        jb   res_bit_is_0
res_bit_is_1:
        sub  ebx, ecx
        add  eax, 1
res_bit_is_0:
        dec  edx
        jnz  div_loop
        mov  [res], eax
    }
    return res;
}
 
uint32_t bitwise_divisionC (uint32_t dividend, uint32_t divisor)
{
    uint32_t res, rem, t;
    int bits_left = CHAR_BIT * sizeof (uint32_t);
 
    res = dividend;
    rem = 0;
    do {
        t = res;
        res <<= 1;
        rem = rem + rem + (res < t);
 
        if (rem >= divisor) {
            rem = rem - divisor;
            res++;
        }
        bits_left--;
    } while (bits_left);
    return res;
}
 
int main()
{
    uint32_t resA = bitwise_divisionA(1234, 17);
    uint32_t resC = bitwise_divisionC(1234, 17);
    uint32_t res = 1234 / 17;
}
Если задать не 32 бита, а допустим 16, 8 можно сделать деление 16-битных, 8-битных чисел
1
1934 / 1249 / 124
Регистрация: 04.01.2010
Сообщений: 4,507
25.11.2021, 16:57 15
Цитата Сообщение от liv Посмотреть сообщение
Мой вариант:
что-то у вас там запутано (стр 38-39) - зачем сдвигать и суммировать потом еще (сдвигать еще раз, по сути)?

Переписал чуток по-другому:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
uint32_t div_val(uint32_t x, uint32_t divider){
    uint32_t res = 0;
    uint32_t divider_pow = divider;
    // Get the x shifted on N bits right
    while (x >= (divider_pow << 1)) {
        divider_pow <<= 1;
        iterations++;
    }
    while (divider_pow >= divider) {
        res <<= 1;
        if (x >= divider_pow) {
            x -= divider_pow;
            res |= 1;
        }
        divider_pow >>= 1;
        iterations++;
    }
    return res;
}
Итераций меньше, меньше переменных, и отсутствует суммирование (iterations не в счет)
https://onlinegdb.com/bEKj6WuWx

Добавлено через 1 минуту
Цитата Сообщение от Voland_ Посмотреть сообщение
зачем
ошибся
0
Модератор
Эксперт CЭксперт С++
4992 / 4403 / 827
Регистрация: 07.10.2015
Сообщений: 9,181
25.11.2021, 16:59 16
Voland_, хорошо. Писал на скору руку...
0
1 / 1 / 1
Регистрация: 26.12.2019
Сообщений: 87
25.11.2021, 18:00  [ТС] 17
Я извиняюсь но я очень плохо знаю асемблер(я его не знаю). а как все что было выше запихнуть конкретно в эту прогу
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.data
.text
li t0, 23
li t1, 1
cycle:
addi t1, t1, 1
mv t2, t0
jal x1, delenie
bne t3, zero, cycle
beq t0, t1, simple
 
complex:
li a0, 0
j exit
 
simple:
li a0, 1
 
delenie:
# тут сама подпрограмма
ret
 
exit:
ecall
0
1934 / 1249 / 124
Регистрация: 04.01.2010
Сообщений: 4,507
25.11.2021, 18:11 18
Цитата Сообщение от ArtoriasDark Посмотреть сообщение
очень плохо знаю асемблер
придется познакомиться. Но "скомпилить выше обозначенные примеры вы можете и вот этим.
0
Модератор
Эксперт CЭксперт С++
4992 / 4403 / 827
Регистрация: 07.10.2015
Сообщений: 9,181
25.11.2021, 18:11 19
ArtoriasDark, это не MIPS часом? Лично я с MIPS не сталкивался.
Если MIPS, то в нем есть же операция деления. Зачем весь этот сыр-бор?
0
469 / 318 / 29
Регистрация: 15.08.2011
Сообщений: 995
25.11.2021, 21:06 20
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Деление можно реализовать через умножение и сдвиг, а вот через вычитание и сдвиг - никак.
Именно через вычитание и сдвиг в двоичной системе оно и делается.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Разве что итерационно, но это жуть как долго.
Например для 16-битной операции самым длинным будет деление 0xFFFF на 1. Обойдется это в 16 вычитаний и 16 сдвигов. Это жуть?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.11.2021, 21:06

Как сделать деление BCD чисел на асемблере? MASM32 Editor
Как сделать деление BCD чисел на асемблере? MASM32 Editor:cry:

Как сделать так чтобы если на ноль было деление не выодился Результат
var a,d,c:real; b:char; procedure kakulyator; begin case b of '+':d:=a+c; '-':d:=a-c;...

Slider как сделать чтоб каждое деление было подписано цифрами от min до max
&lt;Slider x:Name=&quot;pathsize_xaml&quot; Minimum=&quot;20&quot; Maximum=&quot;100&quot; Value=&quot;20&quot;...

Ребята подскажите как методы сделать на минус и на деление что бы все корректно отображалось
public class math { int i,n,sum,vich=0,mul=1; int div; int A; ...

сделать сложение, вычитание , умножение и деление
нужно сделать сложение, вычитание , умножение и делание unit Unit1; interface uses ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.