Hello! Приведу цитату из книги "Изучаем Ассемблер - Крупник А.Б.": Задача 5-10. Напишите процедуру деления 64-битового числа, хранящегося в двух регистрах, на произвольное число. Подсказка: вспомните деление -«столбиком» десятичных чисел. Довольно долго уже голову ломаю! Как это сделать??? Помогите кто знает! ЗЫ, всякие специальные для этого команды не предлагать!
А в чем проблема? Если совсем по-простому, берем делимое и вычитаем из него делитель до тех пор, пока не останется значение, меньше делителя. Это наш остаток. В цикле вычитания считаем, сколько раз мы вычли делитель из делимого. Это целая часть. Если используется 32битный режим процессора, то для вычитания есть смысл воспользоваться командой sbb. Столбиком чуть сложнее (но быстрее), и полно примеров в интернете.
Сравниваем старшие разряды делимого с делителем, если больше или равно -- вычитаем из них делитель, пишем единицу в частное; если меньше -- пишем нуль в частное. После этого сдвигаемся на один разряд вправо (относительно делимого), опять сравниваем... ну и так далее до конца В точности, как при ручном делении в столбик, с той лишь разницей, что при делении десятичных чисел надо ещё установить конкретную цифру частного, а здесь их всего две -- 0 или 1.
Код (Text): mov eax, dword [x+0] mov edx, dword [x+4] mov ebx, dword [y+0] xor ecx, 64 xor ebp, ebp xor edi, edi xor esi, esi @@: clc rcl eax, 1 shl edx, 1 ; две предыдущие команды можно заменить shld rcl ebp, 1 cmp ecx, ebx rcl esi, 1 rcl edi, 1 loop @b not esi not edi mov dword [r+0], esi mov dword [r+4], edi ... x dq XXXXXXXXXXXX y dd YYYYYYYYYYYY r dq ?
вот только не надо думать что тебе дали законченный код. тебя лишь пнули в нужную сторону. поймешь принцип - сможешь закончить, не поймешь - забей.
CtrlAltDel Задача 5-10. Напишите процедуру деления 64-битового числа, хранящегося в двух регистрах, на произвольное число. - если следовать строго этому, загрузите делимое (64 бита) в регистры EDX:EAX, делитель в любой 32-х битный РОН (или в память) и делите на здоровье, к примеру, командой, Div EBX (если делитель помещен в EBX). Чтобы не напороться на переполнение, делаем проверку содержимого EDX & EBX.
Если требуется разделить 64-битное на 32-битное Код (Text): ; EDX - HIDWORD ; EAX - LODWORD ; ECX - DIVIDER DIV ECX Если требуется разделить n-dword'ное на 32-битное Формат структур, на которые указывают параметры lpArg и lpRes: [DWORD: число DWORD'ов в записи числа; <данные>] Код (Text): Divide proc USES EDI ESI, lpArg:DWORD, nDiv:DWORD, lpRes:DWORD MOV ESI, lpArg MOV EDI, lpRes MOV EBX, nDiv MOV ECX, [ESI] MOV [EDI], ECX LEA EAX, [ECX*4] ADD ESI, EAX ADD EDI, EAX PUSH EDI STD XOR EDX, EDX @loop: LODSD DIV EBX STOSD LOOP @loop POP EAX CMP DWORD PTR [EAX], 0 JNE @F DEC DWORD PTR [EDI] @@: CLD RET Divide Endp А вот как разделить n-битное на m-битное без остатка пока что я не понимаю. ( вычитание не предлагать - числа большие ).
CtrlAltDel Код (Text): .model flat include windows.inc includelib user32.lib extern _imp__wsprintfA:dword extern _imp__MessageBoxA@16:dword .code start: mov edx,dword ptr x+4 mov ebx,y cmp edx,ebx ja overflow mov eax,dword ptr x mov esi,80000000h xor edi,edi xor ebp,ebp a0: shrd ebp,ebx,1 shr ebx,1 cmp edx,ebx jb a2 jne a1 cmp eax,ebp jb a2 a1: sub eax,ebp sbb edx,ebx add edi,esi a2: shr esi,1 jnz a0 push edi;частное push eax;остаток mov edx,dword ptr x+4 mov eax,dword ptr x mov ebx,y div ebx; проверка push eax;частное push edx;остаток mov ebx,offset buffer push offset format push ebx call _imp__wsprintfA add esp,4*6;корректируем стек jmp short a3 overflow: mov ebx,offset err a3: push MB_OK push offset MsgCaption push ebx push 0 call _imp__MessageBoxA@16 ret MsgCaption db "div",0 err db 'пререполнение',0 buffer db 20 dup (0) q1 dd 0FFF00001h format db 'остаток через div %08Xh',0Ah,'частное через div %08Xh',0Ah db '------------------------',0Ah db 'остаток через сдвиги %08Xh',0Ah,'частное через сдвиги %08Xh',0 x dq XXXXXXXXXXXXXXXXh y dd YYYYYYYYh end start Еще один вариант здесь. max7C4 Хотелось бы увидеть ваш вариант из #4 целиком, хотябы в псевдокоде, или алгоритм на словах, или ссылочку на алгоритм
обычное деление в столбик приведенное к двоичному виду и активно использующее cf в качестве буфера, но я там кое-что не дописал (это что-бы человек разобрался), а кое-что изменил (это на внимательность).
max7C4 Нет, собираю коллекцию К сожалению, ваш полный вариант делит не совсем корректно. Ещё один вариант Код (Text): .686P .model flat include windows.inc includelib user32.lib extern _imp__wsprintfA:dword extern _imp__MessageBoxA@16:dword .code start: xor ebx,ebx mov ecx,y jecxz a3 inc ebx mov edx,dword ptr q+4 cmp edx,ecx jae a3 mov eax,dword ptr q xor edi,edi mov esi,80000000h inc ebx a0: shld edx,eax,1 jc a1 cmp edx,ecx jb a2 a1: add edi,esi sub edx,ecx a2: shl eax,1 shr esi,1 jnz a0 push edi;частное в edi push edx;остаток в edx mov edx,dword ptr q+4 mov eax,dword ptr q div ecx;проверяем push eax;частное в eax push edx;остаток в edx push offset format push offset buffer call _imp__wsprintfA add esp,4*6;корректируем стек a3: push MB_OK push offset MsgCaption push [ebx*4+msg] push 0 call _imp__MessageBoxA@16 ret MsgCaption db "Div",0 buffer db 20 dup (0) q dq 0AABCD40008000000h y dd 0FEDCBA87h format db 'остаток через div %08Xh',0Ah,'частное через div %08Xh',0Ah db '------------------------',0Ah db 'остаток через сдвиги %08Xh',0Ah,'частное через сдвиги %08Xh',0 err1 db 'деление на 0',0 err2 db 'переполнение',0 msg dd err1,err2,buffer end start
Mikl___ ну вы поменяйте shld на shl/rcl, а то как я посмотрел (потом) она нижнюю часть не изменяет. и все будет путем