Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the forum
Board view  Mix view

not setting carry (Developers)

posted by ecm Homepage E-mail, Düsseldorf, Germany, 17.10.2025, 09:30

> > To ensure that these odd "error codes" are detected properly, callers
> > should ensure to stc before the int 21h call. Int 21h hooks
> > ideally should preserve this Carry Flag status when chaining or calling
> > their downlinks.
> >
> > Unfortunately, this isn't properly documented much, including in the
> > Interrupt List.
>
> As you indicate, "ideally" INT 21h chains should preserve ALL flags (not
> just Carry) when passing though, and when using CF as a return flag should
> preserve ALL flags except Carry. This means NOT simply issuing a STC/CLC
> followed by a RETF 2 (I've seen that done) at the end of the handler but
> instead manipulating the the Carry bit in the Flags register (on the stack)
> for the return. This is important because an Interrupt call also
> manipulates the Interrupt flag for entry into the Interrupt handler and you
> definitely want to preserve the callers Interrupt flag on the return. The
> other really critical Flag you absolutely don't want to mess with is the
> Direction flag.

I agree. Unfortunately, ROM-BIOS routines that may modify CF often return with code like sti followed by retf 2. Another flag that should be preserved is the Trace Flag.

Here's some example code that returns all the arithmetic status flags other than the Overflow Flag, but preserves all the control flags (IF, DF, TF):

entry     Leave13         ; for msbio/ms96tpi.nas and msbio/msdisk.nas
entry   Leave2F
        push bp
        mov bp, sp
        push ax
        lahf
; bp + 0 = saved bp
; bp + 2 = ip
; bp + 4 = cs
; bp + 6 = fl
        mov byte [bp + 6], ah
        pop ax
        pop bp
        iret


And here's code that returns only the Carry Flag, preserving all others:


.iret_CF:
        push bp
        mov bp, sp
        rcr byte [bp + 6], 1    ; flip
        rol byte [bp + 6], 1    ; flop
        pop bp
        iret



> When issuing a call that uses CF for the return, the caller should always
> set CF before the call in case of incompatibility, and set the values of
> the return registers (if there are any) to some value that should never be
> returned by the handling routine.
>
> That's all just good programming practice.

I agree. As an example, when I call int 21h function 3306h (MS-DOS v5+ "get true version") I set up bx as zero before the call:


        xor bx, bx
        mov ax, 3306h   ; get real DOS version
        int 21h


In the same program I call the FreeDOS-originated extension call int 21h function 33FFh. It doesn't have a clear success indicator, so I prepare dx as zero and expect a non-zero returned segment in dx if the call is supported:


        mov ax,33ffh    ; get FreeDOS version string pointer
        xor dx, dx
        int 21h         ; returns DX AX
        test dx, dx
        jnz gotname
        mov dx, ds
        mov ax, msgnoname
gotname:


In MSDebug I also set bx to zero for the 3306h call.

---
l

 

Complete thread:

Back to the forum
Board view  Mix view
22747 Postings in 2119 Threads, 402 registered users, 412 users online (1 registered, 411 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum