When is DGROUP/@data required to set up ds?

Started by allynm, May 02, 2011, 10:34:21 PM

Previous topic - Next topic

allynm

Hello everyone,

I'm a 16 bit novice and I'm searching for an explanation to the following problem.  I'm using full segment definitions and using c functions linked with Borland 2.01 library (c0l.obj, cl.lib) and have run into a phenomenon I don't understand, but no doubt you folks will. 

If I set up the ds segment using DGROUP (with no ASSUME ), the program runs fine.  Printf runs the string in dseg shown below.  In addition int 21h will print the "howdy" string.

However, if I replace DGROUP with mov ax, SEG dseg even with an ASSUME ds:dseg, the printf function does not run, although the string printed by int  21h runs without a problem

What is happening here? 

My related question is:  what code could I use IN PLACE OF mov ax, DGROUP that would achieve the same effect.  The command lines I use are:  ml /c /omf /Fl /Zi dgroup.asm   and   ..\bin\link16 /map /codeview dgroup.obj c:\tc\lib\c0l.obj,,,c:\tc\lib\cl.lib

Here's the code:


.model large, c
.386


printf PROTO C, :VARARG
sseg segment para stack '_stack'
db 256 dup ('stack   ')
sseg ends

dseg segment para public '_data'

strng db "howdy$", 13, 10, 0
fmt1 db "%s", 0
dseg ends


cseg segment para public '_code'

main PROC
;ASSUME  ds:dseg
mov ax, DGROUP  ;SEG dseg
mov ds, ax

invoke printf, aDDR fmt1, ADDR strng

mov dx, OFFSET ds:strng
mov ah, 09h
int 21h
exit:
mov ah, 4Ch
int 21h
main ENDP
cseg ends
end main


Many thanks.

Mark Allyn

dedndave

 :bg
first, i wouldn't try to mix C and 16-bit asm - lol

that being said....
there may be an issue with segment ordering
when the linker gets ahold of the object files and library modules, it uses the first ones listed to determine segment order
as modules are added, segments are "inserted" according to combine type and class
i have really forgotten all the segment orders - lol
but, for a small model, it would be code, then data, then stack

if you like, you can open and close all the segments in an include file, in the proper order
then, in the source, you can open and close them in any order because the include file has already established the order

recently, there was another thread that was closely related to this - something to do with mixing 16-bit C and asm
in that thread, you will find links to open watcom
you might look in their documentation to see what the order is

even better, try to find the borland documentation that lays out all the segments
it is also a good idea to match the segment parameters, step by step
for example, i see you are using paragraph alignment
i am pretty sure that borland uses word alignment
the combine and class parameters are also important for large model
these need to be the same for segments in DGROUP so that the linker may combine them together

one other tip
i would start with a small model and work my way up   :P
you are only complicating things by using a large model
and - make sure the lib you are linking with is set up for the same memory model

now, for the best free advice you'll get in this thread....
it is much easier in 32-bit world   :U

MichaelW

MASM is well equipped to deal with mixed-language programming. I don't know the answer to the question "When is DGROUP/@data required to set up ds", but I know a likely way around the problem, specify an appropriate model and language type and use the simplified segment directives including the .STARTUP directive. If you need to know how to set up DS (and move the stack into DGROUP) and use the full segment directives, use the above method, and when you assemble have MASM create a listing file. Here is the listing file from one of my TC 2.01 tests:

Microsoft (R) Macro Assembler Version 6.14.8444     05/02/11 19:08:01
clibtest.asm      Page 1 - 1


;====================================================================
.model large, c
.386
;====================================================================

printf PROTO c :VARARG
getch PROTO c
atof PROTO c :DWORD

;====================================================================

.stack
0000 .data

0000     pi    REAL8 3.14159265
       400921FB53C8D4F1
0008     r8    REAL8 0.0
       0000000000000000

0010 25 64 25 63 00     fmtd  db    "%d%c",0
0015 25 78 68 25 63 00     fmth  db    "%xh%c",0
001B 25 66 25 63 00     fmtf  db    "%f%c",0
0020 32 2E 37 31 38 32     estr  db    "2.718282",0
       38 32 00

