Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.05.2012, 02:53   #1
kventin_zhuk
БНТУ ФИТР
Форумчанин
 
Аватар для kventin_zhuk
 
Регистрация: 20.05.2012
Сообщений: 315
По умолчанию Assembler. деление

Здравствуйте. Преподаватель поставил задачу разделить число на само себя(12h/12h в моём варианте). Нельзя использовать команду DIV, а можно только команду сдвига SRH, команду and для проверки чётности и команду sub. Уже неделю ломаю мозг, всё никак. Из того,что придумал:

mov ax,12h
shr ax,1 12h/2=9
shr ax,1; 9h/2=4 -----> CF=1
shr ax,1 4/2=2
shr ax,1 2/2=1

Четырьмя последовательными сдвигами я достиг результата 1. Число 2 в 4-ой степени = 10h. Преподаватель говорит, что я разделил 12h/10h , а мне нужно 12 на 12. т.е (2^4+2);
Помогите плз, кто знает чем.
С++(console/builder/WinAPI/Linux), C#, Pascal, Delphi, Asm, Prolog.
< ----- Контакты
kventin_zhuk@live.com

Последний раз редактировалось kventin_zhuk; 20.05.2012 в 02:55. Причина: описка
kventin_zhuk вне форума Ответить с цитированием
Старый 20.05.2012, 11:37   #2
vadimych
Форумчанин
 
Регистрация: 16.01.2011
Сообщений: 325
По умолчанию

Цитата:
Преподаватель поставил задачу разделить число на само себя(12h/12h в моём варианте)
А что, может быть результат не равный единице?
vadimych вне форума Ответить с цитированием
Старый 20.05.2012, 13:03   #3
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

вопрос не в результате, а в упражнении.

не знаю зачем свиг и "и". все что приходит на ум, это вычитать 12h пока вычитается и инкрементить счетчик вычитаний.
f.hump вне форума Ответить с цитированием
Старый 20.05.2012, 13:34   #4
kventin_zhuk
БНТУ ФИТР
Форумчанин
 
Аватар для kventin_zhuk
 
Регистрация: 20.05.2012
Сообщений: 315
По умолчанию

Цитата:
Сообщение от f.hump Посмотреть сообщение
вопрос не в результате, а в упражнении.

не знаю зачем свиг и "и". все что приходит на ум, это вычитать 12h пока вычитается и инкрементить счетчик вычитаний.
да,мне тоже пришло это на ум. написал программу с инкрементами, работает, вот что получилось:
Цитата:
mov bp,300
mov ax,718b
mov [bp],ax
mov ax,[bp]
mov bx,59
mov [bp+10],bx;
and ax,1
jnz 129
and bx,1
jnz 129
mov ax,718b
mov bx,59
shr ax,1
shr bx,1
jmp 12F
mov ax,718b
mov bx,59
inc cx
sub ax,bx
jge 12F
add ax,bx
dec cx
С++(console/builder/WinAPI/Linux), C#, Pascal, Delphi, Asm, Prolog.
< ----- Контакты
kventin_zhuk@live.com
kventin_zhuk вне форума Ответить с цитированием
Старый 22.05.2012, 11:49   #5
DiemonStar
Старожил
 
Регистрация: 08.02.2012
Сообщений: 2,173
По умолчанию

и какой результат хочет увидеть ваш преподаватель? целое число с остатком или дробное число?
Правильно поставленная задача - три четверти решения.
DiemonStar вне форума Ответить с цитированием
Старый 22.05.2012, 13:12   #6
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,139
По умолчанию

kventin_zhuk
ниже несколько способов деления без использования команд div/idiv

Табличное преобразование
Для реализации деления на заранее известное число можно использовать табличное преобразование (команда XLAT).

Деление через вычитание
Частное от деления можно представить как количество вычитаний делителя из делимого до тех пор, пока делимое сохраняет знак. Это дало возможность организовать деление путем повторения последовательности вычитаний с проверкой знака делимого. Если произошла перемена знака, то нужно уменьшить счетчик числа вычитаний на единицу, а делимое и делитель сложить. Теперь делимое будет равно остатку, а счетчик числа вычитаний равен частному. Так делили на ранних микропроцессорах Intel (i4004, i8080), которые еще не поддерживали команду деления.

