views:

169

answers:

3
+4  A: 

In this line:

    printf("%02d: %08X : %08X\n", i, *(x + i), *(x - i));

the x pointer is a character pointer, which after dereferencing gets promoted to an integer with sign extension, which causes all your output values to be either 000000xx or FFFFFFxx depending on the value of bit 7.

Instead, what you probably want to do is use an int pointer to scan through the stack values, instead of a char pointer.

Greg Hewgill
Thanks for answering but unfortunately, I can only mark one as an accepted answer.
NawaMan
+6  A: 

You're looking at individual chars, then casting those to 32-bit integers, which is confusing you. The return address is in the least significant bytes of these four lines:

16: 00000054 : 00000000
17: FFFFFF8B : 00000000
18: 00000004 : FFFFFFFF
19: 00000008 : 00000000

I.e. your return address is 0x08048b54.

Try this instead:

uint32_t *x;
x = (uint32_t *)&x4;
for(i = 0; i < 32; i++)
    printf("%02d: %08X : %08X\n", i, *(x + i), *(x - i));
Martin B
Hi, I've modified the code and now it works (it shows the address I see in the debugger disassembly). :D Thanks. I have one more question if you could please answer. What are the information in between the return address to the first local variable? As you see, there is about 8 bytes in between. You can point me to a source so that you don't need to explain. Thanks again.
NawaMan
The 0xbfaced38 is the frame pointer, see http://en.wikipedia.org/wiki/Function_prologue and http://en.wikipedia.org/wiki/Stack_frame#Structure for explanations. As for the remaining bytes, I'm not so sure... I'm guessing those could be registers that were saved on the stack. If you want to know for sure, take a look at the assembly for DoTestStack() -- very instructive anyway, and that should tell you what's being pushed onto the stack.
Martin B
Thanks a lot. I will take a look at those.
NawaMan
+1  A: 

A good idea if you want to know how this all works is to run your application in a debugger. It's really cut's the crap to figure out what's going on.

Any debugger is OK, however I know windbg best so here's some pointers on where to get started at a slightly modified version of your code, like Greg suggested, you need an int*.

CHANGE:

 char *x = &x4;

TO:

 int *x = &i;

DELETE:

 x = &x4;

MOVE(first variable, before x1):

 int i;

NEW CHANGE(much easeir to read, and doing as previously (x-i) is random/not currently in-scope values):

printf("%02d: %08x : %08x\n", i, x + i, *(x + i));

This change will show effectivly the stack-frame address and the value.

In windbg, get the calls, memory, threads and command windows up so you can see them all. Compile your C code with a compiler, I used MSVC (you can get it for trial for free), compile with the "Visual Studio 20## Command Prompt" with "cl /Zi your.c". Load up Windbg (debugging tools for Windows), press Ctrl+E or use "open executable".

Load the following windows so you can see them all at one time, Calls, Locals, Memory, Threads and Command.

At the command window, put a breakpoint on your DoTestStack with "bu DoTestStack".

start debugging with "g" command.

After you get to the breakpoint, use "p" to single step, you should get the source popped up also, or you can watch the output of your application, after it's running in the for loop, go back to Windbg. Get the memory window up and set it to "Pointers and Symbols" for an address type in "i", it should have the debug information from the compile (/Zi) and will give you a listing of "Pointers and symbols" starting from a pointer to the address of i.

The output should be identical to the test code (after you do the changes I suggested), if you continue to hit p, you will see also that in the memory window you can observe the value for i changing per execution, however as the printf is now printing other values, you will simply see it at the original "0" on the output ;).

You can alternativly use the windbg command dds (note the value for i is 0xb as it's in the middle of the for loop)

0:000> dds i
0018ff24  0000000b
0018ff28  02586bf9
0018ff2c  0018ff24
0018ff30  0018ff38
0018ff34  00401118 a!TestStack+0x8 [c:\temp\a.c @ 33]
0018ff38  0018ff40
0018ff3c  00401128 a!main+0x8 [c:\temp\a.c @ 35]
0018ff40  0018ff88
0018ff44  00401435 a!__tmainCRTStartup+0xf8 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 257]
0018ff48  00000001
0018ff4c  003c1e48

This is identical (exept no symbol support) as the modified test code;

00: 0018ff24 : 00000000
01: 0018ff28 : 02586bf9
02: 0018ff2c : 0018ff24
03: 0018ff30 : 0018ff38
04: 0018ff34 : 00401118
05: 0018ff38 : 0018ff40
06: 0018ff3c : 00401128
07: 0018ff40 : 0018ff88
08: 0018ff44 : 00401435
09: 0018ff48 : 00000001
10: 0018ff4c : 003c1e48
RandomNickName42
Thanks very much for the answer. I will try that out. :D
NawaMan