0000 .code

;====================================================================

;-------------------------------------------------------------
; This dummy procedures prevent the linker from returning an
; "unresolved external" error. Something in the library code
; is apparently referencing this name, and while the dummy
; procedure will satisfy the linker, if the library were to
; actually call the procedure it would probably fail.
;-------------------------------------------------------------

0000 main proc
0000  CB   ret
0001 main endp

.startup
0001    *@Startup:
0001  B8 ---- R    *     mov    ax, DGROUP
0004  8E D8    *     mov    ds, ax
0006  8C D3    *     mov    bx, ss
0008  2B D8    *     sub    bx, ax
000A  C1 E3 04    *     shl    bx, 004h
000D  8E D0    *     mov    ss, ax
000F  03 E3    *     add    sp, bx

;====================================================================

    ;----------------------------------------------------------
    ; For the C calling convention the arguments are pushed in
    ; right to left order, and the caller is responsible for
    ; removing them from the stack after the call returns.
    ;
    ; If the arguments are being correctly removed from the
    ; stack the starting and ending values of SP should match.
    ;----------------------------------------------------------

    invoke printf, ADDR fmtd, 123, 10
0011  6A 0A    *     push   +0000Ah
0013  6A 7B    *     push   +0007Bh
0015  1E    *     push   ds
0016  68 0010 R    *     push   OFFSET DGROUP:fmtd
0019  9A ---- 0000 E    *     call   printf
001E  83 C4 08    *     add    sp, 00008h

    invoke printf, ADDR fmth, 1234h, 10
0021  6A 0A    *     push   +0000Ah
0023  68 1234    *     push   +01234h
0026  1E    *     push   ds
0027  68 0015 R    *     push   OFFSET DGROUP:fmth
002A  9A ---- 0000 E    *     call   printf
002F  83 C4 08    *     add    sp, 00008h

    invoke printf, ADDR fmtf, pi, 10
0032  6A 0A    *     push   +0000Ah
0034  66| FF 36 0004 R    *     push   dword  ptr pi+000000004h
0039  66| FF 36 0000 R    *     push   dword  ptr pi
003E  1E    *     push   ds
003F  68 001B R    *     push   OFFSET DGROUP:fmtf
0042  9A ---- 0000 E    *     call   printf
0047  83 C4 0E    *     add    sp, 0000Eh

    invoke atof, ADDR estr
004A  1E    *     push   ds
004B  68 0020 R    *     push   OFFSET DGROUP:estr
004E  9A ---- 0000 E    *     call   atof
0053  83 C4 04    *     add    sp, 00004h

0056  DD 1E 0008 R     fstp r8

    invoke printf, ADDR fmtf, r8, 10
005A  6A 0A    *     push   +0000Ah
005C  66| FF 36 000C R    *     push   dword  ptr r8+000000004h
0061  66| FF 36 0008 R    *     push   dword  ptr r8
0066  1E    *     push   ds
0067  68 001B R    *     push   OFFSET DGROUP:fmtf
006A  9A ---- 0000 E    *     call   printf
006F  83 C4 0E    *     add    sp, 0000Eh

    invoke getch
0072  9A ---- 0000 E    *     call   getch

.exit
0077  B4 4C    *     mov    ah, 04Ch
0079  CD 21    *     int    021h

;====================================================================

end
Microsoft (R) Macro Assembler Version 6.14.8444     05/02/11 19:08:01
clibtest.asm      Symbols 2 - 1




Segments and Groups:

                N a m e                 Size     Length   Align   Combine Class

CLIBTEST_TEXT  . . . . . . . . . 16 Bit 007B   Word   Public  'CODE'
DGROUP . . . . . . . . . . . . . GROUP
_DATA  . . . . . . . . . . . . . 16 Bit 0029   Word   Public  'DATA'
STACK  . . . . . . . . . . . . . 16 Bit 0400   Para   Stack   'STACK'


Procedures,  parameters and locals:

                N a m e                 Type     Value    Attr

