not setting carry (Developers)
> > 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:
- not setting carry - kerravon, 16.10.2025, 10:29
![Open in board view [Board]](img/board_d.gif)
![Open in mix view [Mix]](img/mix_d.gif)
- not setting carry - ecm, 16.10.2025, 16:17
- not setting carry - bretjohn, 16.10.2025, 23:59
- not setting carry - ecm, 17.10.2025, 09:30
- not setting carry - kerravon, 17.10.2025, 07:58
- not setting carry - ecm, 17.10.2025, 10:29
- not setting carry - kerravon, 17.10.2025, 10:55
- not setting carry - ecm, 17.10.2025, 11:31
- not setting carry - kerravon, 17.10.2025, 16:51
- not setting carry - ecm, 17.10.2025, 18:43
- not setting carry - kerravon, 17.10.2025, 19:05
- not setting carry - ecm, 17.10.2025, 18:43
- not setting carry - kerravon, 17.10.2025, 16:51
- not setting carry - ecm, 17.10.2025, 11:31
- not setting carry - kerravon, 17.10.2025, 10:55
- not setting carry - ecm, 17.10.2025, 10:29
- not setting carry - bretjohn, 16.10.2025, 23:59
- not setting carry - ecm, 16.10.2025, 16:17
Mix view