Forum: PC-Programmierung div 8086 nasm


von Booter (Gast)


Lesenswert?

Dear all

What got I wrong about unsigned division in 8086 assembler?
Why it work only for dividend high part equal zero?

Nasm 2.15.05 code:
1
[ bits  16]
2
[ cpu   8086]
3
[ org   0x7c00]           ; qemu and real hw      same results
4
;[ org   0x100]            ; dosbox                for both
5
  mov   ax, 0x2143        ; dividend low
6
  mov   dx, 0x6587        ; dividend high         doesn't work
7
;  mov   dx, 0             ;                       works fine
8
  mov   cx, 0x10          ; divisior
9
  div   cx                ; 0x21436587 / 0x10 = quot=ax=0x2 rem=dx=1
10
  mov   al, ah            ; al=0x2='☻' (CP437)
11
  mov   ah, 0xe           ; terminal output
12
  int   0x10              ; bios
13
  jmp   $                 ; end
14
  times 0x1fe-$+$$ db 0   ; zero fill
15
  dw    0xaa55            ; MBR signature
Listing
1
     1                                  [ bits  16]
2
     2                                  [ cpu   8086]
3
     3                                  [ org   0x7c00]
4
     4                                  ;[ org   0x100]
5
     5 00000000 B84321                    mov   ax, 0x2143
6
     6 00000003 BA8765                    mov   dx, 0x6587
7
     7                                  ;  mov   dx, 0
8
     8 00000006 B91000                    mov   cx, 0x10
9
     9 00000009 F7F1                      div   cx
10
    10 0000000B 88E0                      mov   al, ah
11
    11 0000000D B40E                      mov   ah, 0xe
12
    12 0000000F CD10                      int   0x10
13
    13 00000011 EBFE                      jmp   $
14
    14 00000013 00<rep 1EBh>              times 0x1fe-$+$$ db 0
15
    15 000001FE 55AA                      dw    0xaa55

von cppbert3 (Gast)


Lesenswert?

1
mov dx,0
2
mov ax,64000 ; ax is set to 0xFA00
3
mov cx,10
4
mul cx ; dx:ax is set to 0x9C400 or 640000 decimal, dx is 0x0009, ax is 0xC400
5
div cx ; dx:ax is set to 0x0FA00 or 64000 decimal, dx is 0, ax is 0xFA00

its absolutely not clear "what" doesn't work, the div and mul operationa 
are working as documented

https://c9x.me/x86/html/file_module_x86_id_72.html
https://carlosrafaelgn.com.br/asm86/

von cppbert3 (Gast)


Lesenswert?

It is dx:ax not ax:dx, your number is not correctly splitted in 
hight,low part, the dx value (high) comes first

von cppbert3 (Gast)


Lesenswert?

this couldn't be in the result, in any way
1
0x21436587 / 0x10 = quot=ax=0x2 rem=dx=1

von Booter (Gast)


Lesenswert?

cppbert3 schrieb:
> this couldn't be in the result, in any way
> 0x21436587 / 0x10 = quot=ax=0x2 rem=dx=1

Typo, thanks.
1
0x21436587 / 0x10 = quot=ah=0x2 rem=dx=1

cppbert3 schrieb:
> its absolutely not clear "what" doesn't work, the div and mul operationa
> are working as documented

It just stops working (no output at all).

And what's the use of that stuff when I have to multiply first with the 
number I divide with right after? Confusion -> Inf

von cppbert3 (Gast)


Lesenswert?

Btw: dosbox got an builtin debugger (not in the default release) so you 
dont need to print your results, just watch the registers change, step 
by step

https://www.vogons.org/viewtopic.php?f=32&t=7323

von cppbert3 (Gast)


Lesenswert?

Booter schrieb:
> Typo, thanks.0x21436587 / 0x10 = quot=ah=0x2 rem=dx=1

What do you think is the correct result? Tip: its much much larger than 
0x2 :)

Booter schrieb:
> It just stops working (no output at all).

Because your registers are absolutely not in the value range you expect

Booter schrieb:
> And what's the use of that stuff when I have to multiply first with the
> number I divide with right after? Confusion -> Inf

Its just an small example how mul,div works - nothing more

von cppbert3 (Gast)


Lesenswert?

Your dx:ax understanding is not correct, you whole "algorithm" seems to 
be crippled, partly in code and your comments, also your al,ah usage 
before int 0x10

Beside assembler code, what are you try to archive with this code block?

von Booter (Gast)


Lesenswert?

What is it if not
1
0x1000*dx+ax
2
------------ = ax rem dx
3
     cx

cppbert3 schrieb:
> Beside assembler code, what are you try to archive with this code block?