atof . . . . . . . . . . . . . . P Far 0000   Length= 0000 External C
getch  . . . . . . . . . . . . . P Far 0000   Length= 0000 External C
main . . . . . . . . . . . . . . P Far 0000   CLIBTEST_TEXT Length= 0001 Public C
printf . . . . . . . . . . . . . P Far 0000   Length= 0000 External C


Symbols:

                N a m e                 Type     Value    Attr

@CodeSize  . . . . . . . . . . . Number 0001h
@DataSize  . . . . . . . . . . . Number 0001h
@Interface . . . . . . . . . . . Number 0001h
@Model . . . . . . . . . . . . . Number 0005h
@Startup . . . . . . . . . . . . L Near 0001   CLIBTEST_TEXT
@code  . . . . . . . . . . . . . Text    CLIBTEST_TEXT
@data  . . . . . . . . . . . . . Text    DGROUP
@fardata?  . . . . . . . . . . . Text    FAR_BSS
@fardata . . . . . . . . . . . . Text    FAR_DATA
@stack . . . . . . . . . . . . . Text    DGROUP
estr . . . . . . . . . . . . . . Byte 0020   _DATA
fmtd . . . . . . . . . . . . . . Byte 0010   _DATA
fmtf . . . . . . . . . . . . . . Byte 001B   _DATA
fmth . . . . . . . . . . . . . . Byte 0015   _DATA
pi . . . . . . . . . . . . . . . QWord 0000   _DATA
r8 . . . . . . . . . . . . . . . QWord 0008   _DATA

   0 Warnings
   0 Errors


And here is the command line I used:

ml /Fl /Sa /c clibtest.asm

I seem to recall the Microsoft libraries requiring that SS=DS. I don't know if TC 2.01 requires it, or just tolerates it.

eschew obfuscation

allynm

Hi Dedndave and MichaelW

I won't be able to respond to all of your comments in this note, but wanted to at least respond partially. 

First, to Dedndave.  Yes, 32 bits would be the way to go cause flat is simpler.  But, as I have mentioned in another thread, I am trying to understand how segmented memories work.  My other comment is that I would have chosen a small model, but in fact the Borland C library requires large model.  Won't work otherwise.  It was this that led me in fact to discover the "problem"... or anomaly... or whatever.  Once discovered, these things nag and won't let one go. 

Second, to MichaelW.  If I understand your comment...and I want to be fair and admit that I often stupidly misread comments...I know that the whole problem would go away if I simply used the "simple segment" segment scheme i.e. .model .stack .data .code .startup .exit.  I would never have found the (my word) anomaly if I had used the simplified segments.  This is (if I read it correctly) exactly what the .lst file you sent shows.  It shows that DGROUP is mov(ed) to ax.  Right.  But, my question is:  why is this required when a Borland C funcition is called even though it isn't required when the library is simply linked (as it is in both cases I have presented).  The .map file for both of my cases is identical.  It clearly shows a mapping of Borland C library functions.  The difference is that in the case where DGROUP is used, the printf function gets its ADDR's right and prints, but when DGROUP isn't used, it doesn't. 


Regards and thanks,
Mark

MichaelW

If I compile one of the sample C applications (hello.c) from within the BORLAND IDE, with the linker option Map file set to Detailed, I get the following MAP file:


Start  Stop   Length Name               Class

00000H 00FF5H 00FF6H _TEXT              CODE
01000H 0141CH 0041DH _DATA              DATA
0141EH 01421H 00004H _EMUSEG            DATA
01422H 01423H 00002H _CRTSEG            DATA
01424H 01425H 00002H _CVTSEG            DATA
01426H 0142BH 00006H _SCNSEG            DATA
0142CH 01471H 00046H _BSS               BSS
01472H 01472H 00000H _BSSEND            STACK
01480H 014FFH 00080H _STACK             STACK

Detailed map of segments

