• Advertisement

Archived

This topic is now archived and is closed to further replies.

how are globals resolved at run time?

This topic is 6013 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was looking through the assembly of a program I was writing, and I realized that when a global was used, its real memory address was used (the exact same thing as &global was printed in assembly output as an operand). How is that address set? When exectly is the global address resolved? Lastly, how come the majority of the replies are to questions that should never have been asked like what should I use ogl or dx?

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Globals have absolute addresses because there, well, global. They live in the global data segment of your program, from the time your program is launched, untill the program dies. When those addresses are assigned is usually by the linker (this is it''s main, and really it''s only job). Even cooler (for certian, rather small, values of cool) look at what happens with

int glbl = 7;

vs

class foo {
int m_glbl;
public:
foo() : m_glbl(7);
} C_glbl;

You can also compare;

char gstr_arr[] = "guess where I live";
with
char *gstr_ptr = "guess where I live";

As to your second question, not everyone knows what a linker does, but everyone knows you should use OpenGL, even when programming for the XBox.

Share this post


Link to post
Share on other sites
Ok, I get it now. I thought memory addresses were absolute. I had to check that out myself, with the program was running in two simultaneous windows, and the addresses were the same.
This is what happens when people teach themselves things, and always use and IDE. I don''t know how these things actually work.

So, how does a program pass memory between itself and a dll? All the addresses would be wrong.

Share this post


Link to post
Share on other sites
Each process has it''s own "address space". That is, what is at addres 0x00001000 for one process is different to what''s at address 0x00001000 for another. This is how you achieve "process isolation" - one process can not access the memory in another process (unless it wants it to, by using shared memory for example).

This scheme is known as virtual memory, since every single memory access your program does must be translated by the processor into a physical address. Every process has a table of virtual addresses, and their corresponding physical address. It''s up to the OS to maintain that table.

Now, as for passing memory addresses to a dll, when you call a dll function, it still uses your process'' address space, so that any memory locations in your process are also valid in the dll. This means that a global variable in a dll is different for all the processes accessing that dll.

That''s just a quick overview, and it''s really a bit more complicated than that, but you get the idea... If you''re really interested in this sort of thing, pick yourself up a copy of a good Operating Systems textbook. I recommend "Operating Systems" by William Stallings.


codeka.com - Just click it.

Share this post


Link to post
Share on other sites
And if you go try writing in someone elses virtual space, you get things like "General Protection Faults" and "Illegal Operations".

Share this post


Link to post
Share on other sites
Thanks for the detailed explanation, it is well apreciated. I am in the process of converting a scripting language, so that instead of compiling to bytecode and executing, it compiles to machine code. I've had a hard time finding good information, references on assembly don't give me enough implementation information (mov eax, somevalue does not really tell me what is going on, it is too simplified), references on the ia-32 spec give too much information.

I'll probably pick up that book just for curiosity's sake, but I think I'll need to find it in the university library when I move in. Too much money for curiosity.

Edited by - Dog_Food on September 8, 2001 12:12:45 AM

Share this post


Link to post
Share on other sites
The story is this.

A global symbol has a corresponding address. This address can correspond to code or data. The computer doesn''t care. In theory, you could execute data if you hardcode a value in a "call" instruction. You could copy code into a data segment if you wanted.

Under Windows, executable files (EXE and DLL) are mapped into the address space described above. This means they are "backed" by disk storage. When your program writes to a page under Windows, the system automatically moves the page to a discardable space in the paging file (main system memory file). This way, one instance can''t harm the data of another, and also the data isn''t changed permanently on disk.

Executables have a preferred, precoded base address. When loading the executable, the system tries to map it at its preferred base address. If this should fail, the system uses the relocation table stored in the file to go through the code and change every global reference by subtracting the preferred address and adding the actual address. This can take some time, so you should always rebase your DLLs using Microsoft''s Rebase.exe utility or the RebaseImage PE helper API.

That pretty much sums it up...

Share this post


Link to post
Share on other sites
Of course, the rebasing is only done once, when the dll is loaded, so it only impacts loading time, not execution time. Besides, well written code won''t contain many global variables anyway. And if you''re an Object Oriented person, you only really need to export one function (the rest are called through object pointers).


codeka.com - Just click it.

Share this post


Link to post
Share on other sites
Thanks Dean Harding and GayleSaver. I guess what I''ll do is something like that to plug in my custom script and connect globals. There will be a relocation table with offsets for globals for each script compiled with its byte code, then upon loading, it will set addresses. External classes and globals will be resolved at run time using a lookup table, and results will be cached. To load the script byte code, the globals are rebased, then the external cached globals in dlls and executables are used. The cached global addresses will be updated when the dll is rebased, or the executable is updated.

Share this post


Link to post
Share on other sites
quote:
Original post by Dean Harding
Of course, the rebasing is only done once, when the dll is loaded, so it only impacts loading time, not execution time. Besides, well written code won''t contain many global variables anyway. And if you''re an Object Oriented person, you only really need to export one function (the rest are called through object pointers).



Yes, but functions have to be rebased as well...any call statements.

Also, most supporting frameworks utilize global variables very extensively anyway...nothing one can do about that.

Share this post


Link to post
Share on other sites
Dog_Food: Unless you want to release your language to your users or to utilize it large-scale, I would advise against writing your own compiler (to machine code) and using an existing language instead.

If you do, though, I would advise limiting its domain to COM. Global variables should never be needed in a good framework. Have your implicit objects handle them by storing them in a table. Don''t get machine-level...

Share this post


Link to post
Share on other sites
As I was writing my scripting language for a game editor, it was getting to the point where it would become easier just to compile the scripting language to machine code rather than to code special interfaces, importing and exporting methods for everything. I am going in the direction of java, with a just in time compiler.

Optimally, in the game editor environment, the user may derive classes from script or editor class types. Data representations must be similar so both the c++ and the script side can access eachother seamlessly. This is not as difficult as it would seem. The only hack thrown in is that virtual functions must be supported through a custom vtable rather than the built in one.

The only machine level support will be for writing new member functions. Class type data, static variables, and globals will be handled with regular c++ classes. External function calls will be hooked up to functions registered in the classes. This was another point, that I want reflection capabilities.

Share this post


Link to post
Share on other sites

  • Advertisement