Деление через вычитание, сложение и сдвиги
При делении двоичных чисел используют два алгоритма: алгоритм деления без восстановления и алгоритм деления с восстановлением. При делении с помощью вычитаний, сложений и сдвигов можно использовать две схемы.
Схема а – делимое по мере вычисления сдвигается влево, делитель остается неподвижным.
Схема б – делимое неподвижно, а делитель по мере вычисления сдвигается вправо. Цифры частного формируются по значению бита переноса CF, устанавливаемого при вычитании или сложении делителя и делимого, и сдвигаются влево.
Таким образом, можно использовать четыре способа деления через вычитания, сложения и сдвиги.
Показываю алгоритм деления без восстановления на примере 125/11=11 остаток 4. Из делимого вычитается делитель, умноженный на степень двойки. Произведение числа на 2^n эквивалентно сдвигу этого числа на n разрядов влево. Если знак результата положительный, то нужно прибавить 2^n к частному, если знак результата отрицательный – частное не увеличивается. Когда знак результата меняется на отрицательный, вычитание заменяется сложением. Так повторяется при уменьшающихся степенях двойки до тех пор, пока не будет достигнута степень, равная нулю. Остатком считается последний положительный результат.
Делим 125 на 11. Делитель укладывается в байт (11<255), поэтому начинаем с 2^7. В начале вычисления частное всегда равно 0:
125 – 11 × 2^7= –1283
–1283 +11 × 2^6= –579
–579 +11 × 2^5= –227
–227 +11 × 2^4= –51
–51 + 11 × 2^3= 37 результат положительный, поэтому складываем 2^3 с частным, частное равно 8+0=8
37 – 11 × 2^2= – 7
–7 + 11 × 2^1= 15 результат положительный, поэтому складываем 2^1 с частным, частное равно 8+2=10
15 –11 × 2^0 = 4 результат положительный, поэтому складываем 2^0 с частным, частное равно 10+1=11, остаток равен 4
Код:
mov edx,ДЕЛИМОЕ
bsr ecx,edx
mov ebx,ДЕЛИТЕЛЬ
bsr eax,ebx ; чтобы не делать лишних операций
sub ecx,eax ; определим разрядность делимого и
mov ebp,1 ; делителя
shl ebp,cl
shl ebx,cl
xor eax,eax; в EAX место под частное, в EDX – остаток
or esi,-1 
a1: mov edi,ebx
add edi,esi
xor edi,esi; neg edi
add edx,edi; если esi=-1 тогда edx:=edx-ebx иначе edx:=edx+ebx
sbb esi,esi; если CF=1 тогда esi:=-1 иначе esi:=0
mov edi,esi
and edi,ebp; если esi=-1 тогда edi:=ebp иначе edi:=0
add eax,edi; если esi=-1 тогда eax:= eax + ebp
test edx,edx
jz a2;exit
shr ebx,1
shr ebp,1
jnz a1
a2:
Деление чисел при помощи вычитаний, сложений и сдвигов в ряде случаев оказывается быстрее, чем использование команд DIV или IDIV. Кроме того, деление при помощи вычитаний, сложений и сдвигов не так очевидно для «кодокопателя», чем команды DIV или IDIV.
Mikl___ вне форума Ответить с цитированием
Старый 22.05.2012, 20:47   #7
Indian
Форумчанин
 
Регистрация: 23.02.2010
Сообщений: 107
По умолчанию

18 = 10010 = 2^4 + 2^1
A*18 = A*(2^4 + 2^1) = A*2^4 + A*2^1
A/18 = A*(1/18)
1/18 = 2^(-5) + 2^(-6) + 2^(-7) (о представлении дробных чисел в двоичной системе см. вики)
A*(1/18) = A*2^(-5) + A*2^(-6) + A*2^(-7)
A*(1/18) = 0 - A*2^(-5) - A*2^(-6) - A*2^(-7)
Только это работает как-то неправильно: 18/18 даст 0(т.к. 18>>5 = 0, 18>>6 = 0, 18>>7 = 0.)

Последний раз редактировалось Indian; 22.05.2012 в 21:25.
Indian вне форума Ответить с цитированием
Старый 22.05.2012, 20:50   #8
kventin_zhuk
БНТУ ФИТР
Форумчанин
 
Аватар для kventin_zhuk
 
Регистрация: 20.05.2012
Сообщений: 315
По умолчанию

Всем спасибо, разобрался)
С++(console/builder/WinAPI/Linux), C#, Pascal, Delphi, Asm, Prolog.
< ----- Контакты
kventin_zhuk@live.com
kventin_zhuk вне форума Ответить с цитированием
Старый 28.05.2012, 14:29   #9
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,139
По умолчанию

Indian
A*(1/18)~A*2^(-4)-A*2^(-7)+A*2^(-10)=A/17,964912280701754385964912280702
при А=18 даст 1

Последний раз редактировалось Mikl___; 29.05.2012 в 06:43.
Mikl___ вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Деление в C++ Юнона Общие вопросы C/C++ 10 29.05.2011 17:53
Деление массива на число, и последующий Division by zero [Assembler] HostileZeth Помощь студентам 1 14.12.2010 19:14
Деление 0479 Общие вопросы по Java, Java SE, Kotlin 1 08.11.2010 00:37
Деление в С++ Tanilita Общие вопросы C/C++ 5 26.02.2010 17:28
Деление |{ot Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 4 24.03.2009 01:50