0000:0000 01FA C=CODE S=_TEXT G=(none) M=C0S ACBP=28
0000:01FA 000D C=CODE S=_TEXT G=(none) M=HELLO.C ACBP=28
0000:0207 003B C=CODE S=_TEXT G=(none) M=IOERROR ACBP=28
0000:0242 0030 C=CODE S=_TEXT G=(none) M=EXIT ACBP=28
0000:0272 0000 C=CODE S=_TEXT G=(none) M=HEAPLEN ACBP=28
0000:0272 00F1 C=CODE S=_TEXT G=(none) M=SETARGV ACBP=28
0000:0363 004A C=CODE S=_TEXT G=(none) M=SETENVP ACBP=28
0000:03AD 0000 C=CODE S=_TEXT G=(none) M=STKLEN ACBP=28
0000:03AD 0026 C=CODE S=_TEXT G=(none) M=ATEXIT ACBP=28
0000:03D3 0152 C=CODE S=_TEXT G=(none) M=MALLOC ACBP=28
0000:0525 0078 C=CODE S=_TEXT G=(none) M=BRK ACBP=28
0000:059D 0000 C=CODE S=_TEXT G=(none) M=FILES ACBP=28
0000:059D 0000 C=CODE S=_TEXT G=(none) M=FILES2 ACBP=28
0000:059D 0113 C=CODE S=_TEXT G=(none) M=WRITE ACBP=28
0000:06B0 0046 C=CODE S=_TEXT G=(none) M=WRITEA ACBP=28
0000:06F6 002B C=CODE S=_TEXT G=(none) M=LSEEK ACBP=28
0000:0721 00EB C=CODE S=_TEXT G=(none) M=LTOA ACBP=28
0000:080C 0021 C=CODE S=_TEXT G=(none) M=CVTFAK ACBP=28
0000:082D 007E C=CODE S=_TEXT G=(none) M=FFLUSH ACBP=28
0000:08AB 0019 C=CODE S=_TEXT G=(none) M=PRINTF ACBP=28
0000:08C4 01E0 C=CODE S=_TEXT G=(none) M=PUTC ACBP=28
0000:0AA4 0004 C=CODE S=_TEXT G=(none) M=REALCVT ACBP=28
0000:0AA8 054E C=CODE S=_TEXT G=(none) M=VPRINTER ACBP=28
0100:0000 0194 C=DATA S=_DATA G=DGROUP M=C0S ACBP=68
0100:0194 000E C=DATA S=_DATA G=DGROUP M=HELLO.C ACBP=48
0100:01A2 005B C=DATA S=_DATA G=DGROUP M=IOERROR ACBP=48
0100:01FE 0006 C=DATA S=_DATA G=DGROUP M=EXIT ACBP=48
0100:0204 0002 C=DATA S=_DATA G=DGROUP M=HEAPLEN ACBP=48
0100:0206 0000 C=DATA S=_DATA G=DGROUP M=SETARGV ACBP=48
0100:0206 0000 C=DATA S=_DATA G=DGROUP M=SETENVP ACBP=48
0100:0206 0002 C=DATA S=_DATA G=DGROUP M=STKLEN ACBP=48
0100:0208 0002 C=DATA S=_DATA G=DGROUP M=ATEXIT ACBP=48
0100:020A 0000 C=DATA S=_DATA G=DGROUP M=MALLOC ACBP=48
0100:020A 0000 C=DATA S=_DATA G=DGROUP M=BRK ACBP=48
0100:020A 0140 C=DATA S=_DATA G=DGROUP M=FILES ACBP=48
0100:034A 0028 C=DATA S=_DATA G=DGROUP M=FILES2 ACBP=48
0100:0372 0000 C=DATA S=_DATA G=DGROUP M=WRITE ACBP=48
0100:0372 0000 C=DATA S=_DATA G=DGROUP M=WRITEA ACBP=48
0100:0372 0000 C=DATA S=_DATA G=DGROUP M=LSEEK ACBP=48
0100:0372 0000 C=DATA S=_DATA G=DGROUP M=LTOA ACBP=48
0100:0372 0031 C=DATA S=_DATA G=DGROUP M=CVTFAK ACBP=48
0100:03A4 0000 C=DATA S=_DATA G=DGROUP M=FFLUSH ACBP=48
0100:03A4 0000 C=DATA S=_DATA G=DGROUP M=PRINTF ACBP=48
0100:03A4 0001 C=DATA S=_DATA G=DGROUP M=PUTC ACBP=48
0100:03A6 0077 C=DATA S=_DATA G=DGROUP M=VPRINTER ACBP=48
0141:000E 0004 C=DATA S=_EMUSEG G=DGROUP M=C0S ACBP=58
0142:0002 0002 C=DATA S=_CRTSEG G=DGROUP M=C0S ACBP=58
0142:0004 0000 C=DATA S=_CVTSEG G=DGROUP M=C0S ACBP=48
0142:0004 0002 C=DATA S=_CVTSEG G=(none) M=CVTFAK ACBP=48
0142:0006 0000 C=DATA S=_CVTSEG G=DGROUP M=REALCVT ACBP=48
0142:0006 0000 C=DATA S=_SCNSEG G=DGROUP M=C0S ACBP=48
0142:0006 0006 C=DATA S=_SCNSEG G=(none) M=CVTFAK ACBP=48
0142:000C 0000 C=BSS S=_BSS G=DGROUP M=C0S ACBP=48
0142:000C 0000 C=BSS S=_BSS G=DGROUP M=HELLO.C ACBP=48
0142:000C 0000 C=BSS S=_BSS G=DGROUP M=IOERROR ACBP=48
0142:000C 0000 C=BSS S=_BSS G=DGROUP M=EXIT ACBP=48
0142:000C 0000 C=BSS S=_BSS G=DGROUP M=HEAPLEN ACBP=48
0142:000C 0000 C=BSS S=_BSS G=DGROUP M=STKLEN ACBP=48
0142:000C 0040 C=BSS S=_BSS G=DGROUP M=ATEXIT ACBP=48
0142:004C 0006 C=BSS S=_BSS G=DGROUP M=MALLOC ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=BRK ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=FILES ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=FILES2 ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=WRITE ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=WRITEA ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=LSEEK ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=LTOA ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=FFLUSH ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=PRINTF ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=PUTC ACBP=48
0142:0052 0000 C=BSS S=_BSS G=DGROUP M=VPRINTER ACBP=48
0147:0002 0000 C=STACK S=_BSSEND G=DGROUP M=C0S ACBP=28
0148:0000 0080 C=STACK S=_STACK G=(none) M=C0S ACBP=74
<snip>


