Shop OBEX P1 Docs P2 Docs Learn Events
Spin Object Binary Structure — Parallax Forums

Spin Object Binary Structure

jazzedjazzed Posts: 11,803
edited 2008-07-11 19:27 in Propeller 1
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.

{{
'=============================
'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

  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-07-10 07:19
    Not quite, the format for a spin binary goes like this
    ---
    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
    ---
  • hippyhippy Posts: 1,981
    edited 2008-07-10 14:22
    My interpretation is that the program has the following format ...

    .------------------------.
    | Program Header         |
    |------------------------|------------------------.
    | Objects                | Top-Level Object       |
    |                        | Second Object          |
    |                        | :                      |
    |                        | Last Object            |
    |------------------------|------------------------'
    | VAR area               |
    |------------------------|
    | Stack area             |
    `------------------------'
    
    
    



    Each object has the following format ...

    .------------------------.
    | Pointer to next Object |
    |------------------------|------------------------.
    | Method Table           | Pointer to first PUB   |
    |                        | Pointer to second PUB  |
    |                        | :                      |
    |                        | Pointer to last PUB    |
    |                        |------------------------|
    |                        | Pointer to first PRI   |
    |                        | Pointer to second PRI  |
    |                        | :                      |
    |                        | Pointer to last PRI    |
    |                        |------------------------|
    |                        | Pointer to first OBJ   |
    |                        | Pointer to second OBJ  |
    |                        | :                      |
    |                        | Pointer to last OBJ    |
    |------------------------|------------------------'
    | DAT Area               |
    |------------------------|
    | PUB/PRI Method code    |   In source file order
    `------------------------'
    
    
    
  • jazzedjazzed Posts: 11,803
    edited 2008-07-10 17:46
    The rectangular maps make it much easier to see [noparse]:)[/noparse]

    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?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • Jasper_MJasper_M Posts: 222
    edited 2008-07-10 19:40
    I think the structure really is

    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
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-07-10 21:22
    jazzed said...
    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.

    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.
  • hippyhippy Posts: 1,981
    edited 2008-07-11 17:13
    I should really have called those "pointers" as "links" in my diagram.

    @ 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.
  • Jasper_MJasper_M Posts: 222
    edited 2008-07-11 18:05
    hippy: most of that is from http://www.cliff.biffle.org/software/propeller/binary-format.html

    except for the var offset, which I found by analyzing hex dumps.
  • jazzedjazzed Posts: 11,803
    edited 2008-07-11 19:27
    Clearly 0x13 is correct as number of sub-objects.
    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
Sign In or Register to comment.