Order of parameters into stack
In the interview before being asked such a question, the function call, the order of the parameters into the stack from left to right, or from right to left. The order of the parameters in the stack is mainly in the invocation mode, in general, __cdecl and __stdcall are parameters from right to left into the stack. Look at the following code:
#include <stdio.h>
int Test (int a, int b)
{
printf ("Address of a%x.\n", &a);
printf ("Address of B%x.\n", &b);
return 0;
}
int main ()
{
Test (1, 2);
return 0;
}
The results of the 64-bit Ubuntu system run:
Address of a 1ec62c.
Address of B 1ec628.
The result of 32-bit Ubuntu is:
Address of a bfd03290.
Address of B bfd03294.
It can be seen that, first of all, different architectures, stack growth direction is different, some from the low address to the high address direction of growth, some from the high address to the low address direction. You can use the following code to determine the growth direction of the stack:
typedef enum {
Low_to_high,
high_to_low,
left_to_right,
right_to_left,
}stack_direc_t;
int Stack_grow_direc ()
{
static char *p = NULL;
Char C;
if (p = = NULL) {
p = &c;
Stack_grow_direc ();
}
else {
printf ("%x.\n", p);
printf ("Second in Stack",%x.\n, &c);
if (&c > P) {
printf ("Stack grows from low address to high address!\n");
return low_to_high;
}
else {
printf ("Stack grows from high address to Low address!\n");
return high_to_low;
}
}
what's in the stack when a function is called
Take parameters from left to right into the stack as an example:
Push arg0--high address
push arg1 ...
Push argn push
EIP
push EBP- -Low address
when the 32-bit system and the 64-bit system function call, the parameter stack method is different.
The problem was not long ago, it was silly, I have only been concerned about the 32-bit system parameters into the stack mode, always thought that 64-bit system is the same, no different, now summed up there are two: 64-bit system first put the incoming parameters in the register, in the function of the specific implementation of the Register value into the stack , and then go to the stack. Parameters in the 64-bit system stack are stored from left to right (because the register passes the value first).
Look at the disassembly below:
C code same as above Ubuntu 32-bit disassembly: int main () {804846d:55 push%ebp 804846e:89 e5 m OV%esp,%ebp 8048470:83 e4 f0 and $0xfffffff0,%esp 8048473:83 EC Sub $0x
10,%esp Test (1, 2); 8048476:c7 movl $0x2,0x4 (%ESP) 804847d:00 804847e:c7-MOVL, ((a)
%ESP) 8048485:e8 8a FF FF call 8048414 <test> return 0; 804848A:B8 mov $0x0,%eax} int Test (int a, int b) {8048414:55 push %EBP 8048415:89 e5 mov%esp,%ebp 8048417:83 EC Sub $0x18,%esp printf
("Address of a%x.\n", &a); 804841A:B8 mov $0x8048560,%eax 804841f:8d 0x8 (%EBP),%edx 80484 22:89 mov%edx,0x4 (%esp) 8048426:89 mov%eax, (%ESP) 8048429:e8 12FF-FF-call 8048340 <printf@plt> return 0; 8048466:B8 mov $0x0,%eax} Ubuntu 64-bit disassembly: int main () {40056e:55 push
%RBP 40056f:48 e5 mov%rsp,%rbp test (1, 2); 400572:BE mov $0x2,%esi 400577:BF mov $0x1,%edi 40057c:e8 ac
FF FF FF CALLQ 40052d <test> return 0; 400581:B8 mov $0x0,%eax} int Test (int a, int b) {40052d:55 Push% RBP 40052e:48 e5 mov%rsp,%rbp 400531:48-EC sub $0X10,%RSP 400535: 7d FC Mov%edi,-0x4 (%RBP) 400538:89 F8 mov%esi,-0x8 (%RBP) printf ("Add
Ress of a%x.\n ", &a); 40053b:48 8d FC Lea-0x4 (%RBP),%rax 40053f:48 mov c6 400542: BF-MOV$0x400614,%edi 400547:B8 mov $0x0,%eax 40054c:e8 BF fe FF FF CALLQ 400410 <
printf@plt> return 0; 400567:B8 mov $0x0,%eax}
Look at the 32-bit Ubuntu operating system, 8048476: It is really the parameters directly into the stack, 2 first into the stack, 1 back into the stack.
8048476: C7 movl $0x2,0x4 (%ESP)
804847d:
804847e: C7 ' a 00
MOVL $0x1, (%ESP)
8048485: E8 8a FF FF FF call 8048414 <test>
Looking at the 64-bit Ubuntu operating system, 2 and 1 were not put into the stack at all, but were placed in registers ESI and EDI.
40056f: e5 mov %rsp,%rbp
Test (1, 2);
400572: $0x2,%esi
400577: " bf" mov $0x1,%edi
40057c: E8 AC FF FF FF callq 40052d <test>
Then look at the 64-bit system test implementation, the first EDI into the stack, and then the ESI into the stack, which is why the function looks like a left to right into the stack reason.
40052d:55 push%rbp 40052e:48 mov e5 RBP 400531:48 $0x10,%rsp 400535:89 7d FC mov%edi,-0x4 (%RBP) 400 538:89 F8 mov%esi,-0x8 (%RBP)