The data segments above starting with _DATA are in the MAP file for your app, followed your stack and data segments:

02600H 02C3AH 0063BH _DATA                  DATA
02C3CH 02C3FH 00004H _EMUSEG                DATA
02C40H 02C41H 00002H _CRTSEG                DATA
02C42H 02C49H 00008H _CVTSEG                DATA
02C4AH 02C61H 00018H _SCNSEG                DATA
02C70H 0346FH 00800H SSEG                   _STACK
03470H 0347BH 0000CH DSEG                   _DATA


So without referencing DGROUP or @data, I can effectively do the same thing by specifying the first segment in the group:

    mov ax, SEG _DATA
    mov ds, ax


And printf works correctly. So I think an imprecise answer to your first question would be something along the lines of:

DGROUP or @data may be required to set up DS if the linker will be combining two or more data or stack segments.

Quotewhy is this required when a Borland C funcition is called even though it isn't required when the library is simply linked
I think the problem is not the function call, but the called function trying to access data through a bad segment address.
eschew obfuscation

dedndave

 :bg
wow, Michael, i haven't seen a map file for a long time - lol
it brings back memories (pun)   :P

notice the class names
i think they have to be the same for the linker to combine them
and - they all have to have a combine type of PUBLIC

01000H 0141CH 0041DH _DATA              DATA - normal data
0141EH 01421H 00004H _EMUSEG            DATA - FPU emulator
01422H 01423H 00002H _CRTSEG            DATA - C runtime
01424H 01425H 00002H _CVTSEG            DATA - C sumpin - may be where borland puts an ID marker
01426H 0142BH 00006H _SCNSEG            DATA - screen segment ?


