x64 assembler Lecture, 64 calling convention with a function parameter passing.

x64 assembler Lecture, 64 calling convention with a function parameter passing.

Dian a review X86 mass participation

In our x86 assembler pass parameters as follows:


push eax
call xxx

xxx fun proc

push        ebp          保存栈底
mov         ebp,esp      设置ebp
sub         esp,0C0h     开辟局部变量空间
push        ebx          保存寄存器环境
push        esi  
push        edi  

pop         edi          恢复寄存器环境
pop         esi  
pop         ebx          
mov         esp,ebp      释放局部变量空间
pop         ebp          恢复栈底
ret                      返回,平展, 如果是 C在外平展 add esp,xxx stdcall 则内部平展 ret 4

See the above code, we should have a diagram of mind.

We can see that according to the diagram. Call functions to do those things.

1. Fill parameters stored in the stack
2. The return address stack
3. Save the bottom of the stack

4. Application to conduct their own internal stack space to preserve the environment and release.

Two Dian x64 assembler

2.1 Detailed compilation

In x64, remain the same. Like most x86.

The assembly code is:

sub rsp,0x28

mov r9,1
mov r8,2
mov rdx,3
mov rcx,4
call xxx
add rsp,0x28

Parameter passing mode 1.
First explain, at X64, a register parameter passing. The first four parameters are rcx rdx r8 r9 for parameter passing. Excess mass participation by the stack. Drawing from right to left.
2. Application Parameters reserve space
at x64, calling a function of time, will apply for a parameter reserves space to hold our parameters. for example, before we push through push
corresponding stack will raise the value of the parameter. in fact, x64 next, the same will apply. this place just did not enter a value in the function of time. after entering the function will be copied to the value of the register in the stack. in fact, the equivalent of you or push up. I was just outside application space, internal assignment.

as follows:


sub rsp,0x28          //申请的栈空间为0x28,就相当于我们push rcx rdx r8 r9.只不过只是申请.
call xxxx
add rsp,0x28

xxx                  //函数内部

mov [rsp - 8],rcx
mov [rsp - 0x10],rdx
mov [rsp - 0x18],r8
mov [rsp - 0x20],r9

xxx 

As shown below:

We write a simple x64 programs. View their disassembly.

First, open up our parameter space, as well as the return address space. We step through what view

you can see the large open space 5 * 8 bytes in size.
Then compiled below its assigned register. Conduct mass participation. We have only four instructions parameter.

This time into the internal Call. Facie stack.

3. A 16-byte stack alignment

Now we should understand.. Use * sub rsp, xxx ** be carried stack to call a function when the function is performed inside the parameter assignment.
Is actually equivalent to push the argument. But it is not the same as x86. Inside We were flat stack up. instead carried out a stack level.

那么有个疑问.比如说我们就4个参数. 通过上面来说.我们应该申请 sub rsp,0x20个字节才对.在CALL的时候
x86 x64都是一样的会将返回地址入栈. 那为什么要rsp,0x28.这样的话会多申请一个参数的值哪.

原因是这样的.栈要按照16字节对齐进行申请.

那么还有人会说.按照16字节对齐,那么我们的参数已经是16字节对齐了.比如为我们4个寄存器申请预留空间. rsp,0x20. (4 * 8 = 32 = 16j进制的 0x20)

那为什么还是会申请 rsp,0x28个字节,并且不对齐.

其实是这样的.当我们在 Call函数的时候.返回地址会入栈.如果按照我们之前申请的rsp,0x20个字节的话.那么当
返回地址入栈之后,现在总共抬栈大小是 0x28个字节.并不是16进制对齐. 但是当我们一开始就申请0x28个字节.
当返回地址入栈.那么就是0x28+8 = 0x30个字节. 0x30个字节不是正好跟16字节对齐吗.

所以我们的疑问也就没有了.

所以申请了0x28个字节,其实多出了的8字节是要跟返回地址一样.进行栈对齐使用.

那么申请的这个8字节空间,是没有用的.只是为了对齐使用.

所以x64汇编其实也就搞明白了.

1.在调用函数之前,会申请参数预留空间.(rcx,rdx,r8,r9)
2.函数内部,会将寄存器传参的值(rcx,rdx,r8,r9)保存到我们申请的预留空间中.
上面这两步其实就相当于x86下的 push r9 push r8 push rdx,push rcx
3.调用约定是__fastcall.传参有rcx rdx,平栈是按照c调用约定平栈. 也就是调用者平栈.

Guess you like

Origin www.cnblogs.com/iBinary/p/10959444.html