This is my C code
C:\Codes>gdb test -q
Reading symbols from C:\Codes\test.exe...done.
(gdb) list 1,15
1 #include<stdio.h>
2
3 int main()
4 {
5 int a = 12345;
6 int b = 0x12345;
7 printf("+-----+-------+---------+----------+\n");
8 printf("| Var | Dec | Hex | Address |\n");
9 printf("+-----+-------+---------+----------+\n");
10 printf("| a | %d | 0x%x | %p |\n",a,a,&a);
11 printf("| b | %d | 0x%x | %p |\n",b,b,&b);
12 printf("+-----+-------+---------+----------+\n");
13
14 return 0;
15 }
(gdb) set disassembly-flavor intel
And this is the standard output
C:\Codes>test
+-----+-------+---------+----------+
| Var | Dec | Hex | Address |
+-----+-------+---------+----------+
| a | 12345 | 0x3039 | 0022FF4C |
| b | 74565 | 0x12345 | 0022FF48 |
+-----+-------+---------+----------+
This is what I'm seeing in GDB
(gdb) break 7
Breakpoint 1 at 0x40135e: file test.c, line 7.
(gdb) run
Starting program: C:\Codes/test.exe
[New Thread 4044.0xab0]
Breakpoint 1, main () at test.c:7
7 printf("+-----+-------+---------+----------+\n");
(gdb) disassemble
Dump of assembler code for function main:
0x00401340 <+0>: push ebp
0x00401341 <+1>: mov ebp,esp
0x00401343 <+3>: and esp,0xfffffff0
0x00401346 <+6>: sub esp,0x20
0x00401349 <+9>: call 0x401990 <__main>
0x0040134e <+14>: mov DWORD PTR [esp+0x1c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x18],0x12345
=> 0x0040135e <+30>: mov DWORD PTR [esp],0x403024
0x00401365 <+37>: call 0x401c00 <puts>
0x0040136a <+42>: mov DWORD PTR [esp],0x40304c
0x00401371 <+49>: call 0x401c00 <puts>
0x00401376 <+54>: mov DWORD PTR [esp],0x403024
0x0040137d <+61>: call 0x401c00 <puts>
0x00401382 <+66>: mov edx,DWORD PTR [esp+0x1c]
0x00401386 <+70>: mov eax,DWORD PTR [esp+0x1c]
0x0040138a <+74>: lea ecx,[esp+0x1c]
0x0040138e <+78>: mov DWORD PTR [esp+0xc],ecx
0x00401392 <+82>: mov DWORD PTR [esp+0x8],edx
0x00401396 <+86>: mov DWORD PTR [esp+0x4],eax
0x0040139a <+90>: mov DWORD PTR [esp],0x403071
0x004013a1 <+97>: call 0x401c08 <printf>
0x004013a6 <+102>: mov edx,DWORD PTR [esp+0x18]
0x004013aa <+106>: mov eax,DWORD PTR [esp+0x18]
0x004013ae <+110>: lea ecx,[esp+0x18]
0x004013b2 <+114>: mov DWORD PTR [esp+0xc],ecx
0x004013b6 <+118>: mov DWORD PTR [esp+0x8],edx
0x004013ba <+122>: mov DWORD PTR [esp+0x4],eax
0x004013be <+126>: mov DWORD PTR [esp],0x40308c
0x004013c5 <+133>: call 0x401c08 <printf>
0x004013ca <+138>: mov DWORD PTR [esp],0x403024
0x004013d1 <+145>: call 0x401c00 <puts>
0x004013d6 <+150>: mov eax,0x0
0x004013db <+155>: leave
0x004013dc <+156>: ret
End of assembler dump.
(gdb)
The address for variables a
& b
is supposed to be at 0x22ff4c
& 0x22ff48
respectively
(gdb) print &a
$1 = (int *) 0x22ff4c
(gdb) print &b
$2 = (int *) 0x22ff48
However, if you look at the following GDB disassemble output, the address was not 0x22ff4c
& 0x22ff48
, but 0x0040134e
& 0x00401356
0x0040134e <+14>: mov DWORD PTR [esp+0x1c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x18],0x12345
I've also debug this on x32dbg but getting the same address too.
I'm confused here. What was the 0x0040134e
& 0x00401356
if they are not the memory addresses for variables a
& b
?
The static variables are stored in the data segment of the memory. The data segment is a part of the virtual address space of a program. All the static variables that do not have an explicit initialization or are initialized to zero are stored in the uninitialized data segment( also known as the BSS segment).
How are variables stored in assembly? The assembler associates an offset value for each variable name defined in the data segment. Each byte of character is stored as its ASCII value in hexadecimal. Each decimal value is automatically converted to its 16-bit binary equivalent and stored as a hexadecimal number.
This system function allows you to set the highest available address in the data section. This system call takes one parameter, which is the highest memory address needed to be set. This value is stored in the EBX register. In case of any error, sys_brk() returns -1 or returns the negative error code itself.
Typically local variables are put on the "stack". This means that the compiler assigns an offset to the "stack pointer" which can be different depending on the invocation of the current function. I.e. the compiler assumes that memory locations like Stack-Pointer+4, Stack-Pointer+8, etc.
0x0040134e <+14>: mov DWORD PTR [esp+0x1c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x18],0x12345
No, 0x0040134e
and 0x00401356
are not addresses for variables a
and b
. Instead they are address of the instruction in code, i.e. instruction pointer IP. a
and b
are initialized in these lines:
0x0040134e <+14>: mov DWORD PTR [esp+0x1c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x18],0x12345
Here the address of a
and b
are esp+0x1c
and esp+0x18
respectively where esp
is the stack pointer. As address you are getting 0x22ff4c
and 0x22ff48
from which you can easily deduct that current esp
is 0x22ff4c - 0x1c
.
Please note the this answer ignores the underlying virtual memory management or other related memory management matters of operating system, i.e. on most architecture 0x22ff4c
and 0x22ff48
will be virtual memory address, not the real physical address of your RAM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With