What is the rationale behind the constant return value for DOS int 21 / AH=9? (print string interrupt)

Viewed 181

I was looking at the specifications for DOS int 21h interrupts here http://spike.scu.edu.au/~barry/interrupts.html

I don't know much about assembly, but it seems like the AL register is the standard to store return values from an interrupt. For instance, service 01h (read character) stores the character read there. And service 02h (write character to stdout) stores the last character output there.

But when it comes to AH=09h (write string to stdout) the return value is ALWAYS 24h. Why is that?

First I thought that SOME value has to be set for some technical reason, but that does not seem to be the case. There are lots of DOS services that don't specify a return value at all. And some store the return value in other registers, such as 2Ch (get system time) which instead stores the result in CH, CL, DH and DL registers instead of AL.

So why does interrupt service AH=09h store a value in AL? And why 24h?

2 Answers

Just for a few more details:

You can see here the source code for this system call in MS-DOS v1.25:

PRTBUF: ;System call 9
        MOV     SI,DX
OUTSTR:
        LODSB
        CMP     AL,"$"
        JZ      RET20
        CALL    OUT
        JMP     SHORT OUTSTR

It uses the LODSB instruction in a loop to load bytes from the string, compare them against $, and write them out. Since LODSB is hard-wired to load into AL, and the loop terminates when $ is seen, that's what's left in AL.

The DOS API specified that AX need not be preserved by system calls (see MS-DOS Programmer's Reference Manual, 1.10.4, "Treatment of Registers"), and the return value from service 09h is just described as "None". So there is no documented guarantee as to what AL should contain on exit; its contents are simply unspecified. Other versions of DOS may have behaved differently, so you obviously should not rely on such behavior.

@Jester did a very good observation. 24h is the ascii code for $, and the service 09h is expecting a $-terminated string. Compare to the service 02h that prints the last character to the output, and this character ends up in AL. And now we're talking about a function that prints a $-terminated string, and leaves $ in the AL register.

This hypothesis would also explain why the official documentation doesn't specify any return value for that interrupt. It's not a part of the specification, but just a result of the inner workings.

So while I (or Jester) cannot say for certain that there is no thought behind this, this explanation makes a lot of sense.

And as @ecm pointed out. It's not "interrupt 09h". It's "interrupt 21h service 09h".

Related