fujidude Posted January 18, 2016 Share Posted January 18, 2016 I've been digging about on binary object files and how they are put together. There are the standard kind, and then some SDX specific ones. To start with, I want to ask a question about the standard ones. I understand they start with: FFFF then another word designating the start address to load into, then one more word with the end address. That's 6 bytes in that header. What I was wondering is if there are additional segments, do they all start with the same kind of 6 byte header, or do they just have the start and end address words and skip the FFFF. In other words, is the FFFF only at the start of the file but not on each segment? Quote Link to comment Share on other sites More sharing options...
joyfulcoder Posted January 18, 2016 Share Posted January 18, 2016 The FFFF is optional for later segments. Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted January 18, 2016 Share Posted January 18, 2016 The $FFFF signature is only necessary at the top of the file (i.e. ahead of the first segment). However, while subsequent headers need only contain start and end (4 bytes), if they happen to also have the $FFFF header, it should ignored by the loader (and this is very trivial to do). SDX binaries are a different matter, since the header signatures define the type of the segment which follows. Quote Link to comment Share on other sites More sharing options...
fujidude Posted January 18, 2016 Author Share Posted January 18, 2016 Thanks guys, that clears that up. Quote Link to comment Share on other sites More sharing options...
xxl Posted January 18, 2016 Share Posted January 18, 2016 so.. binary file: FF FF FF FF FF FF FF means load FF to FFFF adress :-) Quote Link to comment Share on other sites More sharing options...
Rybags Posted January 18, 2016 Share Posted January 18, 2016 There's also the Init and Run procedure. Any time a segment is loaded, an indirect call is made to whatever address is pointed to by $2E2 - this address is pre-initialized to point to an RTS before each segment read starts. At the end of the file, the file is run by a JMP indirect through $2E0. No return is expected. Some Doses support return but it shouldn't be relied on. 1 Quote Link to comment Share on other sites More sharing options...
phaeron Posted January 18, 2016 Share Posted January 18, 2016 so.. binary file: FF FF FF FF FF FF FF means load FF to FFFF adress :-) Actually, no... it's treated as an empty EXE file by DOS 2. Atari documented the details of the executable load format in the DOS 2 and 2.5 manuals. The key rule that allows FFFF before segments is that you are allowed to concatenate load files together with the Copy File command. Since the source files are required to begin with FFFF, this means that any segment in a load file can have it too. What they didn't document is that a load file is not required to have any segments, so that an executable file consisting solely of the FFFF signature is a valid one. This means that FFFF is never a valid segment start address and loaders have to skip them even if it occurs multiple times in a row. That's actually what DOS 2 does, if you check the CIO calls it does during a load. That having been said, you do not want to make executables that have embedded FFFFs. Not all loaders handle them properly, and in particular some PC-based programs will crash if they encounter it. The DOS manuals also precisely document the behavior of the run vector. It is always invoked at EOF, no matter when RUNAD is written during the load. No run vector is supposed to return to DOS, same as an RTS from the run vector. When multiple run vectors are present, only the last one takes effect. Many loaders don't support these behaviors, though. Finally, DOS 2 defines IOCB #1 as the load IOCB. Also not universal. What I haven't been able to find is authoritative documentation on aborting a load from an INIT vector. JMP (DOSVEC) seems to be the universal way of doing so, but I haven't found any official DOS reference for that yet. 3 Quote Link to comment Share on other sites More sharing options...
fujidude Posted January 18, 2016 Author Share Posted January 18, 2016 Yeah, this from Mapping The Atari (revised edition): 738-739 ZE2-ZE3 INITADInitialization address read from the disk. An autoboot file mustload an address value into either RUNAD above or INITAD. Thecode pointed to by INITAD will be run as soon as that location isloaded. The code pointed to by RUNAD will be executed onlyafter the entire load process has been completed. To returncontrol to DOS after the execution of your program, end yourcode with an RTS instruction. Quote Link to comment Share on other sites More sharing options...
xxl Posted January 18, 2016 Share Posted January 18, 2016 (edited) Atari documented the details of the executable load format in the DOS 2 and 2.5 manuals. The key rule that allows FFFF before segments is that you are allowed to concatenate load files together with the Copy File command. Since the source files are required to begin with FFFF, this means that any segment in a load file can have it too. What they didn't document is that a load file is not required to have any segments, so that an executable file consisting solely of the FFFF signature is a valid one. This means that FFFF is never a valid segment start address and loaders have to skip them even if it occurs multiple times in a row. That's actually what DOS 2 does, if you check the CIO calls it does during a load. no, this means that before landing adress at FF FF signature FF FF is mandatory. and if DOS skip bytes after signature that means binary loader in DOS has bug. unless you agree that valid binary file signature is (FF FF) * N not FF FF :-) --- besides... command: binary save in DOS properly create such binary file (eg: FF FF FF FF FF FF C0) Edited January 18, 2016 by xxl Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted January 18, 2016 Share Posted January 18, 2016 That's how I handle it: grab two bytes; if a and b = $FF, ignore and grab next two. If not, it's the start address. Quote Link to comment Share on other sites More sharing options...
phaeron Posted January 19, 2016 Share Posted January 19, 2016 no, this means that before landing adress at FF FF signature FF FF is mandatory. and if DOS skip bytes after signature that means binary loader in DOS has bug. unless you agree that valid binary file signature is (FF FF) * N not FF FF :-) --- besides... command: binary save in DOS properly create such binary file (eg: FF FF FF FF FF FF C0) No, this just means that DUP has poor validation. There's no reason for DOS to support a special case specifically for this, unless you believe there's an actual useful reason for or any possible way that DOS could load a single byte into the high byte of the IRQ vector. Quote Link to comment Share on other sites More sharing options...
xxl Posted January 19, 2016 Share Posted January 19, 2016 No, this just means that DUP has poor validation. There's no reason for DOS to support a special case specifically for this, unless you believe there's an actual useful reason for or any possible way that DOS could load a single byte into the high byte of the IRQ vector. so you belive there's an actual useful reason for or any possible way that DOS could load a single byte into any rom area (C000-CFFF; D800-FFFF). if file has block that load data into rom that means it is not binary file? Quote Link to comment Share on other sites More sharing options...
baktra Posted January 19, 2016 Share Posted January 19, 2016 Yeah, this from Mapping The Atari (revised edition): 738-739 ZE2-ZE3 INITAD Initialization address read from the disk. An autoboot file must load an address value into either RUNAD above or INITAD. The code pointed to by INITAD will be run as soon as that location is loaded. The code pointed to by RUNAD will be executed only after the entire load process has been completed. To return control to DOS after the execution of your program, end your code with an RTS instruction. I am just curious, What happens when a segment is loaded to addresses 735-741. Does this qualify as an INIT jump too? Quote Link to comment Share on other sites More sharing options...
Rybags Posted January 19, 2016 Share Posted January 19, 2016 With Init and Run it doesn't matter how the data gets there. It can be loaded direct, it can be loaded overlayed as part of a bigger data chunk although it's not a good idea to just load big chunks into the OS work area. It could also be set by the program. e.g. an Init section could execute and set the Run address itself rather than have it loaded. Though in practice you'd have to question why, and I doubt many if anything would do it. Setting the Init address inside the program should have no effect. When an Init section returns the Init address is reinitialized to point to an RTS. Quote Link to comment Share on other sites More sharing options...
fujidude Posted January 19, 2016 Author Share Posted January 19, 2016 e.g. an Init section could execute and set the Run address itself rather than have it loaded. Though in practice you'd have to question why, and I doubt many if anything would do it. I wonder if it was ever done to make cracking a program just a little less easy. Quote Link to comment Share on other sites More sharing options...
phaeron Posted January 20, 2016 Share Posted January 20, 2016 so you belive there's an actual useful reason for or any possible way that DOS could load a single byte into any rom area (C000-CFFF; D800-FFFF). if file has block that load data into rom that means it is not binary file? No, I'm saying that it's not a binary file because Atari never specifically documented it would work and it doesn't actually work. It doesn't work on Atari DOS 2.0S. It doesn't work on Atari DOS 2.5. It doesn't work on SpartaDOS 3.2g. It doesn't work on SpartaDOS 4.0. It doesn't work on SpartaDOS 4.0 X.COM. It doesn't work on MyDOS 4.55. It doesn't work on Turbo-DOS XE. In summary, using FFFF as a segment start address was never documented as supported, doesn't work on a large selection of contemporary DOSes, and doesn't have a use. Therefore, practically, it isn't supported in executable files. Quote Link to comment Share on other sites More sharing options...
Rybags Posted January 20, 2016 Share Posted January 20, 2016 I wonder if it was ever done to make cracking a program just a little less easy. Doubtful. Most game software ever made booted up and read raw sector data. Using a Dos format wastes 3 bytes per sector plus means the overhead of having to keep at minimum a read-only filesystem in memory. Though a rudimentary read-only Dos can be done very cheaply, if just file numbers are used instead of doing filename processing it could probably be done in under 300 bytes. Quote Link to comment Share on other sites More sharing options...
xxl Posted January 20, 2016 Share Posted January 20, 2016 In summary, using FFFF as a segment start address was never documented as supported Atari did not specify what will work (Atari never specifically documented load adress f000 would work also) but outline a standard (signature is ffff not n*ffff), and fffff as the load address fits in the standard and DOS can create such file, can't load it. what about starting address higher than end address - fit in standard? Atari documented it? binary load succeeds in spite of the creation such file in dos - reports an error. so, you can not reason about the standard by what functions opetares because as I showed on two cases DOS not being able to handle a file created by himself and handle the file which he can not create. Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted January 20, 2016 Share Posted January 20, 2016 (edited) Sigh... I infer from this polemic that XBIOS supports loading a segment at $FFFF then. Edited January 20, 2016 by flashjazzcat 3 Quote Link to comment Share on other sites More sharing options...
Rybags Posted January 20, 2016 Share Posted January 20, 2016 To me even though it makes little sense it should be valid to have a load start or end of $FFFF as valid. Using the Low and High = $FF as a "skip signature" method to me is a shortcut to save a few bytes programming and also reeks of some of the Y2K paranoia where stuff like inputs of 9-99 99-9 etc had to be tested as well because in the old days were used as EOF flags. Also, though it's not exactly a common thing to do, it's sometimes desirable to just point a section to Rom such that it's not actually loaded to Ram - either by quick/dirty mod to source or patching the object file. OK, sort of contradictory by panning a kludge then promoting another but... Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted January 20, 2016 Share Posted January 20, 2016 But how would you propose to deal with optional binary signatures in any but the first segment aside from checking if Low AND High = $FF? It's only a shortcut if you don't set a flag once a single signature is skipped in order to avoid skipping next pair of bytes if they also happened to both equal $FF. Pragmatically, it may be best practice to allow a segment to point at $FFFF, but in practical terms it's completely unnecessary. There are 14,335 other load addresses in ROM to choose from for patching purposes. Even if one wished to set the IRQ vector direct from the file, the start address would be $FFFE, so none of the above would even matter. Plus which, the matter is moot since - as Avery points out - almost no DOS will load the file correctly. So: create a file containing a segment with a load address of $FFFF and watch it fail on almost all binary loaders but the one which fixes the "issue". Quote Link to comment Share on other sites More sharing options...
xxl Posted January 20, 2016 Share Posted January 20, 2016 no, and I do not earn some extra theory but reason is simple - 7 bytes. BLOAD ldy #$FF - (_IDFFFF-_lbf) ; 2 bytes _lbf sty _IDFFFF ; 3 bytes jsr GET_BYTE sta load_ptr jsr _GET_BYTE sta load_ptr+1 and load_ptr ldy #$00 ; 2 bytes cmp #$ff beq _lbf _IDFFFF equ *-1 Quote Link to comment Share on other sites More sharing options...
pirx Posted January 20, 2016 Share Posted January 20, 2016 Sigh... I infer from this polemic that XBIOS supports loading a segment at $FFFF then. Exactly ))))) And how easy it is to protect against XBIOS loading now when we know - just add second $ff pair and blam, it hangs )))))))))))) Quote Link to comment Share on other sites More sharing options...
xxl Posted January 20, 2016 Share Posted January 20, 2016 @Pirx :-) try :-) Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted January 20, 2016 Share Posted January 20, 2016 Ah... the irony. I just checked my loader and it will already load to $FFFF. Perhaps I can now rewrite it so it's smaller. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.