Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the forum
Board view  Mix view

New version DRDOS 7.01.7 & 7.01.8 (Announce)

posted by ecm Homepage E-mail, Düsseldorf, Germany, 14.12.2023, 20:58

> > You can convert the code below for Int64 to Int32 and replace the 32-bit
> > registers with 16-bit registers to skip the 32-time loop.
>
> Thanks for the code. I can not convert it one by one, because the DRSYS
> div32 procedure also returns the remainder, but I get the idea...
>
> However, for now I decided to leave the shifting algorithm as it is, mainly
> because it is a code path not often taken, and i want to fix more things
> than I break :-D
>
> The div32 procedure is mainly called with 512 as the divisor (to calculate
> sectors and offsets into the FAT). So 99% of the time, the optimized 16-bit
> shortcut is used, I guess.
>
> The current version is here:
> https://github.com/SvarDOS/edrdos/blob/8fa1acd6576...9fd7f283a9119e3494036ce7/drdos/bdevio.a86#L2029
>
> It should yield correct results (kernel behaves as expected). But perhaps
> someone with more assembly experience might double-check (from div32_full
> on it is the original code).


div32:                                    ; 32-bit division
;--------
; On Entry:
;       32-bit dividend & divisor on stack
;       space for 32-bit quotient & remainder reserved on stack
;       SP-16
; On Exit:
;       32-bit quotient & remainder on stack
;       SP-16
; Modified registers:
;       AX,CX,DX,BP
        mov     bp,sp                   ; base address of temporary variables
        add     bp,2


Twice `inc bp` is cheaper in code space.

  xor     dx,dx
        cmp     10[bp],dx               ; if divisor high != 0 => 32bit div
         jne    div32_full
        mov     cx,8[bp]                ; CX <- divisor low
        mov     2[bp],dx                ; clear remainder high, guaranteed to
                                        ; ...be zero here
        mov     ax,14[bp]               ; AX <- dividend high
        test    ax,ax                   ; if both dividend and divisor are
                                        ; ...16bit, perform one 16bit division
         jz     div16                   ; ...else perform two 16bit divisions
dix2x16:
        div     cx                      ; divide dividend high by divisor low
div16:  mov     6[bp],ax                ; 6[bp] <- quotient high
        mov     ax,12[bp]               ; AX <- dividend low
        div     cx                      ; divide dividend low by divisor low
                                        ; ...DX -> remainder of previous
                                        ; ...      division or zero
        mov     [bp],dx                 ; store remainder low
        mov     4[bp],ax                ; store quotient low
        ret
div32_full:


Looks good to me. Dispatching to either the two-step division or a single one is new to me. I do think you could save code space at the cost of some performance by just dropping the test and jz. Zero divided by CX is always zero.

---
l

 

Complete thread:

Back to the forum
Board view  Mix view
22049 Postings in 2034 Threads, 396 registered users, 275 users online (0 registered, 275 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum