home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
bdsc-2
/
l2-225.ark
/
LI.DOC
< prev
next >
Wrap
Text File
|
1988-05-21
|
9KB
|
257 lines
L225.DOC
Using .REL files with version 2.2.5 of the L2 linker.
July 1984
When portions of a C program compiled with the BDS C compiler are
to be implemented in assembly language, the present version of L2 provides
an alternative to the use of CASM. Formerly, one had to prepare a .CRL
file by running CASM, then assembling the resulting preprocessed file. Now
the assembly language source file can be assembled with Microsoft's M80,
and the .REL file produced by the assembler then linked directly with the
other parts of the program.
As an example, consider the following assembler source for a function
which puts out a character, but substitutes a 'D' for any digit:
ndput::
pop d
pop h
push h
push d
mov a,l
cpi '0'
jc .1
cpi '9'+1
jnc .1
mvi l,'D'
.1: push h
call putchar##
pop d
ret
end
Supposing the above text to be in a file NDPUT.MAC, then the procedure
to assemble it and link it into a C program CND that calls this function is:
A>m80 =ndput
A>l2 cnd ndput.rel
L2 determines that it is to load a .REL file instead of a .CRL file from
the presence of the extension ".rel". L2 will also scan .REL file libraries
that are put together using the library manager LIB.
Here are some advantages of using M80 and the new version of L2 over
the old way of incorporating assembly modules:
(1) it's more convenient and straightforward
(2) assembler syntax is more flexible (labels can
be indented, '$' can be used)
(3) conditional assembly instructions and macros are
available
(4) Z80 source code can be used
(5) modules can have multiple entry points
(6) assembly modules can make external reference to
data in other assembly modules (not just callable
functions)
(7) an assembly module can request that a .REL file be
scanned to satisfy its external references, through
the use of the pseudo-operation '.request'
(8) it is easier for C modules and assembly modules to
make joint use of data in the external area of ram by
the use of dseg's (cf. below)
(9) external variables can be provided with initial values
(also by using dseg's)
On the other hand, the loading or scanning of .REL files by L2 is
slightly slower than with .CRL files, and this version of L2 is larger by
about 1 1/2k, making less ram available to hold the program being linked.
M80 partions code into segments, viz. aseg's, cseg's, dseg's,
and common. Version 2.2.5 of L2 can deal with only two of these --
cseg's and dseg's. The ordinary case is where code and data are in
a cseg. The little example given above was like this, although the
'cseg' directive was not given explicitly. A dseg is useful when a
function written in assembler and a C program both need to refer
to the same external variable. Here is an example where a C program
calls an assembly function to initialize a string to blanks:
/* file tstblank.c */
#include <bdscio.h>
char blanks[41];
main()
{ fillblank();
}
-----------------------------
.comment *
file fillblan.mac *
fillblank::
lxi h,blanks
mvi e,40
mvi a,' '
.1: mov m,a
inx h
dcr e
jnz .1
mvi m,0
ret
dseg
ds 6 ;6 bytes used in bdscio.h
blanks: ds 41
end
----------------------------
A>cc tstblank -e1000
A>m80 =fillblan
A>l2 tstblank fillblan.rel
In such a case, L2 equates the beginning of the dseg with the beginning
of the external data area, which in this example was given as 1000H when
the program was compiled. When dseg's are used, some address is ordinarily
given using the compiler '-e' option, so that L2 can tell what offset
to use for the data segment. When the C program was not compiled with the
'-e' option, or when the main module is a .REL file, this address can be
supplied to the linker using its '-e' option (new to this version):
A>cc tstblank
A>m80 =fillblan
A>l2 tstblank -e 1000 fillblan.rel
So long as dseg's contain only labels and 'ds' or 'org' directives,
their use will have no impact on the length of the code file produced
by L2; however, if any real data is put in a dseg with 'db' or 'dw'
directives, the code file will have to be longer to accommodate it.
In the following example, the blank initialized string will be incorporated
into the .COM file:
/* file noth.c */
#include <bdscio.h>
char blanks[41];
main()
{ /* does nothing */
}
-----------------------------
.comment *
file exdata.mac *
dseg
ds 6 ;6 bytes used in bdscio.h
rept 40
db ' '
endm
db 0
end
----------------------------
A>cc noth -e1000
A>m80 =exdata
A>l2 noth exdata.rel
Like CLINK, this version of L2 has a '-z' option which prevents the
zeroing of the external data area which ordinarily is done at the
start of execution of a C program. It might seem that this option
should have been used above -- i.e.:
A>l2 noth -z exdata.rel
It is ok to do this, but not necessary, since L2 would assume that
the '-z' option was intended in any case. (Why zero out the initialization
data before it can be used?)
In the above example, an external symbol 'blanks::' could have
been put in the assembly file, but this could not make any difference
to the way the program works, unless there were another assembly
module referring to this symbol. This is because names associated
with external data are lost in the process of compilation.
According to M80, external symbols have at most seven significant
characters, whereas in .CRL files produced by the BDS C compiler the
name of a function can have up to eight significant characters. This
difference might occasionally cause a problem. In the first example
given in this document, the statement "call putchar##" gives rise to
a reference to the external symbol 'PUTCHAR?', where the '?' is wild --
it matches the end of another external symbol or any eighth character
in another external symbol. So, if there happened to be a C function
called 'putchart', e.g., this might be called instead of the intended
function 'putchar'. L2 will not warn you about this. Nasty situation.
In case there is an external data area defined through dseg's but
not in a compiled main program in C, the linker will have to decide where
the external data area ends according to what it finds in the dseg's.
To make sure that it decides correctly, define a symbolic address at the
end of the last data. E.g.
dseg
mpointer: ds 2
mbuffer: ds 80h
dummy:
end
Without the symbol 'dummy', L2 would think the data area ended at the
beginning of mbuffer, instead of at the end.
Large programs that require a 2nd disk phase pass through the .CRL
and .REL files and which also have initialization data defined in
dseg's will sometimes require all code to be linked in before any
dseg's are encountered, and it may also be necessary to arrange the data
so that it will be loaded in order of increasing memory addresses.
Finally, here are some notes about the source files for version
2.2.5 of L2:
L2.C [perhaps called L225.C]
The main program, adapted from David Kirkland's version (which
came from Scott Layson's version).
RDRL.MAC
A function to read an item from a .REL file bit stream.
SPR.MAC
Assembly language version of the standard library function _spr,
which is called by printf. Needs about 2 pages less code than
the C version. (This and RDRL could fairly easily be converted
to .CSM files -- some symbol names with '.' or '_' might have
to be changed.)
CHARIO.MAC
Assembly language version of Scott Layson's CHARIO.C. Needs about
2 pages less code than the C version.
BDS.LIB
Include file for the .MAC functions. (This is the same as the
standard version of this file, but has a few extra symbols defined.)
There is a note on compilation and linking in L2.C. If you don't need to
make a new L2.COM file, you can easily do so. Well, what I mean to say is
that a version 2.2.5 of L2 can be most readily built up if a version 2.2.5
of L2 is already available, in which case the procedure is:
A>m80 =rdrl
A>m80 =spr
A>m80 =chario
A>cc l2 -e5100
A>l2 l2 rdrl.rel spr.rel chario.rel
If the L2.COM [possibly called L225.OBJ] which accompanies this document is
for some reason unusable, a version 2.2.5 could (I suppose) be brought up
from the first two of these files and the original CHARIO.C by editing RDRL
into .CSM format, and using CASM, ASM, and an older L2 or CLINK. The '-e'
address would have to be adjusted upwards.
I do not know how, or whether, this version of L2 works with CDB. I have
no specific reason to think that it wouldn't work, but I haven't tried it.
It is possible that .REL files produced by D.R.'s RMAC can be loaded by
L2, but that's something else I haven't tried.
Greg Lee
631B 10th Ave
Honolulu, HI 96816