@確率的に説明したように:
コンパイラは、SP に関連する変数 (この場合は i、p、および p2p) を参照します。つまり、コンパイラは各変数の SP からのオフセットを決定し、それに応じてマシン コードを生成します。
多分この例はあなたにそれをさらに説明します。amd64 上にあるため、ポインタのサイズは 8 バイトです。ご覧のとおり、変数はなく、レジスタからのオフセットのみです。
#include <cstdlib>
#include <stdio.h>
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
int i, *p = &i;
int **p2p = &p;
printf("address 0f i: %p",p);//0x7fff4d24ae8c
return 0;
}
分解:
!int main(int argc, char** argv) {
main(int, char**)+0: push %rbp
main(int, char**)+1: mov %rsp,%rbp
main(int, char**)+4: sub $0x30,%rsp
main(int, char**)+8: mov %edi,-0x24(%rbp)
main(int, char**)+11: mov %rsi,-0x30(%rbp)
!
! int i, *p = &i;
main(int, char**)+15: lea -0x4(%rbp),%rax
main(int, char**)+19: mov %rax,-0x10(%rbp) //8(pointer)+4(int)=12=0x10-0x4
! int **p2p = &p;
main(int, char**)+23: lea -0x10(%rbp),%rax
main(int, char**)+27: mov %rax,-0x18(%rbp) //8(pointer)
! printf("address 0f i: %p",p);//0x7fff4d24ae8c
main(int, char**)+31: mov -0x10(%rbp),%rax //this is pointer
main(int, char**)+35: mov %rax,%rsi //get address of variable, value would be %esi
main(int, char**)+38: mov $0x4006fc,%edi
main(int, char**)+43: mov $0x0,%eax
main(int, char**)+48: callq 0x4004c0 <printf@plt>
! return 0;
main(int, char**)+53: mov $0x0,%eax
!}
main(int, char**)()
main(int, char**)+58: leaveq
main(int, char**)+59: retq