[fpc-devel] System/370 port. Episode 5 - Addressing data
steve smithers
stevie at collector.org
Fri Feb 10 21:48:20 CET 2012
Episode 5 - Addressing data
This is where I really expose my ignorance of FreePascal internals. I know a
teeny little bit about Delphi so I hope it carries through.
As far as 370 Assembler is concerned, and this probably applies to most
assemblers, there is no inherent difference between data and code, it is just a
label defined as an aide-memoire. There is no reason, for example, why you
can't load an instruction, or part of it, into a register, modify it and store
it back into the program. I have even seen some programs that pull off such
tricks intentionally. I, personally, think shooting is too good for programmers
who get up to these sorts of stunts, but it happens. Conversely, there is no
reason, as far as the processor is concerned, why you cannot branch (370 for
Jump) into the middle of a character array for example. All assembler
programmers have come across this one too, it's called a bug.
So ultimately, it doesn't matter whether we are generating code for a branch
instruction or for a move instruction or anything else we use the same basic
idea using index registers that we have discussed previously. However, it won't
surprise you to learn that there are some complications.
Not all instructions support index registers. But remember that the address A
for an label is given by A := B + D + I where B is the value held in the base
register, D is the displacement held in the instruction and I is the value in
the Index register. This sum is performed by the processor internally. So,
using the example we had previously:
LA R1,(LABELB-PROG)/4096
SLL R1,12
B LABELA-((LABELA-PROG)/4096)*4096(R1)
Let's assume that the A (Add) instruction doesn't support index registers, we
can rewrite the code fragment as:
LA R1,(LABELB-PROG)/4096
SLL R1,12
LA R1,LABELA-((LABELA-PROG)/4096)*4096(R1)
A R1,0(R1)
The final LA puts the address A in register 1 by doing the arithmetic above,
and the A (Add) now specifies a displacement of 0 from base register R1. (we
wouldn't actually do it this way under these circumstances. This is an
artificial example for illustrative purposes only before any assembler
programmers write in)
Right - FreePascal - I'm out on a limb here but... All variables (or constants
or labels for that matter) have to be defined before use to Pascal (See Note 1
at bottom). At the time they are defined, an entry will be built in a symbol
table. Now the symbol table has to point at the storage reserved for the
variable; There are only a limited number of ways it could do that.
1) It could hold the absolute address. That's stupid because it means the
program has to be loaded at the same place all the time.
2) It could hold the address of the variable as a relocatable value whose
value is resolved, either at link-edit time or at program-load time. That
doesn't really help us when we come to accessing dynamic storage or using
shared code. So...
3) So it's my guess that it holds the address as a pointer to a block of
storage allocated on the heap or the stack or wherever else it wants to put it.
and an offset into that block. (plus other stuff like length and type) Sound
familiar? This is base / displacement addressing! It's just that the
displacement isn't limited to 4k and the base isn't in a register.
Or maybe I'm wrong. But I don't think I am. Now the displacement, sorry offset,
won't have the same limitations that 370 code has, but I've already demonstrated
a way to handle this. The only realistic example I can think of that runs
counter to this, is where values are themselves in registers. Then, it's not a
storage reference problem.
Note 1. This isn't strictly true I suppose. You can do something like
With TObject.Create
begin
....
end;
However, the compiler has to create a temporary variable to store this value
in order to access the object, otherwise it's just memory floating around. At
least I think it does!
--
Regards
Steve
More information about the fpc-devel
mailing list