次の小さなコードについては、別の投稿で構造のサイズとデータを正しく整列するためのすべての可能性について説明しました:
struct
{
char Data1;
short Data2;
int Data3;
char Data4;
} x;
unsigned fun ( void )
{
x.Data1=1;
x.Data2=2;
x.Data3=3;
x.Data4=4;
return(sizeof(x));
}
対応する逆アセンブリを取得します(64ビット)
0000000000000000 <fun>:
0: 55 Push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c6 05 00 00 00 00 01 movb $0x1,0x0(%rip) # b <fun+0xb>
b: 66 c7 05 00 00 00 00 movw $0x2,0x0(%rip) # 14 <fun+0x14>
12: 02 00
14: c7 05 00 00 00 00 03 movl $0x3,0x0(%rip) # 1e <fun+0x1e>
1b: 00 00 00
1e: c6 05 00 00 00 00 04 movb $0x4,0x0(%rip) # 25 <fun+0x25>
25: b8 0c 00 00 00 mov $0xc,%eax
2a: 5d pop %rbp
2b: c3 retq
address of local variables
が使用されていると思われる右側にある用語の計算方法がわかりません。さらに、%rip register
で計算するのか分からない
%rip
と%rsp
または%rbp
の間のリンクを示す例を示してください。つまり、move
命令を使用する場合のアドレスの計算に特に役立ちます。
RIPアドレス指定は、常にRIP(64ビット命令ポインター)レジスタに関連しています。したがって、グローバル変数にのみ使用できます。 0オフセットは、RIPアドレス指定された命令の後の次の命令のアドレスに等しくなります。例えば:
mov al,[rip+2] al=53
jmp short next (length=2 bytes)
db 53
next:
mov bl,[rip-7] (length=6 bytes) bl=53
即時の場合を除いて、通常、コードにデータを直接混在させることはありませんが、実際に非常に小さなオフセットでコードを実行した場合に何が起こるかを示しています。
.o
を逆アセンブルしたため、コードではオフセットを確認およびチェックできません(4つのゼロが表示されます)。 objdump -drwC
を使用して、分解するときにシンボル名/再配置を表示します。これらは、このオブジェクトを実行可能ファイルにリンクするときに、リンカーによって入力されます。
`rbpに関連するローカルにアクセスする例:
Push rbp ;save rbp
mov rbp,rsp ;rbp = pointer to return address (8 bytes)
sub rsp,64 ;reserve 64 bytes for local variables
mov rax,[rbp+8]; rax = the last stack-passed qword parameter (if any)
mov rdx,[rbp]; rdx = return address
mov rcx,[rbp-8]; rcx = first qword local variable (this is undefined now)
mov r8, [rbp-16]; r8 = second qword local variable (this is undefined now)
.
.
mov rsp,rbp
pop rbp
ret