Деление N-разрядного беззнакового
Деление N-разрядного беззнакового целого BCD-числа на одноразрядное BCD-число размером 1 байт (макрокоманда)
div_bcd_l_r macro u.N.v.w.r local ml
:div_bcd_l_r u.N.v.w.r - деление N-разрядного беззнакового целого BCD-числа
;на одноразрядное BCD-число размером 1 байт. :Вход: и - делимое; N - длина делимого, v - делитель. :Выход: w - частное, г - остаток. :Порядок следования байтов - старший байт по младшему адресу (не Intel) (!).
mov г.О
lea si.u ;j=0
хог di.di :j=0
mov cx.N
xor dx.dx
xor bx.bx
ml: mov ah,г
mov al.[si]
aaJ
div v сформировать результат:
mov w[di].al ;частное
mov r.ah .-остаток в г
inc si
inc di
loop ml
:если нужно - получим модуль (уберите знаки комментария)
: mov cx.N ;длина операнда
: lea bx.w
; call calc_abs_r
endm
Деление неупакованных BCD-чисел
:div_bcd_NM_r.asm - деление неупакованных BCD-чисел и и v размером n+m и п байт.
;Вход: и-и^гиз-.и,^,, - делимое: v=v1v2...vn - делитель. Ь=25б - основание системы счисления.
;Выход: q™q1q2-.qm - частное. r=rir2...rn - остаток,
:Порядок следования байт - старший байт по младшему адресу (не Intel) (!).
.data значения в и и v нужно внести
uO db 0 дополнительный байт для нормализации
u db 1,0.3.5,9,4,6 :делимое
m=$-u :длина в байтах значения и
vO db 0 :для сложения OvjV2..vn
v do 5.9.1 :делитель
n=$-v :длина в байтах значения v
ГПП1=П1-П
w db m+1 ctup (0) :для промежуточных вычислений q db mm dup (0) :частное qq db 0
г db n dup (0) :остаток
b dw 10 юснование системы счисления
d db 0
temp dw 0
temp_r db n dup (0)
borrow db 0 :факт заема на шаге D4
k db 0 ;перенос 0 =< k < 255
carry db 0
.code
:вставить описание макрокоманд calc_complement_r. mul_bcd_r. sub_bcd_r. add_bcd_r. :div_bcd_l_r
div_bcd_NM_r proc ;D1 - нормализация
xor ax.ax
mov dl.v
inc dl :vl+l
mov ax.b
div dl
mov d.al :d=b/(v1+l)
mul_bcd_r u.m.d.l.w
eld
push ds
pop es
lea si.w
lea di.uO
mov cx.m+1 rep movsb
mul_bcd_r v.n.d.l.w
eld
push ds
pop es
lea si.w+1
lea di.v
mov ex,n rep movsb :D2:
mov si.O ;n=0 :D3: @@m7: moval.uO[si]
emp v,al
jne @@ml
mov qq.9 :qq=b-l
jmp @@m2
(<t@ml: xor ax,ax
mov al.uO[si]
mul b
xor dx.dx
mov dl,uO[si+l]
add ax.dx
mov bl.v ;v->bx divbl
mov qq.al
@@m2: :проверим выполнение неравенства:
@@m4: mul v+1
mov temp. ax: taiip=v2*qq
xor ax.ax
mov al ,uO[si]
mul b
xor edx.edx
mov dl.uO[si+l] add dx.ax
mov al.qq
mul v :eax=qq*vl
sub dx,ax
xchg dx.ax
mul b
xor bx.bx
mov bl.uO[si+2]
add ax.bx
cmp temp,ax
jna (a@m3
dec qq
mov al.qq
jmp @@m4
@@m3: : D4
mul_bcd_r v.n.qq.l.w
mov bx.si
push si
sub_bcd_r uO[bx].<n+l>.w,<n+l>,uO[bx] ;v<->w
jnc @@m5 :переход, если нет заема (результат положительный)
mov borrow.1 ;запоминаем факт заема, получаем дополнение
pop si ;D5
@@m5: moval.qq
mov q[si].al
cmp borrow.1 : был заем на шаге D4 ??
jne @@m6 :D6 - компенсирующее сложение
mov borrow.0 :сбросин факт заема
dec q[si]
mov bx.si
push si
add_bcd_r uO[bx].<n+l>.vO,<n+l>,uO ;перенос не нужен :D7
@@m6: pop si
inc si
cmp si.mm
jle @@m7 :D8 - денормализация
mov bx.si
div_bcd_l_r uO[bx],N,d.r.temp_r
ret
div_bcd_NM_r endp *
main:
call div_bcd_NM_r end main
Упакованные BCD-числа
В отличие от неупакованных BCD-чисел, разработчики команд микропроцессора Intel весьма сдержанно отнеслись к проблеме обработки упакованных BCD-чисел. Существуют только две команды — DAA и DAS, которые поддерживают процесс сложения и вычитания упакованных BCD-чисел. Умножение и деление этих чисел не поддерживается вовсе. По этой причине при необходимости выполнения арифметических вычислений с упакованными BCD-числами есть смысл предварительно преобразовывать их в неупакованное представление, выполнять необходимые действия, результат которых конвертировать (если нужно) обратно в упакованный вид. Так как действия по преобразованию не являются основными в процессе вычислений, то желательно, чтобы они были максимально быстрыми. Можно предложить много вариантов подобного преобразования. Рассмотрим один из них.