Mind on alati paelunud, et mis arvuti mälus andmetega juhtub; kus nad mingil ajal on.
Sellele küsimusele on hea vastust otsida C keele ja gdb-ga
Lihtne C kood:
1 #include
2 #include
3
4 int main (void) {
5 int *p1, stack[10];
6 int a = 10;
7 int b = 20;
8
9 p1 = stack;
10
11 *p1 = a;
12
13 p1++;
14 *p1 = b;
15
16 printf("value on top(b) is %d, address %d\n", *p1, p1);
17 *p1 = 0;
18
19 p1--;
20 printf("value on top(a) is %d, address %d\n", *p1, p1);
21 *p1 = 0;
22
23 return 1;
24 }
22:56:10 margusja@IRack> gcc stack.c -o stack -g (-g siis on hea gdb-ga asja uurida)
käivitame:
22:56:10 margusja@IRack>
./stack
value on top(b) is 20, address 1791502060
value on top(a) is 10, address 1791502056
22:56:42 margusja@IRack>
Nagu oleks ja ei ole ka. Minule ei piisa.
Läheme debuggeriga kallale:
22:56:42 margusja@IRack> gdb ./stack
GNU gdb 6.3.50-20050815 (Apple version gdb-1705) (Fri Jul 1 10:50:06 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done
(gdb)
Vaatame, kuhu paigutada breakbointerid:
(gdb) list
1 #include
2 #include
3
4 int main (void) {
5 int *p1, stack[10];
6 int a = 10;
7 int b = 20;
8
9 p1 = stack;
10
(gdb)
11 *p1 = a;
12
13 p1++;
14 *p1 = b;
15
16 printf("value on top(b) is %d, address %d\n", *p1, p1);
17 *p1 = 0;
18
19 p1--;
20 printf("value on top(a) is %d, address %d\n", *p1, p1);
(gdb)
21 *p1 = 0;
22
23 return 1;
24 }
(gdb)
Seame breakbointerid:
(gdb) b 8
Breakpoint 1 at 0x100000e26: file stack.c, line 8.
(gdb) b 12
Breakpoint 2 at 0x100000e37: file stack.c, line 12.
(gdb) b 15
Breakpoint 3 at 0x100000e55: file stack.c, line 15.
(gdb) b 18
Breakpoint 4 at 0x100000e85: file stack.c, line 18.
(gdb) b 22
Breakpoint 5 at 0x100000ecb: file stack.c, line 22.
Programm käima:
(gdb) r
Starting program: /Users/margusja/Documents/c/stack
Reading symbols for shared libraries +........................ done
Breakpoint 1, main () at stack.c:9
9 p1 = stack;
Vaatame, mis meil siis mälus tegelikult toimub:
(gdb) info locals
p1 = (int *) 0x7fff5fbff708
stack = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
a = 10
b = 20
(gdb)
Ülaltoodud infos on oluline info p1 = (int *) 0x7fff5fbff708 – siin algab meie stack. Hetkel on see tühi.
Laseme programmiga edasi:
(gdb) c
Continuing.
Breakpoint 2, main () at stack.c:13
13 p1++;
Vaatame, mis olukord meie stackis on:
(gdb) info locals
p1 = (int *) 0x7fff5fbff6c8
stack = {10, 0, 0, 0, 0, 0, 0, 0, 0, 0}
a = 10
b = 20
(gdb)
Vaatame, mis toimub aadressil 0x7fff5fbff6c8
(gdb) x/10c 0x7fff5fbff6c8
0x7fff5fbff6c8: 10 '\n' 0 '\0' 0 '\0' 0 '\0' 0 '\0' 0 '\0' 0 '\0' 0 '\0'
0x7fff5fbff6d0: 0 '\0' 0 '\0'
(gdb)
Kenasti on näha, et meie 10 asub alates aardessilt 0x7fff5fbff6c8 4 ühikut.
Okei, laseme, edasi:
(gdb) c
Continuing.
Breakpoint 3, main () at stack.c:16
16 printf(“value on top(b) is %d, address %d\n”, *p1, p1);
(gdb)
Uurime mälu:
(gdb) info locals
p1 = (int *) 0x7fff5fbff6cc
stack = {10, 20, 0, 0, 0, 0, 0, 0, 0, 0}
a = 10
b = 20
(gdb)
Näeme, et stack (sp) on suurenenud: 0x7fff5fbff6cc
Kui vaadata uuesti stacki stacki algusest:
(gdb) x/10c 0x7fff5fbff6c8
0x7fff5fbff6c8: 10 '\n' 0 '\0' 0 '\0' 0 '\0' 20 '\024' 0 '\0' 0 '\0' 0 '\0'
0x7fff5fbff6d0: 0 '\0' 0 '\0'
(gdb)
Koodist lähtuvalt hakkab nüüd nn stack tühjenema:
(gdb) c
Continuing.
value on top(b) is 20, address 1606416076
Breakpoint 4, main () at stack.c:19
19 p1–;
(gdb) x/10c 0x7fff5fbff6c8
0x7fff5fbff6c8: 10 ‘\n’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’
0x7fff5fbff6d0: 0 ‘\0’ 0 ‘\0’
(gdb) c
Continuing.
value on top(a) is 10, address 1606416072
Breakpoint 5, main () at stack.c:23
23 return 1;
(gdb) x/10c 0x7fff5fbff6c8
0x7fff5fbff6c8: 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’ 0 ‘\0’
0x7fff5fbff6d0: 0 ‘\0’ 0 ‘\0’
(gdb) c
Continuing.
Program exited with code 01.
Tegu on C baasil stack toimimise näitega, masinkoodi uurides, kordagi tegelikult sp ei liigutata, selleks peaks tegema keeruliseme C koodi, või puhtalt masinkoodis push ja pop käsklusi kasutama, seda ehk edaspidi. Siiski antud näide peaks andma ülevaate mäluosa, mida kutsutakse stack, kasutamisloogikast. Siin väljendus kenasti LIFO (LastIn-FirstOut) järjekord samuti.