Strange HiTech's LINK anomaly

79 views
Skip to first unread message

ladislau szilagyi

unread,
May 9, 2023, 9:51:24 AM5/9/23
to RC2014-Z80
Hi,

I noticed a strange LINK behavior, related to how it handles the DATA program section.

It affected me in an unexpected way, while working to adapt the HiTech's C compiler's toolset to Bill Shen's Z80ALL.

Because the Z80ALL hardware configuration ( 4 x 32KB RAM segments, the fixed 32KB segment being loaded at 8000H, the other 3 selectable 32KB segments at 0H ), I needed to have my "memory allocator" code located above 8000H, so I used some buffers placed in the DATA segment to "force" the linker to "move" higher the segment placed after DATA, which contained the "memory allocator" code.

After some spectacular crashes, in desperation I took a closer look on the COM file and I found that my "memory allocator" was simply "missing", not being included in the file.

I looked at the memory map file produced by the LINK, it was OK.

But the .COM file was "smaller" than expected... strange!

So I made same basic tests:

I used a simple assembly source file, including TEXT, DATA and BSS segments.

As a precaution, I used the "old" original HiTech's ZAS.COM to assemble-it...
(at first, I suspected my Z80AS to build wrong .OBJ files, but my suspicion proved to be wrong)

-------------------------
I>type t.as
        psect text
start:
ld      sp,stack
ld      hl,info
        psect data
buf:    defs 10h
info:   defm 'DATA'
        psect bss
        defs 40h
stack:
        end start

I>type t.sub
oldzas t.as
xsub
link
-mt.map -ptext=100h,data,bss -c100h -ot.com t.obj
type t.map
dumpx t.com

I>submit t

I>oldzas t.as

I>xsub

I>link
link> -mt.map -ptext=100h,data,bss -c100h -ot.com t.obj


(xsub active)
I>type t.map
Machine type is Z80

t.obj           text          100        6      data          106       14
                bss           11A       40

TOTAL           Name         Link     Load   Length
                (abs)           0        0        0
                text          100      100        6
                data          106      106       14
                bss           11A      11A       40

                                  Symbol Table

__Hbss  bss   015A  __Hdata data  011A  __Htext text  0106  __Lbss  bss   011A
__Ldata data  0106  __Ltext text  0100

I>dumpx t.com
0000 : 31 5A 01 21 16 01 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : 1Z.!............
0010 : 1A 1A 1A 1A 1A 1A 44 41 54 41 1A 1A 1A 1A 1A 1A : ......DATA......
0020 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0030 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0040 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0050 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0060 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0070 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................

(xsub active)
I>
-----

The T.COM looks fine.

Now, let's edit T.AS, to change only:
buf: defs 100h

(buffer was increased to 100H)
-----
I>type t.as
        psect text
start:
ld      sp,stack
ld      hl,info
        psect data
buf:    defs 100h
info:   defm 'DATA'
        psect bss
        defs 40h
stack:
        end start

I>submit t

I>oldzas t.as

I>xsub

I>link
link> -mt.map -ptext=100h,data,bss -c100h -ot.com t.obj


(xsub active)
I>type t.map
Machine type is Z80

t.obj           text          100        6      data          106      104
                bss           20A       40

TOTAL           Name         Link     Load   Length
                (abs)           0        0        0
                text          100      100        6
                data          106      106      104
                bss           20A      20A       40

                                  Symbol Table

__Hbss  bss   024A  __Hdata data  020A  __Htext text  0106  __Lbss  bss   020A
__Ldata data  0106  __Ltext text  0100

I>dumpx t.com
0000 : 31 4A 02 21 06 02 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : 1J.!............
0010 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0020 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0030 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0040 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0050 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0060 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0070 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0080 : 61 72 74 0D 0A 0D 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A : art.............
0090 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00A0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00B0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00C0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00D0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00E0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00F0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0100 : 1A 1A 1A 1A 1A 1A 44 41 54 41 1A 1A 1A 1A 1A 1A : ......DATA......
0110 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0120 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0130 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0140 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0150 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0160 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0170 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................

(xsub active)
I>
-----

The T.COM is still OK.

Edit again T.AS, change only:
buf: defs 1000h

(we increased the buffer to 1000H)

-----
I>type t.as
        psect text
start:
ld      sp,stack
ld      hl,info
        psect data
buf:    defs 1000h
info:   defm 'DATA'
        psect bss
        defs 40h
stack:
        end start

I>submit t

I>oldzas t.as

I>xsub