Actually it's a bug in my version of U/ ( ud u1 --- rem quot ) from the 
fig-FORTH Model

s is data stack, pop adds two to s and jumps to next
1
  db    0x82, "u/", 0x80  ; NF
2
  dw    $abs              ; LF
3
u_slash:
4
  dw    u_slash+2         ; CF
5
  mov   bx, [s]           ; PF
6
  mov   ax, [bx+4]
7
  mov   dx, [bx+2]
8
  div   word [bx]
9
  mov   [bx+4], dx
10
  mov   [bx+2], ax
11
  jmp   pop

von cppbert3 (Gast)


Lesenswert?

1
EAX: 22 33 55 77
2
 AX:       55 77
3
 AH:       55    
4
 AL:          77
5
6
DX:AX: 66 88 55 77
7
   AX:       55 77
8
   DX: 66 88

von cppbert3 (Gast)


Lesenswert?

and your result quotient needs to fit in ax - that seems not the case, 
so get a "Division quotient overflow"

https://stackoverflow.com/questions/53915057/overflow-in-division-in-assembly8086/53916372

von Booter (Gast)


Lesenswert?

cppbert3 schrieb:
> "Division quotient overflow"

Thank you allot for connecting the dots (and setting the next). :)

So it's:
1
0x10000*dx+ax
2
------------- = ax rem dx,  cx≠0 ∧ cx≥dx
3
     cx
1
mov dx, [high_dividend]
2
mov ax, [low_dividend]
3
mov cx, [divisor]
4
clc
5
cmp dx, cx
6
jnb div_error
7
div cx
8
mov [quotient], ax
9
mov [remainder], dx
10
jmp next
11
div_error:
12
...

von cppbert3 (Gast)


Lesenswert?

Booter schrieb:
> cppbert3 schrieb:
>> "Division quotient overflow"
>
> Thank you allot for connecting the dots (and setting the next). :)
>
> So it's:0x10000*dx+ax
> ------------- = ax rem dx,  cx≠0 ∧ cx≥dx
>      cx
> mov dx, [high_dividend]
> mov ax, [low_dividend]
> ...

better now :)

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

The nice thing about assembler is that you can easily work around such 
incapabilities by using various methods. A division by 10h is nothing 
more than a 4-bit shift to the right (even if it might be slower on 
modern CPUs when you need to use more instructions), a division by 100h 
can easily be done by splitting registers (AX into AH and AL as AH 
contais already the result and AL the reminder without actually 
executing the division).

And if your processor is 32 bit (not 16 only) use it.

von rbx (Gast)


Lesenswert?

Booter schrieb:
> What got I wrong about unsigned division in 8086 assembler?
> Why it work only for dividend high part equal zero?

Nothing. This is just the way to do it. For some "deeper" look of view 
you  have to ask Intel-Developers why you have to set dx explicitly to 
0.

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

You don't have to set DX to zero, you have to set it low enough, that 
the result of the division (by 16) fits in AX.

That's why I suggested to execute this DIV operation by bitshifting or 
as 32 bit operation if the processor is able to.

von rbx (Gast)


Lesenswert?

Ben B. schrieb:
> You don't have to set DX to zero, you have to set it low enough, that
> the result of the division (by 16) fits in AX.

Are you Intel-Developer? But you are right. It could be sufficient, to 
set dh to 0 - but some more testing and gaming with numbers will give 
some more safety about this case ;)

von cppbert3 (Gast)


Lesenswert?

rbx schrieb:
> Ben B. schrieb:
> You don't have to set DX to zero, you have to set it low enough, that
> the result of the division (by 16) fits in AX.
>
> Are you Intel-Developer? But you are right. It could be sufficient, to
> set dh to 0 - but some more testing and gaming with numbers will give
> some more safety about this case ;)

Its fully and overly well documented for at least 40 years now, 
absolutely no need to talk to intel developers or gaming with numbers

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

There is no gaming. As a DIV by 10h is nothing more than a 4-bit shift 
and the maximum result to fit in AX is 0xFFFFh, the maximum number you 
can divide is 0xFFFFF, or DX:AX 0x000F:0xFFFF - will give you AX 0xFFFF 
as result and DX 0x000F as reminder. DX bigger than 0x000F will result 
in the error described.

If you need more you can perform this operation as 32-bit operation or 
you need to work around the problem as I described before.

> mov   ax, 0x2143        ; dividend low
> mov   dx, 0x6587        ; dividend high
> mov   cx, 0x10          ; divisior
> div   cx

MOV EAX,0x65872143
XOR EDX,EDX
MOV ECX,0x10
DIV ECX             ; result in EAX, reminder in EDX

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.