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 _______________________________________________ fpc-devel maillist - [email protected] http://lists.freepascal.org/mailman/listinfo/fpc-devel