those segments form DGROUP and should be in the same order in the first obj linked
surprised i don't see a CONST segment

01472H 01472H 00000H _BSSEND            STACK
01480H 014FFH 00080H _STACK             STACK


as i recall, _BSSEND is a dummy segment used to test for stack overlfow
BSS is, of course, uninitialized data
it looks like it may have been combined with DGROUP, somehow
i guess the class names do not have to match
and - odd that _BSS is in DGROUP, but _SCNSEG is not
doesn't the map file give you the size of DGROUP ?
DGROUP must be a public symbol

now i remember - it goes something like this
the linker will combine segments of the same class name before combining other segments

dedndave

near as i can figure, it should look something like this....

_TEXT   SEGMENT WORD PUBLIC 'CODE'
_TEXT   ENDS

DGROUP  GROUP   _DATA,_EMUSEG,_CRTSEG,_CVTSEG,_SCNSEG,_BSS,_BSSEND

_DATA   SEGMENT PARA PUBLIC 'DATA'
_DATA   ENDS

_EMUSEG SEGMENT WORD PUBLIC 'DATA'
_EMUSEG ENDS

_CRTSEG SEGMENT WORD PUBLIC 'DATA'
_CRTSEG ENDS

_CVTSEG SEGMENT WORD PUBLIC 'DATA'
_CVTSEG ENDS

_SCNSEG SEGMENT WORD PUBLIC 'DATA'
_SCNSEG ENDS

_BSS    SEGMENT WORD PUBLIC 'BSS'
_BSS    ENDS

_BSSEND SEGMENT WORD PUBLIC 'STACK'
_BSSEND ENDS

_STACK  SEGMENT PARA STACK 'STACK'
_STACK  ENDS


if you put that in an INC file and include it at the beginning, your segments will be in order
and - when you open your code segment in the source file...
_TEXT   SEGMENT WORD PUBLIC 'CODE'
        ASSUME  CS:_TEXT,DS:DGROUP,SS:_STACK

of course, you have to put DGROUP into DS, and possibly ES

you may need to add a CONST segment just before _BSS and add it to DGROUP
it could be that this program had nothing to put in that segment
or, that borland does not follow MS convention

CONST   SEGMENT WORD PUBLIC 'CONST'
CONST   ENDS

dedndave

one more note...
some of those segments are created by the compiler and may not be necessary to link with the library
you may be able to make a map of some (several) modules from the library and see which are used
some compilers put a marker in there, usually in the form of a copyright notice
the libraries won't work without it - lol
that is some compilers

FORTRANS

Hi,

   From a textbook:

   "Segments defined with the .STACK, .DATA, .DATA?, and .CONST
directives are placed in a group named DGROUP.  The value of DGROUP
rather than that of the segment name should be loaded into DS
register at the start of the code section."

   And later on:

"Simplified Segment Defaults

   ...

   With full segment definitions, the data segment address in the DS
register is the address from which OFFSET addresses are calculated.
With simplified definitions, the base address for OFFSET addresses
is that of DGROUP for .DATA, .DATA?, or .STACK segments.  .CODE,
.FARDATA, and .FARDATA? segments have their own base addresses and
are not part of DGROUP."

   Looks like he forgot .CONST there.

   Anyway, it looks as if the high level language is using the
equivalent of simplified directives for naming segments.  So
use DGROUP or SEG {first data segment name} as MichaelW
suggests.  Note that in assembly the order of the segments
may not follow the "standard" ordering, so check with a MAP
listing.

HTH,

Steve N.

allynm

Hi Michaelw, Dedndave, and SteveN,

I haven't been able to manage handling Dedndave's suggestions yet, but I will.  For the moment, I'll try to respond to Michael W and Steve who seem to be in agreement about the remedy. 

So, I tried using _data as MichaelW suggested and what happened was:  I got the printf function to work and print "howdy?" and also I got at the very end of the run the int 21h "howdy".  BUT, in between there was a bunch of garbage from another data segment. 

So, I reasoned thusly:  why not write


allynm

