Spin Object Binary Structure
jazzed
Posts: 11,803
Please review this .spin object binary structure interpretation for errors.
The·bytes omit the var space, stack markers, and stack.
Some of this infomation is described on the wiki and in the Prop manual.
7/11 Added: My guess for the number after·Method pointer was wrong, it is
apparently the number of local variables used by the given method.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (jazzed) : 7/14/2008 10:41:52 PM GMT
The·bytes omit the var space, stack markers, and stack.
Some of this infomation is described on the wiki and in the Prop manual.
7/11 Added: My guess for the number after·Method pointer was wrong, it is
apparently the number of local variables used by the given method.
{{ '============================= 'A Spin Object Binary Struture '============================= }} {{ Given the objects shown below, a .binary will be produced as: obchain.spin: +- myobj.spin: [noparse][[/noparse]4] +- myobj2.spin: 000000 00 b4 c4 04 6f ca 10 00 5c 00 88 00 2c 00 8c 00 000010 28 00 02 04 1c 00 00 00 28 00 04 00 28 00 0c 00 000020 28 00 14 00 28 00 1c 00 fe ed fa ce 36 3f d6 4a 000030 36 3f d4 4b 04 7a 32 00 14 00 02 01 10 00 00 00 000040 14 00 04 00 fe ed 11 11 32 00 00 00 10 00 02 00 000050 0c 00 00 00 fe ed 22 22 32 00 00 00 Reformatted as longs: 000000 04c4b400 0010ca6f 0088005c 008c002c 000010 04020028 0000001c 00040028 000c0028 000020 00140028 001c0028 cefaedfe 4ad63f36 000030 4bd43f36 00327a04 01020014 00000010 000040 00040014 1111edfe 00000032 00020010 000050 0000000c 2222edfe 00000032 00000000 Reformatted as words with annotations: 000000 b400 04c4 ca6f 0010 005c 0088 002c 008c obj vars stk PUB isp 000010 0028 0402 001c 0000 0028 0004 0028 000c noff NOM+ PUBp PUBv Obj1 Obj2 000020 0028 0014 0028 001c edfe cefa 3f36 4ad6 Obj3 Obj4 Cookie PUB bytes 000030 3f36 4bd4 7a04 0032 0014 0102 0010 0000 noff NOM+ PUBp PUBv 000040 0014 0004 edfe 1111 0032 0000 0010 0002 Obj1 Cookie PUB noff NOM+ 000050 000c 0000 edfe 2222 0032 0000 0000 PUB prm? Cookie PUB bytes eol Flattened with comments: 00 b400 ' clkfreq low 02 04c4 ' clkfreq hi 04 ca6f ' sum byte, clkmode byte 06 0010 ' (obj) object start addr 08 005c ' (vars) variables start 0A 0088 ' (stk) stack start 0C 002c ' (PUB) obchain first PUB method start 0E 008c ' (isp) initial stack pointer value 10 0028 ' (noff) Next object offset? $10 + $28 = $38 12 0402 ' (NOM+) number of objects, number of methods+1 14 001c ' (PUBp) obchain PUB pointer from OBJ = $10 + $1C 16 0000 ' (PUBv) number of bytes used for locals in method (locals*4) 18 0028 ' (Obj1) myob[noparse][[/noparse]0] address start $10 + $28 1A 0004 ' myob[noparse][[/noparse]0] var offset 1C 0028 ' (Obj2) myob[noparse][[/noparse]1] address start $10 + $28 1E 000c ' myob[noparse][[/noparse]1] var offset 20 0028 ' (Obj3) myob[noparse][[/noparse]2] address start $10 + $28 22 0014 ' myob[noparse][[/noparse]2] var offset 24 0028 ' (Obj4) myob[noparse][[/noparse]3] address start $10 + $28 26 001c ' myob[noparse][[/noparse]3] var offset 28 edfe ' (Cookie) end of obchain declarations 2A cefa 2C 3f36 ' (PUB) the obchain first PUB method bytecode start 2E 4ad6 30 3f36 32 4bd4 34 7a04 36 0032 38 0014 ' (noff) myobj start ? Next object offset ? $38 + $14 = $4C 3A 0102 ' (NOM+) number of objects, number of methods+1 3C 0010 ' (PUBp) PUB start pointer $38 + $10 = $48 3E 0000 ' (PUBv) number of locals in method 40 0014 ' (Obj1) myobj2 $38 + $14 = $4C? 42 0004 44 edfe ' end of myobj declarations 46 1111 48 0032 ' myobj PUB 4A 0000 4C 0010 ' myobj2 start ? Next object offset ? $4C + $10 = $5C 4E 0002 ' (NOM+) number of objects, number of methods+1 50 000c ' PUB start $4C + $C = $58 52 0000 54 edfe ' end of myobj2 declarations 56 2222 58 0032 ' myobj2 PUB 5C 0000 ' end of object list obchain.spin: CON ' test clock settings _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ ob[noparse][[/noparse]4] : "myobj" DAT cookie long $cefaedfe PUB main dira |= 1 repeat outa ^= 1 --- myobj.spin: OBJ ob : "myobj2" DAT cookie long $1111edfe PUB main ------- myobj2.spin: DAT cookie long $2222edfe PUB main }} {{ Another header example: 0000 B400 04C4 846F 0010 08C8 0A48 003C 0A4C obj vars stk PUB isp 0010 0160 0208 002C 0000 0060 0004 00AB 0004 noff NOM+ PUB1 M2 M3 0020 00F7 0004 0143 0190 0153 0000 015A 0000 M4 M5 M6 M7 0030 0160 0004 0614 0130 FACE FEED 3701 3824 Obj1 Obj2 Cookie PUB1 bytes 0040 351E 013A 00C2 0906 }}
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (jazzed) : 7/14/2008 10:41:52 PM GMT
Comments
---
Header
---
----
Chain section
----
0-offset to next object in chain
2-offset from current var section to var section of next object in chain?
----
PUB section
This is a list of offsets and stack sizes increases for PUB methods
Only one pub method in this example
----
4-offset from start of object to start of method code
6-number of (longs or bytes?) to increase stack pointer by
---
PRI section
Same as pub only pri section
---
8-offset from start of object to start of method code
A-number of (longs or bytes?) to increase stack pointer by
---
Sub Objects
Lists offsets to the sub objects of this object
---
C-offset from start of current to start of the sub-object
E-offset from start of the current var section to the var section of the sub-object
---
DAT section
---
---
More objects
---
---
VAR section
---
---
Stack
---
---
Free memory
---
Each object has the following format ...
This is all consistent with what the bytes show. Seems the "number of longs to increase the stack" makes more sense for a method than just a number of parameters. How does the compiler distinguish between PUB and PRI in the method tables?
Steven, your work on DOL prompted my curiousity. I'm able to load/run an "application" in my own experiments, but not one that has additional objects. I assume that the "standard" must be followed for everything to work perfectly. Looking at DOL2, it was not clear where the object details were being handled.
Being able to completely replace objects in runtime rather than just adding them seems moderately difficult. Has anyone tried this with success?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OBJ HEADER:
2 byte size (aka. offset to next obj), not including VAR
1 byte number of PRI+PUB+1
1 byte number of direct sub objs
FUNCTION LIST
2 byte offset to the function
2 byte number of locals
SUB-OBJECT LIST
2 byte code offset
2 byte VAR offset (from the beginnign of the VAR region of current object)
All the offsets are from the beginning of the OBJ HEADER logn.
EDIT: Also, all the objects are long-aligned. Offsets in bytes. PUB routines are before PRI routines. For indexed objects, an entry in the object list is made, with the same code offset but different var offset (if it has vars).
Post Edited (Jasper_M) : 7/10/2008 7:50:19 PM GMT
Thats strange, I've been loading and running tv_text which has the tv driver as a subobject under both the original dol and dol2. Yes, the standard has to be followed and it is a bit of mucking around. If you have a look in the DOL_core file the load object method should explain what happens. First I open the file and read in the header. From the header I calculate the amount of PUB, PRI and DAT space by subtracting the start of VAR from the start of the program. Then I calculate the amount of VAR space by subtracting the start of the stack from the start of VAR. After that I allocate memory and copy the PUB, PRI and DAT sections into memory. Then I calculate the offsets to the Method table and VAR space from the current object and copy them into the method table of DOL. Then I calculate offsets for DOL, sd and the heap and run the init method in the just loaded object so that it can find these. Finally I return the position of the object so that other objects can find the new object.
See, all simple :P
When I first started playing around with this, I was able to move objects and swap objects just by playing around with the method table. Having the wrong number of arguments shouldn't cause a problem with the interpreter except that they will be wrong values.
@ jazzed : How does the compiler distinguish between PUB and PRI in the method tables?
It doesn't. It just sorts all links into PUB/PRI/OBJ order. The reasoning for that isn't known. It's not possible to reverse the table to determine which are PUB/PRI without analysing where the calls come from and that's not fool-proof if the links aren't referenced (called) from anywhere.
@ Jasper_M : You could well be correct on the second pair of bytes of the next object link, PUB+PRI+1 and OBJ counts.
except for the var offset, which I found by analyzing hex dumps.
Description 0x12 is wrong ... The consensus here appears to be number of methods+1: PUB+PRI+1
<added text="From Cliff's page (thanks Jasper_M)" />
0x0012 1 This seems to be an offset, in long words from 0x0010, to the start of the outermost SPIN object's data/code.
0x0013 1 Number of sub-objects. For our purposes, 0x00.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (jazzed) : 7/12/2008 4:34:06 AM GMT