converting memory address to relative address

Started by
3 comments, last by mikeman 18 years, 2 months ago
Hello. I decided to solve a problem I had using an array of functions, or simply a pointer to a bunch of functions, the only problem with this is that when I debug my game in assembly, it stores the address of these functions in the ds? I don't even know what the ds is :( I'm a sad panda. Here is what my borg-like debugger says:

CALL DWORD PTR DS:[EAX*4+427B40]        ;  vc_debug.004110F5



The register debug window in vc++ suddenly prints to the window 00427B40 = 004110F5. Well shoot. Why did the debugger get all fancy on me? I don't have the brain power to convert addresses from one form to another. After debugging the program in a few other debuggers to figure out whats going on, I can gather that the DS lies at 0023h. Whatever that means. Can some smart programmer please make sense of what's going on? Thank you. P.S. I have no idea if the topic of this thread has any relevance to the context. I've been googling and well, I know it has somethign to do with memory!
Advertisement
Quote:Original post by ordered_disorder
Hello. I decided to solve a problem I had using an array of functions, or simply a pointer to a bunch of functions, the only problem with this is that when I debug my game in assembly, it stores the address of these functions in the ds? I don't even know what the ds is :( I'm a sad panda.

If you don't know what the ds register is, don't bother debugging in assembly. (hint: it's a segment register)

What are you trying to debug in there? There is probably a better way to do it, whatever it is.
The debugger just probably calculated the EAX*4+427B40 for you and it gave 4110F5, or something like that.

DS is one of the CPU's segment registers (CS,DS,ES,FS,GS) and it used to point at the data segment of the program. I'm not sure how it goes today with 32-bit paging OS's.

Most probably EAX is the index to your array and 427B40 is the base address of the array, EAX*4+427B40 is the address to the index you are referring to, and the whole line CALL DWORD PTR DS:[EAX*4+427B40] calls whatever function should be stored there. If the program hangs on this line, the CALL jump is invalid, which means that the value stored in your array is some random data or a null pointer. You must make certain that the array is properly initialized with valid function pointers.

But the main point I'd like to ask is why do you debug in asm? If you're using vc, the debugger can give you references to the original source code and variables.
In answer to the question of why I'm debugging in assembly, it's because I'm trying to learn it to become a better programmer. Btw, the value of eax at the time was 0, so there's no way that expression could equal the address that the program is calling. I really hope somebody can tell me how that address was calculated.

Clb, I've been doing fine working in assembly for the last few weeks, it's only until today when I tried using array of functions did this crazy data segment come into play. I also scoured google before coming, unlike a lot of forum members. This is a question I do need help on.

And doing the normal calculation of 16*segement + offset isn't giving me the correct linear address, so it has nothing to do with the original MS-DOS setment/offset calculations. If you know whats going on please tell me. Thank you for any all help.
The instruction just does a "call" jump to the address that is contained on [EAX*4+427B40]. Note, it doesn't call the address "EAX*4+427B40". It takes the desired address from the variable whose address is "EAX*4+427B40". If you do a memory dump at that address, you can see that for yourself.

As for DS, it's the data segment and you don't need to worry about it. The arithmetic "16*segment + offset" is not correct for 32-bit assembly. Here, the segments are loaded with selectors for descriptors about the address space. Windows though use the "flat" model, which means that the entire linear address space is in one segment. As I said, just pretend that segments don't exist, as Windows don't really make use of them.

If you want to mess around with it a little yourself:

	LDT_ENTRY ldt;	CONTEXT context;	context.ContextFlags=CONTEXT_ALL;	GetThreadContext(GetCurrentThread(),&context);	GetThreadSelectorEntry(GetCurrentThread(),context.SegDs,&ldt);		int limitHigh = ldt.HighWord.Bits.LimitHi;	limitHigh <<= 24;	unsigned int limit = (ldt.HighWord.Bits.LimitHi << 16) + ldt.LimitLow;    if (ldt.HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;	unsigned int base = (ldt.HighWord.Bits.BaseHi << 24) +  (ldt.HighWord.Bits.BaseMid << 16)+ldt.BaseLow;	cout<<"Segment Base: "<<base<<endl;	cout<<"Segment Size: "<<limit/(1024.0*1024)<<" MB"<<endl;


This prints the base and the size of the DS(data) segment. You'll see that the base is 0 and the size is 4GB and the same is for CS also. So you see that you don't need any conversion from segmented to flat address space.

[Edited by - mikeman on January 29, 2006 5:29:30 AM]

This topic is closed to new replies.

Advertisement