To: Alpha test group From: Cameron W. Cotrill Re: LX, version 2.0c Date: 11/05/89 After discussion with Joe Wright, LX has been altered with conditional assembly code for type 1, type 3, and type 4. Square brackets were removed from the source so M80 would work. 2.0b would link correctly with Al Hawley's ZML, but not with LINK or SLRNKP. While solving this limitation, I came up with a solution to another type 4 problem. The details follow and I hope are clear. I propose them as guidelines for type 4 coding. The reason for linker problems is the differing ways $MEMRY is treated by the linkers when creating PRL. LINK doesn't mark the contents of $MEMRY as relocatable. SLRNKP does, but marks the wrong byte (this rules it out for type 4's totally). ZML marks the contents as relocatable (in my view the correct way to handle $MEMRY), but can be made to act like LINK. CODEND uses $MEMRY and expects the contents to be the address of the first available byte above the program. This means only ZML in "native" mode can produce PRL's where CODEND works. But hold on - of what use is CODEND in a type 4 anyway? A type 4 is supposed to load as high in memory as possible. All other things being perfect (which they seldom are due to the size of the bitmap), $MEMRY's contents should point to the first byte of the CCP in the case of a type 4! Do we want to allocate our scratch buffers inside Z34 (and possibly DOS)? No, in a type 4, all dynamic buffers should be allocated below the program. CODEND is of no use in this case. But wait... what if we need fixed buffers in the program? In the case of a smart linker that truncates uninitialized DSEG data, the bitmap for the PRL overlays the data space. What if the data space is larger than the bitmap? The type 4 loader was written to cover this. Recall the type 4 loader overlays the 100h long PRL header. The program itself starts in record 2 and will run in place without relocation if the file, starting with record 2, is loaded into TPA starting at 100h. The type 4 program has a Z3ENV header in record 2. At offset 0bh in record 2 the top address+1 of the type 4 program is placed. The type 4 loader examines this address and if it is larger than the end of the bitmap will use this address in calculating the load address for the type 4. The important thing to note here is this address is examined before the type 4 is loaded and relocated. OK, how do we figure out what this address should be? Trial by error? How much code and data will REL libraries add? Let's render unto Caeser those things which are Caeser's. We want the first address after the top of the program here - sounds like a job for $MEMRY! But wait - $MEMRY is broken for type 4's - right? Not here! We haven't allowed the bitmap to corrupt this value at the time the type 4 loader looks at it! All linkers write the value relative to 100h correctly - they just honk up the bitmap information! So, simply put $MEMRY:: here and let the linker do the work. This implies the value is useless to the application, though. It has been altered in who knows what manner. This means that type 4's are not just type 3's assembled to PRL except in trivial cases. However, we can pare a bit of code out since they are not type 3's - like the safety header. The type 4 loader code itself takes care of this. LX puts these ideas to use. Consider what LX does. It loads a file into memory and runs it. The file can load at an arbitrary address (types 1 and 3) or can load as high in memory as possible. If LX itself is a type 4, we can't load anything above it so it makes no sense to even consider the possibility. However, if LX is a type 3, we can load above LX or below LX. A properly written type 3 should be able to decide where to put its scratch data buffers - high or low. Clearly, the buffers should be placed above the type 3 if there is room. Similarly, a type 1 can't load data below itself so it makes no sense to consider the possibility (though here, LX's checking code isn't disabled due to programmer lazyness). LX must also handle possible overlap between itself and the program it loads, but that's another story. ....... 2.0b Error handling corrected for case where LX not an ECP or forced ECP as per Howard Goldstein's suggestions. This is still alpha test so take proper precautions... ....... 2.0a I finally got fed up enough with the limitations of LX to do something about them. Prime on the limitations list was version 1.9 could not be made into a type 4. This was always a pain for me as I often lower the top of tpa below where most type 3's load for testing. Another problem is that LX always loaded code above itself and then moved it to where it ran, adding to the free memory requirements. Finally, LX couldn't load type 4's. LX2.0 fixes all these limitations. The memory management code and loader code is all new. LX will now load a program where it is going to run if it can. Otherwise, it will load it above LX if there is room. Failing that, it will load immediately below LX. Code copy direction (down or up) is noted and the correct move type selected so that overlaps aren't a problem. All the functional features of LX19 were retained. However, ADJMCL was re-written to allow manipulation of the MCL in place and TBUFF is no longer copied to a local buffer in LX before parsing. These changes allowed adding the rather extensive memory management and loader code without making LX take any more room. In fact, I believe LX2.0 is smaller than 1.9. Other sections were re-coded to suit my whims. Files in the alpha test package: LX20-1.COM - type 3 at 100H LX20-3.COM - type 3 at 8000H LX20-4.COM - type 4 LX20.ZZ0 - Source for LX Please observe the usual precautions when testing LX20 and report any bugs or suggestions to me on Ladera. Enjoy!