Continuation from reply to Dedndave, Steve, and Michael W...

Sorry I chopped myself off midsentence.   I tried an experiment, attempting to add 371h to _data to get to dseg, but this experiment didn't work. 

Anyway,  so where MichaelW writes:

"So without referencing DGROUP or @data, I can effectively do the same thing by specifying the first segment in the group:

Code:
    mov ax, SEG _DATA
    mov ds, ax

And printf works correctly. So I think an imprecise answer to your first question would be something along the lines of:"

I was unable to get the code to run properly.

I'll try to implement any other suggestions.  But, the bottom line seems to be that if you want the thing to work you have to somehow load the first segment of the data class into the ds.  Or else use DGROUP right from the start.  I'm OK with this, but as I say, when I tried to lad the first segment of _data, I kind of got a mess plus the right stuff.

Regards,
Mark


allynm

Hi MichaelW and SteveN and 'Dave,

Sorry.  I made a mistake in my coding.  Went back and fixed the problem so that I REALLY implemented MichaelW's and SteveN's proposal to load the FIRST segment in the data class.  It worked!  So, I think we're "there" in the sense of answering my original query as to whether I had to use DGROUP exclusively...

But, here is an additional point of interest.  If I use the .DOSSEG directive, the code I originally sent you will NOT assemble.  The assembler reports an error pertaining to DSEG  (no.  L2002). 

Thanks for working on this.  I really appreciate it.

Mark Allyn


MichaelW

This is the code I was using:

.model large, c
.386

printf PROTO C, :VARARG

sseg segment para stack '_stack'
db 256 dup ('stack   ')
sseg ends

dseg segment para public '_data'
strng db "howdy$", 13, 10, 0
fmt1 db "%s", 0
dseg ends


cseg segment para public '_code'

main PROC

;ASSUME  ds:dseg
;mov ax, DGROUP  ;SEG dseg

  mov ax, SEG _DATA
  mov ds, ax

invoke printf, aDDR fmt1, ADDR strng

mov dx, OFFSET ds:strng
mov ah, 09h
int 21h
exit:
mov ah, 4Ch
int 21h
main ENDP
cseg ends
end main

And the batch file:

ML /Fl /Sa /c mark.asm
pause
LINK16 /MAP mark.obj forcefp.obj c0l.obj,,,fp87.lib emu.lib mathl.lib cl.lib;
pause
mark
pause

And the result:

D:\MASMDOS\tc201_test>ML /Fl /Sa /c mark.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: mark.asm

D:\MASMDOS\tc201_test>pause
Press any key to continue . . .

D:\MASMDOS\tc201_test>LINK16 /MAP mark.obj forcefp.obj c0l.obj,,,fp87.lib emu.li
b mathl.lib cl.lib;

Microsoft (R) Segmented Executable Linker  Version 5.60.339 Dec  5 1994
Copyright (C) Microsoft Corp 1984-1993.  All rights reserved.


D:\MASMDOS\tc201_test>pause
Press any key to continue . . .

D:\MASMDOS\tc201_test>mark
howdy$
howdy
D:\MASMDOS\TC201_~1>pause
Press any key to continue . . .


Are these the results you expected?
eschew obfuscation

allynm

Hi MichaelW & SteveN and 'Dave

Thanks MichaelW.  Yes, that is the original code I sent and eventually, as I said in my last post, this is the code I used...except, of course, I swapped out the seg dseg snippet for seg _data.  And it ran.

One point I don't understand has to do with the _DATA segment (as named in the .map file).  In my code the _DATA segment is 371h bytes.  What's inside this segment? 

Question for SteveN--you gave several quotations from a textbook regarding this problem.  Could you give me a reference for the textbook?

Thanks all,
Mark

FORTRANS

Hi Mark,

   Sure thing.  Got it from Edward R. Hamilton Bookseller Company,
which sells remaindered (?) books, EdwardRHamilton.com.
"Structured Assembler Language for IBM Microcomputers" by
Alton R. Kindred, Oxford University Press, 1991, ISBN: 0-19-517296-5.

Regards,

Steve N.