I>link
link> -mt.map -ptext=100h,data,bss -c100h -ot.com t.obj


(xsub active)
I>type t.map
Machine type is Z80

t.obj           text          100        6      data          106     1004
                bss          110A       40

TOTAL           Name         Link     Load   Length
                (abs)           0        0        0
                text          100      100        6
                data          106      106     1004
                bss          110A     110A       40

                                  Symbol Table

__Hbss  bss   114A  __Hdata data  110A  __Htext text  0106  __Lbss  bss   110A
__Ldata data  0106  __Ltext text  0100

I>dumpx t.com
0000 : 31 4A 11 21 06 11 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : 1J.!............
0010 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0020 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0030 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0040 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0050 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0060 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0070 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0080 : 61 72 74 0D 0A 0D 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A : art.............
0090 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00A0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00B0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00C0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00D0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00E0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
00F0 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0100 : 1A 1A 1A 1A 1A 1A 44 41 54 41 1A 1A 1A 1A 1A 1A : ......DATA......
0110 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0120 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0130 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0140 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0150 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0160 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0170 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
0180 :                    (GARBAGE)
........................................................
07F0 :                    (GARBAGE)

(xsub active)
I>
 
--------

SURPRISE!

Although the MAP file seems OK, the COM file is NOT OK, it has the size of just 0800H!
It should have been larger than 1000H (the buffer only is 1000H bytes wide...) !!!

So, when the section DATA contains large buffers defined using DEFS, the LINK does not include the whole DATA segment into the .COM file, truncating-it (it seems to 2KB).

I solved the problem replacing 

DEFS 1000H

with

REPT 1000H
DEFB 0
ENDM

...and, of course, using Z80AS instead of ZAS...

Example:
---------------------
I>type t.as
        psect text
start:
ld      sp,stack
ld      hl,info
        psect data
buf:    rept 1000h
        defb    0
        endm
info:   defm 'DATA'
        psect bss
        defs 40h
stack:
        end start

I>submit t

I>z80as t.as
Z80AS Macro-Assembler V4.8

Errors: 0
Finished.

I>xsub

I>link
link> -mt.map -ptext=100h,data,bss -c100h -ot.com t.obj


(xsub active)
I>type t.map
Machine type is Z80

t.obj           text          100        6      data          106     1004
                bss          110A       40

TOTAL           Name         Link     Load   Length
                (abs)           0        0        0
                text          100      100        6
                data          106      106     1004
                bss          110A     110A       40

                                  Symbol Table

__Hbss  bss   114A  __Hdata data  110A  __Htext text  0106  __Lbss  bss   110A
__Ldata data  0106  __Ltext text  0100

I>dumpx t.com
0000 : 31 4A 11 21 06 11 00 00 00 00 00 00 00 00 00 00 : 1J.!............
0010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
...........
0FF0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
1000 : 00 00 00 00 00 00 44 41 54 41 1A 1A 1A 1A 1A 1A : ......DATA......
1010 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
1020 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
1030 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
1040 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
1050 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
1060 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................
1070 : 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A : ................

(xsub active)
I>

Now, the T.COM is OK!
------------------------

Be aware of this annoying issue, it could cause you serious trouble!

Ladislau

 

Fred Weigel

unread,
May 10, 2023, 11:09:33 AM5/10/23
to RC2014-Z80
Ladislau

This is very interesting. A defs 1000h will not work with my obj2mac.c tool either. The data comes first, and this is followed by relocation and fixup. The linker is structured such that
a fixed buffer is retained, and NOWHERE is there an indication of how large this should be. Based on compiling a bunch of C code, and processing the run-time library, I decided that HiTech never uses more than 500 bytes or so. So, obj2mac uses 1024 as the size of the relocation buffer. Which is nowhere close to 4096 bytes! So, you can probably use 4 repeats of defs 200h and have that work as well. (just a guess). But I will update the buffer size to 2000h (8192 decimal) in obj2mac.c (and test).  You can look at the source for objtomac at


The path is: HiTech C -> obj, obj -> mac, mac -> rel and then use the Microsoft linker (or plink II). obj2mac.c is just my interpretation of obj files (reverse engineer the format -- I did NOT dis-assemble or de-compile LINK.COM for this). You can also fine as2nac,cm which is a very crube as -> mac converter. It *only* works for HiTech C generated as files, and specifically I used it to convert the HiTech run-time library to rel format. Given some issues in HiTech C, I abandoned that and tackled the obj format directly. Use whatever you want -- this is MIT licensed (and all source is included, of course).
Reply all
Reply to author
Forward
0 new messages