This paper mainly discusses the access efficiency of heap and stack in use. Use macro assembly instructions to analyze the access situation for simple inference.
Lab environment and usage tools: i686,32-bit Ubuntu Linux. GCC (Ubuntu/linaro 4.6.3-1ubuntu5) 4.6.3,gdb
First, refer to the code of the question and the "answer", which is "more heap and stack access efficiency." But in fact, he gave the two ways to use the stack, the individual tries to occupy the heap space situation, can only be malloc () and new () and other system calls generated.
#include <stdio.h>
Main () {
char a = 1;
Char c[] = "1234567890";
Char *p = "1234567890";
A = c[1];
A = p[1];
}
"Answer": Comparison of access efficiency
Chars1[]= "AAAAAAAAAAAAAAA";
Char *s2= "BBBBBBBBBBBBBBBBB";
AAAAAAAAAAA are assigned at the time of execution;
And BBBBBBBBBBB is determined at compile time.
The main question is that both are stored in the stack, determining "AAA ..." is the execution time assignment? is the execution "assignment" in the stack.
So, now that you see the code. Let's just control it. It is possible to compare the access efficiency of the two-segment string initialized with "array" and "pointer" (which will explain the detailed meaning) in the first form.
Macro assembly instructions Run the process:
Breakpoint 1, Main () at Efficiencyofstorage.c:4
4 char a = 1;
1:x/i $pc
= 0x8048419 <main+21>: Movb $0x1,0x10 (%ESP)
5 char c[] = "1234567890";
0x804841e <main+26>: Movl $0x34333231,0x11 (%ESP)
0x8048426 <main+34>: Movl $0x38373635,0x15 (%ESP)
0x804842e <main+42>: MOVW $0x3039,0x19 (%ESP)
0x8048435 <main+49>: Movb $0x0,0x1b (%ESP)
6 char *p = "1234567890";
0x804843a <main+54>: Movl $0x8048540,0xc (%ESP)
7 A = c[1];
0x8048442 <main+62>: Movzbl 0x12 (%ESP),%eax
0x8048447 <main+67>: mov%al,0x10 (%ESP)
8 a = p[1];
0x804844b <main+71>: mov 0xc (%ESP),%eax
0x804844f <main+75>: Movzbl 0x1 (%eax),%eax
0x8048453 <main+79>: mov%al,0x10 (%ESP)
10}
0x8048457 <main+83>: mov 0x1c (%ESP),%edx
0x804845b <main+87>: Xor%gs:0x14,%edx
0x8048462 <main+94>: je
0x8048469 <main+101>
0x8048464 <main+96>: Call
0x8048320 <[email protected]>
0x8048469 <main+101>: Leave
0X804846A <main+102>: ret
(it can be seen according to the order of the variable declarations.) Offset address on Linux stack is growing)
First, it is a character array, and the numeric character 0-9 converts the ASCII code to be 0x30-0x39.
Char c[] = "1234567890";
0x804841e <main+26>: Movl $0x34333231,0x11 (%ESP)
0x8048426 <main+34>: Movl $0x38373635,0x15 (%ESP)
0x804842e <main+42>: MOVW $0x3039,0x19 (%ESP)
0x8048435 <main+49>: Movb $0x0,0x1b (%ESP)
The entire array C contains a terminator that should occupy 11 address space (which can be verified with sizeof), 0x11 to 0x1b.
In the small-end mode, the character array "01234567890" starts from the low address 0x11. To 0x1b end (Terminator ASCII value 0x00):
Stack offset Address: 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b
Corresponding memory contents: 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x00
PS: Although the third time it only presses into Word's long data (two bytes), it also uses a single line of instruction that presses the size of the terminator to byte.
6 char *p = "1234567890";
0x804843a <main+54>: Movl $0x8048540,0xc (%ESP)
The P pointer itself is definitely on the stack, so the P pointer directly points to the address of the string constant (0x8048540), and the process of "1234567890" being deposited into the address is omitted, and its own initiative .
7 a = c[1];
0x8048442 <main+62>: Movzbl 0x12 (%ESP),%eax
0x8048447 <main+67>: mov%al,0x10 (%ESP)
Remove the value 0x32 from address 0x12. Passed to the EAX register.
about Movzbl. At the bottom of the article is a specific explanation, saying that the popular point is the (8-bit) byte length of the value 0x32 moved to (32-bit) long length of an address storage space (this example is EAX) register-the EAX median 0x00000032 (the first 24 should be 0. Due to "zero". Can be sure after eight bits is 0x32, can be)
mov Al puts EAX's low 8-bit value 0x32, which is the number 2. Save to the stack offset address 0x10 (that is, the address of variable a).
Assignment complete
Assuming these simple compilations do not understand, but also interested. Please go to my popular compilation sticker
8 a = p[1];
0x804844b <main+71>: mov 0xc (%ESP),%eax
0x804844f <main+75>: Movzbl 0x1 (%eax),%eax
0x8048453 <main+79>: mov%al,0x10 (%ESP)
Move the pointer P (which points to the address) stored in the stack offset address 0xc to the EAX register.
The second sentence is more difficult:
Remove the pointer from the EAX, offset by 1. Read the second character ' 2 ' in the string, and store the corresponding value (0x32, or number 2) of the (eight-bit) address to the stack offset address 0x10 (that is, the address of variable a).
Lower 8 bits in the EAX register. That is 0x32. To the stack offset address 0x10, that is, assigns a value to a.
Assignment complete
Conclusion: It is obvious that the former directly has the destination to read data from the stack to register eax, the latter must first read the pointer value, and then through the pointer and offset to find the value of the address required, according to our knowledge about the principle of computer composition. Once more access to memory, obviously inefficient.
What can be seen is that two strings are read in the same manner as the array subscript, so it is not related to the mode of operation?
The feeling is not rigorous, also tested with the hands of the operation of the form, such as the following (multiple test. and the upper process variable address is afraid to change. The principle is also possible):
One a = * (c + 1);
1:x/i $pc
= = 0x8048487 <main+83>: Lea 0x21 (%ESP),%eax
(GDB)
0x0804848b A = * (c + 1);
1:x/i $pc
= 0x804848b <main+87>: Movzbl 0x1 (%eax),%eax
(GDB)
0x0804848f A = * (c + 1);
1:x/i $pc
= = 0x804848f <main+91>: mov%al,0x20 (%ESP)
Remove the address of C
Remove--c address +1 offset points to-value
Pass this value to variable a
(GDB)
A = * (P + 1);
1:x/i $pc
= = 0x8048493 <main+95>: mov 0x1c (%ESP),%eax
(GDB)
0x08048497 a = * (P + 1);
1:x/i $pc
= 0x8048497 <main+99>: Movzbl 0x1 (%eax),%eax
(GDB)
0x0804849b a = * (P + 1);
1:x/i $pc
= = 0x804849b <main+103>: mov%al,0x20 (%ESP)
Remove the first address of the "string constant" that p points to
Remove--The value of thefirst address of the "string constant" that p points to +1 offset
Pass this value to variable a
The only difference is the command Lea and MOV, the reason is that P is pointing to the "constant zone", only the content of P (that is, the target address) can be, and C. You want to take your own address.
PS: There is no control over the heap space access problem due to the system call involved. Instruction many. The process is slow. Heap is a lot slower than stack access, which is obvious.
Report:
In this article, the so-called "stack offset address 0x10", non-absolute address. Refers to an offset address. %esp is a fixed position, and how much offset is the fixed position plus how many offsets.
= 0x8048456 <main+34>: movl $0x38373635,0x25 (%ESP)
(gdb) Print $esp
$ = (void *) 0xbffff230
(GDB) Si
0x0804845e 5 char c[] = "1234567890";
= 0x804845e <main+42>: movw $0x3039,0x29 (%ESP)
(gdb) Print $esp
$ = (void *) 0xbffff230
0x08048465 5 char c[] = "1234567890";
= 0x8048465 <main+49>: movb $0x0,0x2b (%ESP)
(gdb) Print $esp
$4 = (void *) 0xbffff230
MOVZBL:
In the/t syntax, the symbol extension and the 0 extension directives are in the format. The basic section "Movs" and "Movz" (the corresponding Intel syntax for movsx and movzx, The MOVZX is a zero extension, which is a high-level complement 0. movsx as symbol extension, i.e. high-level complement sign bit)
followed by the length of the source operand and the length of the destination operand. MOVSBL means that the Movs (from) byte long;movbw means that the Movs (from) byte (to) WORD;MOVSWL means the Movs (from) word (to) long.
The same is true for MOVZ directives. For example, the instruction "MOVSBL%al,%edx" means to place the contents of the Al register in the edx register after the symbol is expanded.
MOVZX is the copy of the contents of the source operand to the destination operand. The value 0 is expanded to 16-bit or 32-bit.
But it only applies to unsigned integers.
He is broadly divided into the following three formats:
MOVZX 32-bit general purpose register, 8-bit general purpose Register/memory unit
MOVZX 32-bit general purpose register, 16-bit general purpose Register/memory unit
MOVZX 16-bit general purpose register, 8-bit general purpose Register/memory unit
The heap space is a dynamic application when the program executes, and the system maintains a linked list of spare areas, from small to large by capacity. Find the first node that meets the requirements (greater than or equal to the required space) and allocate it.
Then it is not necessarily the whole list, under WINDOWS, the best way is to allocate memory with VirtualAlloc . He is not in the heap, nor in the stack , but directly in the process of the address space to retain a piece of memory, although the most inconvenient to use. But the speed is fast, also the most flexible.
So how do I delete the deletion? How do you know how much to delete? This size is recorded by the system. No problem, just the free (), delete ().
If the application is less, unfortunately there is no very suitable, the allocation of more parts, the system will be released, lest waste.
Linux c Access Efficiency control-heap, stack, constant area