c++ - How DMC handle segments & Optlink oddities
- Manoel (241/241) Apr 23 2016 Hi everyone,
Hi everyone,
As I'm trying to make DMC working for a 16bit x86 (80186) non PC
hardware, I started to make a crt for that target, but once I
started to make real program, I got problem with how segments are
handled by DMC.
DMC seems to create a full bunch of segments which are good:
_TEXT for code
_DATA for inited RW data
CONST for constant data ?
_BSS for non inited RW data ?
I'm using a memory model which is close to the small and tiny
model, but CS, DS and SS are different, as the code is in ROM,
data are in a limite memory space (I can't copy the whole
executable there, and at the end there could be more than 64K of
data and it would be paginated, but that's another problem) and
the stack have it's own area.
My first issue is that I don't understand how DMC put data into
each segments, and I can't find a way to make sure it does what I
want.
It seems to put everything into _DATA, it honour the __cs, but
the CONST segment stay empty whatever the code I put.
Here is an example:
int non_init_var; /* Should be in _BSS */
int inited_var = 2; /* Should be in _DATA */
const int constant_var = 53; /* Should be in CONST */
int main(int argc, char *argv[])
{
const int const_local_var = 20; /* Should be in
TEXT or CONST */
static int static_local_var; /* Should be in
_BSS */
static int static_inited_local_var = 5; /* Should be in
_DATA */
int local_var = 42; /* Should be on
stack */
printf("Hello World!"); /* Text should be in CONST or in
TEXT as it is implicitely const here. */
/* Just to make sure all the variable are used and are not
stripped */
non_init_var = 29;
static_local_var++;
local_var = non_init_var + inited_var + constant_var +
const_local_var + static_local_var + static_inited_local_var;
return local_var;
}
After building with
dmc -c -a1 -NL test.c
I got this annotated disassembly output from the freeware version
of IDA Pro 5:
FLAT:0000 ;
FLAT:0000 ;
+-------------------------------------------------------------------------+
FLAT:0000 ; ¦ This file is generated by The Interactive
Disassembler (IDA) ¦
FLAT:0000 ; ¦ Copyright (c) 2010 by Hex-Rays SA,
<support hex-rays.com> ¦
FLAT:0000 ; ¦ Licensed to: Freeware version
¦
FLAT:0000 ;
+-------------------------------------------------------------------------+
FLAT:0000 ;
FLAT:0000 ; Input MD5 : F86FF1C59D493A04AE64BE3441AE11FD
FLAT:0000
FLAT:0000 ; File Name : C:\users\crossover\Desktop\My Mac
Desktop\AC2016\AC2016\test.obj
FLAT:0000 ; Format : Object Module Format (OMF/Microsoft)
FLAT:0000 ; Module name : test.c
FLAT:0000 ; MS parameters :
FLAT:0000 ; Debug info type : CodeView
FLAT:0000
FLAT:0000
FLAT:0000 .386
FLAT:0000 .model flat
FLAT:0000
FLAT:0000 ;
---------------------------------------------------------------------------
FLAT:0000
FLAT:0000 ; Segment type: Group
FLAT:0000 FLAT group
FLAT:0000
extn00:0001 ; Near data, 4 bytes
extn00:0001 ;
---------------------------------------------------------------------------
extn00:0001
extn00:0001 ; Segment type: Externs
extn00:0001 ; extn00
extn00:0001 extrn _non_init_var:byte:4 ; DATA
XREF: _main+1Cw
extn00:0005 extrn __acrtused_con:far
extn00:0005
extn01:0006 ;
---------------------------------------------------------------------------
extn01:0006
extn01:0006 ; Segment type: Externs
extn01:0006 ; extn01
extn01:0006 ; int printf(const char *,...)
extn01:0006 extrn _printf:near ; CODE XREF:
_main+12p
extn01:0006
_TEXT:00000007 ;
---------------------------------------------------------------------------
_TEXT:00000007
_TEXT:00000007 ; Segment type: Pure code
_TEXT:00000007 _TEXT segment dword public 'CODE' use32
_TEXT:00000007 assume cs:_TEXT
_TEXT:00000007 ;org 7
_TEXT:00000007 assume es:nothing, ss:nothing,
ds:nothing, fs:nothing, gs:nothing
_TEXT:00000007
_TEXT:00000007 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
_TEXT:00000007
_TEXT:00000007 ; Attributes: bp-based frame
_TEXT:00000007
_TEXT:00000007 public _main
_TEXT:00000007 _main proc near
_TEXT:00000007
_TEXT:00000007 local_var = dword ptr -4
_TEXT:00000007
_TEXT:00000007 enter 4, 0
_TEXT:0000000B push ebx
_TEXT:0000000C mov eax, 20
_TEXT:00000011 mov [ebp+local_var], eax
_TEXT:00000014 push offset aHelloWorld ;
"Hello World!"
_TEXT:00000019 call _printf
_TEXT:0000001E mov ecx, 29
_TEXT:00000023 mov dword ptr
ds:_non_init_var, ecx
_TEXT:00000029 inc ds:static_local_var
_TEXT:0000002F mov edx, ds:_inited_var
_TEXT:00000035 lea ebx, [ecx+edx]
_TEXT:00000038 add ebx, ds:_constant_var
_TEXT:0000003E add ebx, [ebp+local_var]
_TEXT:00000041 add ebx, ds:static_local_var
_TEXT:00000047 add ebx,
ds:static_inited_local_var
_TEXT:0000004D mov eax, ebx
_TEXT:0000004F add esp, 4
_TEXT:00000052 pop ebx
_TEXT:00000053 leave
_TEXT:00000054 retn
_TEXT:00000054 _main endp
_TEXT:00000054
_TEXT:00000054 _TEXT ends
_TEXT:00000054
_DATA:00000005 ;
---------------------------------------------------------------------------
_DATA:00000005
_DATA:00000005 ; Segment type: Pure data
_DATA:00000005 _DATA segment dword public 'DATA' use32
_DATA:00000005 assume cs:_DATA
_DATA:00000005 ;org 5
_DATA:00000005 public _inited_var
_DATA:00000005 _inited_var dd 2 ; DATA
XREF: _main+28r
_DATA:00000009 public _constant_var
_DATA:00000009 _constant_var dd 53 ; DATA
XREF: _main+31r
_DATA:0000000D static_inited_local_var dd 5 ; DATA
XREF: _main+40r
_DATA:00000011 ; char aHelloWorld[]
_DATA:00000011 aHelloWorld db 'Hello World!',0 ; DATA
XREF: _main+Do
_DATA:00000011 _DATA ends
_DATA:00000011
CONST:0000000E ;
---------------------------------------------------------------------------
CONST:0000000E
CONST:0000000E ; Segment type: Zero-length
CONST:0000000E CONST segment dword public 'CONST' use32
CONST:0000000E CONST ends
CONST:0000000E
_BSS:0000000F ;
---------------------------------------------------------------------------
_BSS:0000000F
_BSS:0000000F ; Segment type: Uninitialized
_BSS:0000000F _BSS segment dword public 'BSS' use32
_BSS:0000000F assume cs:_BSS
_BSS:0000000F ;org 0Fh
_BSS:0000000F assume es:nothing, ss:nothing,
ds:nothing, fs:nothing, gs:nothing
_BSS:0000000F static_local_var dd ? ; DATA
XREF: _main+22w
_BSS:0000000F ; _main+3Ar
_BSS:0000000F _BSS ends
_BSS:0000000F
_BSS:0000000F
_BSS:0000000F end
What I see here is that the CONST segment is absolutely empty,
especially with all things that should be treated as constant
(because they are explicitly or implicitly declared as constant,
the text given in parameter to printf should be constant for
exemple)
and two variable defined in this C file, but not initialised
instead of going into the BSS are put as extern? That clearly not
what should be expected.
I've run this with 32bit x86 output, but using all memory model
for 16bit DOS does the same.
The fact that on some system and that some linker may merge CONST
and DATA segments is possible, as on some system everything is in
RAM anyway, but that should not be the C compiler that do such a
thing.
I should only copy the non constant variables into the RW DATA
RAM, and not all the constant one that could be really big on
some project.
Is this a bug in DMC?
Is this something done on purpose? If yes, how can I force it to
use the CONST segment for everything which is constant, and make
sure it does not create extern for variable that are clearly
defined in the current file.
By the way, I also have a few thing I don't understand with the
optlink:
I've created a third group to represent a specific area in memory:
section PRAM class=IRAM location=00000h
resb 0200h ; Put at byte 200h
_tickL: resw 1 ; Low word of tick counter
_tickH: resw 1 ; High word of tick counter
group CGROUP _TEXT
group DGROUP C_COMMON _DATA _BSS _CONST ENDDATA
group IRGROUP PRAM
and optlink seems to have merged DGROUP with IRGROUP where I
should not expect this at all as in one C file that use
_tickL/_tickH, instead of referencing them as a far pointer (ds
is not set to this section) it just merge that section with the
DGROUP, which is not the behaviour I expected.
Similar problem, I've tried to use the trick to get the size of
the RW data by putting a pointer at the beginning of the DGROUP,
and use the ENDDATA section to put an end pointer and use them to
copy the rw data into the memory, but doing that as when the
assembler build the CRT, it does not now where DRGOUP is about to
be put in the resulting file, and create a relocation marker to
say "I still don't know where this is to be put" but then, when
linking optlink does not replace that marker with the real value
so I end with a file with relocation, which is not something I
want as I'm currently using exe2com (updated to work on 64bit
computer) which does not want relocatable EXEs.
Is there is a way to copy the DGROUP into memory without
generating a relocation?
Thanks
Manoel
Apr 23 2016








Manoel <godzil godzil.net>