Format of .O and .L files. The whole mechanism of processing .O files revolves around 0x82 bytes in the data stream: these are used as an escape value. Normal data that is to be linked in appears in the output file byte for byte, and is copied straight over by ZLINK. When ZLINK encounters a 0x82 byte, then it does not pass it over, instead it takes special action depending on the value of the next byte, known as the flag byte. In the explanations below, the term "current segment" is used to refer to whichever segment code is being generated for, and the base of the current segment is the point at which code generation for the appropriate segment started in the .O file being processed. 0x82: escaped 0x82 byte in data stream - in order that these bytes can appear, they must be escaped with themselves, so the line: db 1,0x82,2 in the source would give: 0x01 (first byte straight over) 0x82 (escape) 0x82 (the 0x82 byte from the db) 0x02 (and the last byte) in the .O file. 0x27: internal cseg reference: 0x22: internal dseg reference: 0x5e: internal useg reference: These three are grouped together as their behavior is similar: following the flag byte are two more bytes that give the word offset from the base of the segment being referred to: as an example, if the label foo: appeared 0x20 bytes into the cseg section of the current .O file, then the source line: call foo would generate the following: 0xcd (call) 0x82 (escape) 0x27 (flag) 0x20 (low byte of offset) 0x00 (high byte of offset) It should be noted that if either byte of the offset is 0x82 then it is NOT escaped in any way, when reading word offsets ZLINK simply picks up the next two bytes regardless. 0x24: external reference: when ZSM cannot resolve a reference to one of the above three, it generates one of these instead: it is similar to the above, but it also includes the name of the external label following the offset word, terminated by another 0x82 byte, so: ld hl, bar - 2 where bar is not defined in this module would give: 0x21 (ld hl,....) 0x82 (escape) 0x24 (flag) 0xfe (low byte of offset (see the -2)) 0xff (high byte of offset) 0x62 ('b' of bar) 0x61 ('a' of bar) 0x72 ('r' of bar) 0x82 (terminate the label) The comment about 0x82 bytes in the offset of internal references also applies here. 0x3a: define an external label: when a label is extern'ed by use of the extern directive, this is how it gets transferred to the .O file: at the appropriate spot an escape, 0x3a flag, and the name appear again terminated by a 0x82, so: .extern fox fox: inc a would give: 0x82 (escape) 0x3a (flag) 0x66 ('f' of fox) 0x6f ('o' of fox) 0x78 ('x' of fox) 0x82 (terminate) 0x3c (inc a) 0x2d: enter the cseg section: 0x2b: enter the dseg section: 0x2a: enter the useg section: 0x40: terminate the file: In order to keep the three segments apart, these sequences are used: Note that the 0x82, 0x2d should be the first thing in the .O file, the action of ZLINK if it comes across anything else is not defined, and ZLINK stops after it reaches the 0x82, 0x40 sequence. ZLINK also expects to find the middle two sequences, even if any of the sections are empty, the appropriate sequence MUST be there, or to put it another way, the absolute minimum that can appear in a .O file is: 0x82 (escape) 0x2d (enter cseg) 0x82 (escape) 0x2b (enter dseg) 0x82 (escape) 0x2a (enter useg) 0x82 (escape) 0x40 (termiate the .O file) Note also that ZLINK expects to get the sections in the order shown above, and each section can only appear once in the file. In general usage, a .O file would be: 0x82 (escape) 0x2d (enter cseg) 0x21 (first byte of data ...) CSEG SECTION 0x82 (escape) 0x2b (enter dseg) DSEG SECTION 0x82 (escape) 0x2a (enter useg) USEG SECTION 0x82 (escape) 0x40 (termiate the .O file) The reason for showing one byte of code in the cseg section is that while code is being generated for that section and only while code is being generated, the base of the current segment is the address at whice the 0x21 byte appears in the output file. There is a special limitation that applies to the useg section in that it can only contain external label definitions (flag byte 0x3a), and ds / org sequences (flag byte 0x3e). 0x3e: process a ds opcode or an org directive: these two are handled in a similar fashion: following the flag byte is the address at which this sequence should end, considered as an offset from the base of the current segment being processed, so: .org 0x0200 in the source would give: 0x82 (escape) 0x3e (flag) 0x00 (low byte) 0x02 (high byte) as org's always refer to the base of the current segment; and if the following ds appeared at address 0x0110 in some segment: ds 0x64 the resulting code woude be: 0x82 (escape) 0x3e (flag) 0x74 (low byte) 0x01 (high byte) Note how the termination address is 0x174: the sum of the start address (0x110) and the size (0x64). As is mentioned in LIB.DOC, .L files are similar to .O files, with the exception that some additional information appears to keep the modules apart, and to provide naming and linking information. The following flag bytes will appear in library files: 0x3b: start a new .O module in the current library: following this is the name of the module, always in upper case, terminated by another 0x82 byte. 0x26: flag an external label that this module can resolve: in order that ZLINK can know which undefined labels a module can resolve, a list is provided at the start, each entry in the list has the following form: (example given for label bar) 0x82 (escape) 0x26 (flag) 0x62 ('b' of bar) 0x61 ('a' of bar) 0x72 ('r' of bar) 0x82 (terminate this sequence) 0x2e: terminate list of labels that can be resolved by this module: after all the external labels have been provided, include this sequence to tell ZLINK to stop scanning for externals. so taking the example from ZSM.DOC: .lib "strcpy" ; generating STRCPY.O .extern _strcpy ; _strcpy is the only external label _strcpy: ; here it is call #arg2 ; and the code .... the entire sequence generated would be: 0x82 (escape) 0x3b (flag a new .O module) 0x53 ('S' of STRCPY) 0x54 ('T' of STRCPY) 0x52 ('R' of STRCPY) 0x43 ('C' of STRCPY) 0x50 ('P' of STRCPY) 0x59 ('Y' of STRCPY) 0x82 (terminate .O module name definition) ; the above sequence gives the name of the module, note that ; the .O is not included, and that the bytes in the .L file ; have been converted to upper case. 0x82 (escape) 0x26 (flag a label resolved in this module) 0x5f ('_' of _strcpy) 0x73 ('s' of _strcpy) 0x54 ('t' of _strcpy) 0x52 ('r' of _strcpy) 0x43 ('c' of _strcpy) 0x50 ('p' of _strcpy) 0x59 ('y' of _strcpy) 0x82 (terminate label) ; this section tells ZLINK the name of the one label that this ; module can resolve, if more than one label can be resolved ; then multiple 0x26 sequences can be included. 0x82 (escape) 0x2e (flag end of list) ; terminate the list of labels we can resolve 0x82 (escape) 0x2d (flag entry to cseg section) 0xcd (call .....) At this point the code continues exactly as per a normal .O file, until the terminating 0x82, 0x40 has been seen. at this point either a new .O file will be defined with a 0x3b sequence, or .... 0x3d: terminate the library: following the terminating 0x82, 0x40 of the last .O module in the library, comes the sequence: 0x82 (escape) 0x3d (flag) which marks the end of the library.