これでさらに遊んでドキュメントを読んだ後、呼び出す関数のために 32 バイトを予約する必要があります。関数が例のように単純で、他の関数を呼び出さない場合は、このスペースを予約する必要はありません。ただし、呼び出す関数はこの 32 バイトを使用する可能性があるため、それらを予約しないと、関数が
また、関数は、ABI に従っている場合、関数を呼び出した関数からスタックに 32 バイトが利用可能であることに依存する場合があります。通常、この 32 バイト領域は、関数で変更されるレジスタを保存するために使用されるため、戻る前にそれらの値を復元できます。これはパフォーマンス上の目的のためだと思います.32バイトが選択されているため、ほとんどのリーフ関数(他の関数を呼び出さない関数)はスタックスペースを予約する必要がなく、レジスタを保存するためにスタックに一時的なスペースがあります戻る前にそれらを復元します。次の例を見てください。
呼び出し機能:
CallingFunction:
push rbp
mov rbp, rsp
sub rsp, 40 // $20 bytes we want to use at [rbp+30],
// plus $20 bytes for calling other functions
// according to windows ABI spec
mov rcx, [rsi+10] // parameter 1 (xmm0 if non-int)
mov rdx, 10 // parameter 2 (xmm1 if non-int)
movss xmm2, [rsi+28] // parameter 3 (r8 if int)
mov r9, [rsi+64] // parameter 4 (xmm3 if non-int)
call MyFunction
// ... do other stuff
add rsp, 40 // free space we reserved
pop rbp
xor rax,rax
ret
呼び出された関数
CalledFunction:
push rbp // standard
mov rbp, rsp // standard
// should do 'sub rsp, 20' here if calling any functions
// to give them a free scratch area
// [rbp] is saved rbp
// [rbp+8] is return address
// [rbp+10] to [rbp+2f] are the 0x20 bytes we can
// safely modify in this function, this could
// be pushed higher if the function had more than 4
// parameters and some had to be passed on the stack
// or if returning a structure or something that needs
// more space. In these cases the CALLER would have
// allocated more space for us
// the main reason for the 0x20 is so that we can save
// registers we want to modify without having to allocate
// stack space ourselves
mov [rbp+10], rsi // save rsi in space allocated by caller
mov [rbp+18], rdi // save rdi in space allocated by caller
mov rsi, [rcx+20]
mov rdi, [rsi+48]
add rdi, [rsi+28]
mov rax, rdi
mov rdi, [rbp+18] // restore changed register
mov rsi, [rbp+10] // restore changed register
pop rbp
ret
元の答え
私は知らないうちにこれに出くわしましたが、そうであるようです。たとえば、GetAsyncKeyState の最初の 2 つの命令は、呼び出し先がパラメーターに使用するために予約する必要がある 0x20 バイト領域の戻りアドレスの上のスタックを上書きします。
user32.GetAsyncKeyState - mov [rsp+08],rbx
user32.GetAsyncKeyState+5- mov [rsp+10],rsi
user32.GetAsyncKeyState+A- push rdi
user32.GetAsyncKeyState+B- sub rsp,20