Path: news1.icaen!news.uiowa.edu!news.physics.uiowa.edu!math.ohio-state.edu!howland.erols.net!news.mathworks.com!uunet!in3.uu.net!news.nacamar.de!news-kar1.dfn.de!news-stu1.dfn.de!news-mue1.dfn.de!news-nue1.dfn.de!news-lei1.dfn.de!news.uni-leipzig.de!news.th-zwickau.de!news.tu-chemnitz.de!nowhere.uucp!fachat From: fachat@physik.tu-chemnitz.de (Andre Fachat) Newsgroups: comp.sys.atari.8bit,comp.sys.atari.programmer,comp.sys.apple2.programmer Subject: 6502 binary format & xassembler Date: 13 Nov 1996 11:28:57 GMT Organization: TU Chemnitz Lines: 263 Message-ID: <56cbdp$at6@narses.hrz.tu-chemnitz.de> NNTP-Posting-Host: vandyke.physik.tu-chemnitz.de X-Newsreader: TIN [version 1.2 PL2] Xref: news1.icaen comp.sys.atari.8bit:39510 comp.sys.atari.programmer:3890 comp.sys.apple2.programmer:7826 Hi there! After the discussion has been going on for a while in the cbm newsgroups, I decided to ask other people what they think about it. I have designed a 6502 relocatable binary file format binary. This format is preliminary and I'm still collecting ideas as how to make it more useful. I also have an assembler (written in ANSI-C) that can produce this format. But first I like to here your comments, esp. what you think about the usefulness for an 65816, as I don't have any info on this one. Thanks André ----------------------------------------snip--------------------------------- 6502 binary relocation format V0.9, as of 02nov1996 --------------------------------------------------- (c) André Fachat (a.fachat@physik.tu-chemnitz.de) 0) What it's for? With some new 6502/C64/C128 operating systems comes the need for a new binary format that allows relocating an assembly language program to a different location. This text tries to find a) a good solution to this problem for the 6502 CPU and b) an assembler source format to use this format in a general manner. It doesn't try to define or discuss object file or library file format, which can be implemented differently by different assemblers. 1) 6502 specifics The 6502 has the special feature of a 'zeropage', i.e. a very limited memory address range used for special addressing modes. So the format should not only provide a means to relocate absolute addresses but also zeropage addresses. The stack is also very limited. A binary format should provide a measure of how much stack space is needed for the application. An issue still to be discussed should be if stack addresses should be relocated and how. The C64 basic interpreter uses a lot of the stack, for example. But I tend to leave the (limited) stack for its real purpose, as stack! Such limits should be defined as 2 byte values, even if the 6502 only has a range of 1 byte. But the 65816 behaves differently (?). Another problem is, that an address can be 'split', i.e. you can just use the high byte or the low byte separately in an opcode. This gives need to a special relocation table format, that can cope with half-address references. 2) assembler source format (as of xa-2.1.0d, 02nov1996) As already used in other formats, the assembler uses three different segment types, i.e. text (the actual program code), data (initialized variables), and bss (uninitialized variables). In addition to that, the 6502 format also includes a zeropage segment type, to allow zeropage variables to be relocated. This zeropage segment is like a bss segment, in that only the length, but not the data is saved. In 2.1.0 there is a way to temporarily disable the creation of relocation table entries. This way absolute code can be inserted into a file. This code should then be copied to the right location at runtime. (Later versions will also provide a way to 'embed' relocatable files in an absolutely addressed code. At least I want to build some operating system ROMs with that...) 2.1) allocation of data segment/zeropage segment address space The assembler switches between the different segments by the means of ".text", ".data", ".bss" and ".zero" pseudo opcodes. The text segment contains the program code. Data holds the initialized data, while bss and zero segments contain uninitialized data for normal/zeropage address space. Everything that is between one of these segment opcodes and the next segment opcode gets into the corresponding segment, i.e. labels, assembled code etc. The text and data segments are saved in the file, while for the bss and zero segments only the length is saved in the file. 2.2) referencing data/bss/zeropage addresses One problem with the 6502 is, that it cannot load an address within one step or assembler opcode. So an address is loaded with standard byte opcodes, like "lda # init adr, Lunix-Adrlist -> init-adr, list of exception vectors etc...) (Should I drop this one?) - StackSize type=2; len=4; content= data word describing the minimum needed stack size. The OS should add an appropriate value for it's IRQ routines and stuff. --------------------------------------------------------------- The text and data segments are just the assembled code. The relocation tables are (each): { [255,...,255,] offset of next relocation (b), typebyte|segmentID [, low_byte] }+ where typebyte is one of WORD $80 2 byte address HIGH $40 high byte of an address LOW $20 low byte of an address and segmentID stands for the segment the reference points to: 0 absolute value 1 text segment 2 data segment 3 bss segment 4 zero segment The offset is a one byte value only. If the difference between the last relocation address and the next one is larger than 254, a 255 is put in the offset byte, and 254 is substracted from the difference, thus allowing to continue without a zero offset byte. A zero offset byte ends the relocation table. The first offset is computed from the segment base address-1, to avoid a 0 value in the first entry. --------------------------------------------------------------- A format for the external refernces list (i.e. a list of undefined references) is not (yet) defined --------------------------------------------------------------- The global list is: { "global_label_name_in_asc",0, segmentID, value.w }+ ..byt $00 --------------------------------------------------------------- This approach allows a) using BLOCK transfers, as no relocation info is hidden within the code or data itself; b) It needs no (not much) side-storage, as a segment can be read using block transfers and then, while reading the relocation table, being relocated on the fly. The only side-storage is the list of segments with corresponding memory offsets. See the provided basic 'loader' code. --------------------------------------------------------------- Possible Changes to the format are: - put the minimum stack size into the file header, not into an option - have an additional byte to flag that the relocation table only allows pagewise relocation. Well, this would insert a word at position 2 (i.e. after the initial .byt 1,0 and before the text segment base address.) The flag would then be one out of 16 possible databits. [This change has a high probability, I think....] - Have possibly multiple objects in one file - add a "static data init" function address header option that gets called after loading but before the thing is executed. This could make runtime linking easier, when each object is one function and not a whole program. ----------------------------------------snip--------------------------------- -- André Fachat, Tel:++49-371-531-3551|"I do not feel obliged to believe that the Stadlerstr 17, 09126 Chemnitz, FRG | same God who has endowed us with sense, a.fachat@physik.tu-chemnitz.de | reason, and intellect has intended us to http://www.tu-chemnitz.de/~fachat | forego their use" -- Galileo Galilei