Деление 64-битного числа

Тема в разделе "WASM.ASSEMBLER", создана пользователем CtrlAltDel, 2 авг 2009.

  1. CtrlAltDel

    CtrlAltDel New Member

    Публикаций:
    0
    Регистрация:
    27 июл 2009
    Сообщения:
    8
    Hello! Приведу цитату из книги "Изучаем Ассемблер - Крупник А.Б.":
    Задача 5-10. Напишите процедуру деления 64-битового числа, хранящегося в двух регистрах, на произвольное число. Подсказка: вспомните деление -«столбиком» десятичных чисел.
    Довольно долго уже голову ломаю! Как это сделать??? Помогите кто знает!

    ЗЫ, всякие специальные для этого команды не предлагать!;)
     
  2. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    А в чем проблема?

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

    Столбиком чуть сложнее (но быстрее), и полно примеров в интернете.
     
  3. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Сравниваем старшие разряды делимого с делителем, если больше или равно -- вычитаем из них делитель, пишем единицу в частное; если меньше -- пишем нуль в частное. После этого сдвигаемся на один разряд вправо (относительно делимого), опять сравниваем... ну и так далее до конца :) В точности, как при ручном делении в столбик, с той лишь разницей, что при делении десятичных чисел надо ещё установить конкретную цифру частного, а здесь их всего две -- 0 или 1.
     
  4. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Код (Text):
    1. mov eax, dword [x+0]
    2. mov edx, dword [x+4]
    3. mov ebx, dword [y+0]
    4. xor ecx, 64
    5. xor ebp, ebp
    6. xor edi, edi
    7. xor esi, esi
    8. @@:
    9. clc
    10. rcl eax, 1
    11. shl edx, 1
    12. ; две предыдущие команды можно заменить shld
    13. rcl ebp, 1
    14. cmp ecx, ebx
    15. rcl esi, 1
    16. rcl edi, 1
    17. loop @b
    18. not esi
    19. not edi
    20. mov dword [r+0], esi
    21. mov dword [r+4], edi
    22. ...
    23. x  dq XXXXXXXXXXXX
    24. y  dd YYYYYYYYYYYY
    25. r  dq ?
     
  5. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    прошу прощения
    Код (Text):
    1. cmp ebp, ebx
     
  6. CtrlAltDel

    CtrlAltDel New Member

    Публикаций:
    0
    Регистрация:
    27 июл 2009
    Сообщения:
    8
    Ого!=) Сколько ответов! Всем спасибо большое! Буду "разбирать" ваши ответы......
     
  7. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    вот только не надо думать что тебе дали законченный код. тебя лишь пнули в нужную сторону. поймешь принцип - сможешь закончить, не поймешь - забей.
     
  8. CtrlAltDel

    CtrlAltDel New Member

    Публикаций:
    0
    Регистрация:
    27 июл 2009
    Сообщения:
    8
    Ну, эт понятное дело! Постараюсь понять......
     
  9. Memphis

    Memphis New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2008
    Сообщения:
    104
    CtrlAltDel
    Задача 5-10. Напишите процедуру деления 64-битового числа, хранящегося в двух регистрах, на произвольное число. - если следовать строго этому, загрузите делимое (64 бита) в регистры EDX:EAX, делитель в любой 32-х битный РОН (или в память) и делите на здоровье, к примеру, командой, Div EBX (если делитель помещен в EBX). Чтобы не напороться на переполнение, делаем проверку содержимого EDX & EBX.
     
  10. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    Если требуется разделить 64-битное на 32-битное
    Код (Text):
    1. ; EDX - HIDWORD
    2. ; EAX - LODWORD
    3. ; ECX - DIVIDER
    4. DIV ECX
    Если требуется разделить n-dword'ное на 32-битное
    Формат структур, на которые указывают параметры lpArg и lpRes: [DWORD: число DWORD'ов в записи числа; <данные>]
    Код (Text):
    1. Divide proc USES EDI ESI, lpArg:DWORD, nDiv:DWORD, lpRes:DWORD
    2.       MOV  ESI, lpArg
    3.       MOV  EDI, lpRes
    4.       MOV  EBX, nDiv
    5.       MOV  ECX, [ESI]
    6.       MOV  [EDI], ECX
    7.       LEA  EAX, [ECX*4]
    8.       ADD  ESI, EAX
    9.       ADD  EDI, EAX
    10.       PUSH EDI
    11.       STD
    12.       XOR  EDX, EDX
    13.   @loop:
    14.       LODSD
    15.       DIV  EBX
    16.       STOSD
    17.       LOOP @loop
    18.       POP  EAX
    19.       CMP  DWORD PTR [EAX], 0
    20.       JNE  @F
    21.       DEC  DWORD PTR [EDI]
    22.   @@: CLD
    23.       RET
    24. Divide Endp
    А вот как разделить n-битное на m-битное без остатка пока что я не понимаю. ( вычитание не предлагать - числа большие ).
     
  11. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    CtrlAltDel
    Код (Text):
    1. .model flat
    2. include windows.inc
    3. includelib user32.lib
    4. extern _imp__wsprintfA:dword
    5. extern _imp__MessageBoxA@16:dword
    6. .code
    7. start:  mov edx,dword ptr x+4
    8.     mov ebx,y
    9.     cmp edx,ebx
    10.     ja overflow
    11.     mov eax,dword ptr x
    12.     mov esi,80000000h
    13.     xor edi,edi
    14.     xor ebp,ebp
    15. a0: shrd ebp,ebx,1
    16.     shr ebx,1
    17.     cmp edx,ebx
    18.     jb a2
    19.     jne a1
    20.     cmp eax,ebp
    21.     jb a2  
    22. a1: sub eax,ebp
    23.     sbb edx,ebx
    24.     add edi,esi
    25. a2: shr esi,1
    26.     jnz a0
    27.     push edi;частное
    28.     push eax;остаток
    29.     mov edx,dword ptr x+4
    30.     mov eax,dword ptr x
    31.     mov ebx,y
    32.     div ebx; проверка
    33.     push eax;частное
    34.     push edx;остаток
    35.     mov ebx,offset buffer
    36.         push offset format
    37.         push ebx   
    38.     call _imp__wsprintfA
    39.     add esp,4*6;корректируем стек
    40.     jmp short a3
    41. overflow: mov ebx,offset err
    42. a3: push MB_OK
    43.     push offset MsgCaption
    44.     push ebx   
    45.     push 0
    46.     call _imp__MessageBoxA@16
    47.     ret
    48. MsgCaption      db "div",0
    49. err db 'пререполнение',0
    50. buffer db 20 dup (0)
    51. q1 dd 0FFF00001h
    52. format db 'остаток через div  %08Xh',0Ah,'частное через div %08Xh',0Ah
    53. db '------------------------',0Ah
    54. db 'остаток через сдвиги %08Xh',0Ah,'частное через сдвиги %08Xh',0
    55. x dq XXXXXXXXXXXXXXXXh
    56. y dd YYYYYYYYh
    57. end start
    Еще один вариант здесь.
    max7C4
    Хотелось бы увидеть ваш вариант из #4 целиком, хотябы в псевдокоде, или алгоритм на словах, или ссылочку на алгоритм
     
  12. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    обычное деление в столбик приведенное к двоичному виду и активно использующее cf в качестве буфера, но я там кое-что не дописал (это что-бы человек разобрался), а кое-что изменил (это на внимательность).
     
  13. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Mikl___
    Но можно поинтересоваться. Вы случайно не not esi/not edi испугались (раз интересуетесь)?
     
  14. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    max7C4
    Нет, собираю коллекцию :) К сожалению, ваш полный вариант делит не совсем корректно. Ещё один вариант
    Код (Text):
    1. .686P
    2. .model flat
    3. include windows.inc
    4. includelib user32.lib
    5. extern _imp__wsprintfA:dword
    6. extern _imp__MessageBoxA@16:dword
    7. .code
    8. start:  xor ebx,ebx
    9.     mov ecx,y
    10.     jecxz a3
    11.     inc ebx
    12.     mov edx,dword ptr q+4
    13.     cmp edx,ecx
    14.     jae a3
    15.     mov eax,dword ptr q
    16.     xor edi,edi
    17.     mov esi,80000000h
    18.     inc ebx
    19. a0: shld edx,eax,1
    20.     jc a1
    21.     cmp edx,ecx
    22.     jb a2
    23. a1: add edi,esi
    24.     sub edx,ecx
    25. a2: shl eax,1
    26.     shr esi,1
    27.     jnz a0
    28.     push edi;частное в edi
    29.     push edx;остаток в edx
    30.     mov edx,dword ptr q+4
    31.     mov eax,dword ptr q
    32.     div ecx;проверяем
    33.     push eax;частное в eax
    34.     push edx;остаток в edx
    35.         push offset format
    36.         push offset buffer 
    37.     call _imp__wsprintfA
    38.     add esp,4*6;корректируем стек
    39. a3: push MB_OK
    40.     push offset MsgCaption
    41.     push [ebx*4+msg]
    42.     push 0
    43.     call _imp__MessageBoxA@16
    44.     ret
    45. MsgCaption db "Div",0
    46. buffer db 20 dup (0)
    47.  q dq 0AABCD40008000000h
    48.  y dd 0FEDCBA87h
    49. format db 'остаток через div  %08Xh',0Ah,'частное через div %08Xh',0Ah
    50. db '------------------------',0Ah
    51. db 'остаток через сдвиги %08Xh',0Ah,'частное через сдвиги %08Xh',0
    52. err1 db 'деление на 0',0
    53. err2 db 'переполнение',0
    54. msg dd err1,err2,buffer
    55. end start
     
  15. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Mikl___
    ну вы поменяйте shld на shl/rcl, а то как я посмотрел (потом) она нижнюю часть не изменяет. и все будет путем