The MASM Forum Archive 2004 to 2012

Miscellaneous Forums => 16 bit DOS Programming => Topic started by: carlottagp on June 19, 2008, 03:57:54 PM

Title: Printing to file with INT 21h Function 40h
Post by: carlottagp on June 19, 2008, 03:57:54 PM
I have two number arrays to be printed to a file.  If I use SI and BP as the pointers to the
arrays, and DI as the pointer to the buffer, no problem.  But if I use BP as the buffer
pointer, and SI and DI as the two array pointers, nothing is printed.  The buffer exists
after I've loaded it, as I have confirmed on the screen, but it won't print to file.

Is there some constraint on using BP that I've overlooked?

Thanks for your advice/comments.

Michael
Title: Re: Printing to file with INT 21h Function 40h
Post by: MichaelW on June 21, 2008, 06:09:49 AM
With so little information it's impossible to know what the problem might be. Given a valid file handle in BX, a valid buffer address in DS:DX, a valid byte count in CX, and assuming that the file is accessible, the Write File or Device function should succeed in writing to the file. If the function is returning with the carry flag set, then the function failed and AX should contain an error code.
Title: Re: Printing to file with INT 21h Function 40h
Post by: sinsi on June 21, 2008, 07:01:58 AM
How are you using BP? Don't forget that without a segment override, the byte (or whatever) at [BP] is actually at SS:[BP], not DS:[BP].

Quote from: MichaelW on June 21, 2008, 06:09:49 AM
With so little information it's impossible to know what the problem might be.
Agreed - post a bit of code, then we can try and help you without resorting to reading your mind. :lol
Title: Re: Printing to file with INT 21h Function 40h
Post by: carlottagp on June 21, 2008, 11:28:08 AM
Thanks for the  answers to my question.  I was using BP in an efort to minimize the number of lines
in the code.  (If I use DI for one of my data arrays and also for the buffer, there will have to be
some PUSHing and POPping - and some additional ofset adjustments -  while transferring each number
pair to the buffer.)

I will check into the segment override scenario.   If BP is defined with respect to SS,
not DS, then I don't understand why I was able to verify the status of the buffer using a few lines
of (diagnostic)  code to show the data on the screen, without the segment override you referred to.

Thanks for your help.

Michael
Title: Re: Printing to file with INT 21h Function 40h
Post by: sinsi on June 21, 2008, 11:36:02 AM
Quote from: carlottagp on June 21, 2008, 11:28:08 AM... using a few lines of (diagnostic)  code ...
So what code? Help us out, we can help you too.
Title: Re: Printing to file with INT 21h Function 40h
Post by: MichaelW on June 21, 2008, 07:17:14 PM
Quote from: carlottagp on June 21, 2008, 11:28:08 AM
If BP is defined with respect to SS, not DS, then I don't understand why I was able to verify the status of the buffer using a few lines of (diagnostic)  code to show the data on the screen, without the segment override you referred to.

Indirect memory operands that specify BP cause the instruction to use SS instead of DS, the default segment for most instructions that access memory. For the TINY memory model or code that uses the .STARTUP directive, this distinction does not matter because SS==DS.
Title: Re: Printing to file with INT 21h Function 40h
Post by: carlottagp on June 23, 2008, 01:36:56 PM

"... using a few lines of (diagnostic)  code ...
So what code? Help us out, we can help you too."

I have a simple subroutine which shows BX on the screen, so I just copied each byte of the buffer to BL and
called the subroutine. 

Rather than getting into a "segment override", which I'm afraid I don't understand, can I use BX for the index of the
buffer, rather than BP?

Thanks again,

Michael
Title: Re: Printing to file with INT 21h Function 40h
Post by: sinsi on June 26, 2008, 06:02:31 AM
Some instructions 'assume' a segment register
- lods assumes DS:SI
- stos assumes ES:DI
- mov [sp],x / mov x,[sp] assumes SS:SP
- mov [bp],x / mov x,[bp] assumes SS:BP

So code like 'mov ax,[bp]' looks to the CPU as 'mov ax,ss:[bp]'. This isn't a problem with a .com file, because (unless you change segment registers) DS=SS,
which means SS:BP is (coincidentally) DS:BP. In a .exe file, there is usually a seperate stack, which means SS is not the same as DS. In that case, you need to override
the assumed segment register (SS) with 'mov ax,ds:[bp]'.

Using BX,SI and DI 'assumes' that it's DS - it's only BP that assumes SS.

Title: Re: Printing to file with INT 21h Function 40h
Post by: MichaelW on June 26, 2008, 04:10:03 PM
For an EXE you can use the .startup directive, or equivalent code.

.startup
0000    *@Startup:
0000  B8 ---- R    *     mov    ax, DGROUP
0003  8E D8    *     mov    ds, ax
0005  8C D3    *     mov    bx, ss
0007  2B D8    *     sub    bx, ax
0009  C1 E3 04    *     shl    bx, 004h
000C  8E D0    *     mov    ss, ax
000E  03 E3    *     add    sp, bx


This effectively moves the stack to the end of DGROUP by setting DS and SS to DGROUP and adding the size of the data segment, in bytes, to SP.