This article mainly discusses the access efficiency of heap and stack in use, and uses macro assembly commands to analyze the access situation for simple judgment.
Lab environment and tools: i686, 32-bit Ubuntu Linux, gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, gdb
Take a short look at the Code:
# Include
Main (){
Char a = 1;
Char c [] = "1234567890 ";
Char * p = "1234567890 ";
A = c [1];
A = p [1];
}
Char s1 [] = "hello ";
Char * s2 = "world ";
The string that s1 points to belongs to the stack, and the string that s2 points to belongs to the heap. (Of course they all belong to Stacks)
Stack address space is allocated when the link is compiled, and the address space in the heap is dynamically applied for and allocated during runtime.
In future access, the array on the stack is faster than the string pointed to by the pointer (such as the heap.
PS: the heap space is dynamically applied for when the program runs. The system maintains a linked list about idle areas, from small to large, by capacity, and finds the first qualified space (greater than or equal to the required space). How can I delete a deletion? How can I know the number of deleted objects? This size is recorded by the system. It is not a problem. Only free () and delete () can be used. If the number of applications is small, unfortunately it is not suitable. If the number of allocated parts is small, the system will release them to avoid waste.
Macro assembly Command Execution Process:
Breakpoint 1, main () at efficiencyOfStorage. c: 4
4 char a = 1;
1: x/I $ pc
=> 0x8048419 : Movb $0x1, 0x10 (% esp)
5 char c [] = "1234567890 ";
0x804841e : Movl $0x34333231,0x11 (% esp)
Zero x 8048426 : Movl $0x38373635,0x15 (% esp)
0x804842e : Movw $0x3039,0x19 (% esp)
Zero x 8048435 : Movb $0x0, 0x1b (% esp)
6 char * p = "1234567890 ";
0x804843a : Movl $0x8048540, 0xc (% esp)
7 a = c [1];
Zero x 8048442 : Movzbl 0x12 (% esp), % eax
Zero x 8048447 : Mov % al, 0x10 (% esp)
8 a = p [1];
0x804844b : Mov 0xc (% esp), % eax
0x804844f : Movzbl 0x1 (% eax), % eax
Zero x 8048453 : Mov % al, 0x10 (% esp)
10}
Zero x 8048457 : Mov 0x1c (% esp), % edx
0x804845b : Xor % gs: 0x14, % edx
Zero x 8048462 : Je
Zero x 8048469
Zero x 8048464 : Call
0x8048320 <__stack_chk_fail @ plt>
Zero x 8048469 : Leave
0x804846a : Ret
(According to the sequence of variable Declaration, we can see that the offset address in linux increases)
First, it is a character array, and the digit 0-9 is converted into an ascii code 0x30-0x39.
Char c [] = "1234567890 ";
0x804841e : Movl $0x34333231,0x11 (% esp)
Zero x 8048426 : Movl $0x38373635,0x15 (% esp)
0x804842e : Movw $0x3039,0x19 (% esp)
Zero x 8048435 : Movb $0x0, 0x1b (% esp)
The entire array c, including the Terminator, should occupy 11 address spaces (which can be verified by sizeof), from 0x11 to 0x1b.
In the small-end mode, the character array "01234567890" is arranged from the low address 0x11 to the end of 0x1b (end character ascii value 0x00 ):
Stack offset address: 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b
Memory content: 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x00
6 char * p = "1234567890 ";
0x804843a : Movl $0x8048540, 0xc (% esp)
The p pointer is directly stored in the stack, and the process of "1234567890" being stored in the stack is omitted.However, this process should be slower than storing it in the stack. The address space in the stack is determined by the compilation link, while the heap is running.
7 a = c [1];
Zero x 8048442 : Movzbl 0x12 (% esp), % eax
Zero x 8048447 : Mov % al, 0x10 (% esp)
Take 0x32 from address 0x12 and pass it to the eax register.
For details about movzbl, the bottom part of this article is that the popular point is to move the (8-bit) byte length value 0x32 to an address bucket with a (32-bit) long length (in this example, eax) register -- at this time, the eax value is 0x00000032 (the first 24 digits should be filled with 0, because "zero", you can be sure that the last eight digits are 0x32)
Mov al saves the 8-bit low eax value 0x32, that is, number 2, to the treasure offset address 0x10 (that is, the address of variable ). Assigned successfully
If you are still interested in these simple assemblies, please move to my Popular Assemblies
8 a = p [1];
0x804844b : Mov 0xc (% esp), % eax
0x804844f : Movzbl 0x1 (% eax), % eax
Zero x 8048453 : Mov % al, 0x10 (% esp)
Move the pointer p stored in the stack offset address 0xc to the eax register.
The second sentence is hard:
Take the pointer from eax, offset 1, read the second character '2' in the string, and set the value corresponding to the (eight-bit) address (0x32, that is, number 2) offset 0x10 (the address of variable ).
Assign a value to a by passing the 8-bit (0x32) in the eax register to 0x10 of the stack offset address.
Assigned successfully
Conclusion: it can be seen that the former directly reads data from the stack to the Register eax, and the latter must read the pointer value first, then we use pointers to find the value of the desired address. According to our knowledge about the computer composition principle, the memory is accessed once more, which is obviously less efficient.
Appendix:
In this article, the so-called "Stack offset address 0x10" and other non-absolute addresses refer to the offset addresses. % esp is a fixed position, and the offset is the offset added to the fixed position.
=> 0x8048456 : Movl $0x38373635,0x25 (% esp)
(Gdb) print $ esp
$2 = (void *) 0xbffff230
(Gdb) si
0x0804845e 5 char c [] = "1234567890 ";
=> 0x804845e : Movw $0x3039,0x29 (% esp)
(Gdb) print $ esp
$3 = (void *) 0xbffff230
0x08048465 5 char c [] = "1234567890 ";
=> 0x8048465 : Movb $0x0, 0x2b (% esp)
(Gdb) print $ esp
$4 = (void *) 0xbffff230
Movzbl:
In AT&T syntax, the format of symbol extensions and zero-extension commands is: basic sections "movs" and "movz" (corresponding to Intel Syntax: movsx and movzx, movzx is zero extension, that is, the high position is supplemented with zero, and movsx is the symbol extension, that is, the high position is supplemented with the symbol bit)
The length of the source operand and the destination operand. Movsbl means movs (from) byte (to) long; movbw means movs (from) byte (to) word; movswl means movs (from) word (to) long. The same applies to movz commands. For example, the command "movsbl % al, % edx" means to extend the content of the al register and place it in the edx register.
Movzx copies the content of the source operand to the destination operand and extends the value 0 to 16 or 32 bits. However, it only applies to unsigned integers.
It is roughly divided into the following three formats:
Movzx 32-bit General Register, 8-bit General Register/memory unit
Movzx 32-bit General Register, 16-bit General Register/memory unit
Movzx 16-bit General Register, 8-bit General Register/memory unit