Printing to file with INT 21h Function 40h

Started by carlottagp, June 19, 2008, 03:57:54 PM

Previous topic - Next topic

carlottagp

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

MichaelW

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.
eschew obfuscation

sinsi

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
Light travels faster than sound, that's why some people seem bright until you hear them.

carlottagp

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

sinsi

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.
Light travels faster than sound, that's why some people seem bright until you hear them.

MichaelW

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.
eschew obfuscation

carlottagp


"... 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

sinsi

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.

Light travels faster than sound, that's why some people seem bright until you hear them.

MichaelW

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.
eschew obfuscation