div 8086 nasm

Gast #6514469
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
Gast #6514479
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/
Gast #6514496
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
Gast #6514501
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
Gast #6514504
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?
Gast #6514518
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
Gast #6514577
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
...
Gast #6514626
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 :)
(Firma: Funkenflug Industries) #6515598
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.
Gast #6516597
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.
Gast #6516976
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 ;)
Gast #6517017
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
(Firma: Funkenflug Industries) #6517227
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren