Thank you two for finding this!
I did some disassembling yesterday and have uploaded brt1.s and brt2.s
to my site now:
(I haven't actually assembled
them yet, there may be mistakes)
Some observations:
- The 'chain' format is actually a linked list and not a list of
addresses. Phil and I both got this wrong.
- The "Init" string is an error message if for some reason the B init
chain didn't run or main doesn't look like a function
- The cmdline arguments overwrite part of the init code. There's about
80 bytes of space for them before it overwrites the code that builds the
argv vector
- brt2.s is only to mark the beginning of the stack
I also saw some differences in the bilib code but haven't really
analyzed that part (yet?)
Would be really great if we could get all the files disassembled and
decompiled and restore the source code for everything :)
Best,
Angelo
On 08/06/23, segaloco via TUHS wrote:
The signature
I would expect from binary B code of this era would be
that the generated code from each source file starts with a branch (or
jmp) around the contents of the file, to a "jsr r5, chain" followed by
a zero terminated list of addresses (which I guessed were addresses of
address words that needed to be fixed up).
Looking a little closer I think that is what this is, because each file is an a.out
header, then a jmp, followed by what I presume is B object code, then the destination of
the jmp at that jsr r5 that passes into a routine that I think is then what handles that
0-terminated table of address words. All of the files have a similar bit up to the data
word this opening process increments, so I suspect those are the bounds of brt1, from the
opening vector (that the header of the B object jumps to) to the data flag that gets set
by the inc operation.
My assumption is that the B objects were stamped with a jmp that simply jumped to
whatever the first address past the end was, so then brt1 had to be physically right there
to accept flow. After that point the remaining bits in the B files aren't as
similar, but what I can say is I don't see anything on the tail end of these binaries
that is consistent enough between them to peg as a brt2. Instead each seems to be a
slightly different jumble of interpreter routines themselves. At least I think, this is a
very high level assessment though, I haven't fully broken any of these into
individual parts yet.
By the way, one characteristic of this supposed brt1 code is that it checks that the
first word after the jump in the B object is 40022(8) (which is the in-core address of the
next word in the B object btw). If it is not present, or the B runtime did not set the
data flag indicated above as the end of brt1, then it simply prints "Init\n" on
stdout and exits. Only if both this B "magic number" and the flag indicating
proper entry are set does it seem to proceed rather than just printing Init and exiting.
Not sure what this means, or what the reasoning behind this behavior is, but that
explains the "Init" string in each binary, it is also part of the B runtime.
- Matt G.