web-dev-qa-db-ja.com

Intelアセンブリの%ripレジスタを理解する

次の小さなコードについては、別の投稿で構造のサイズとデータを正しく整列するためのすべての可能性について説明しました:

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命令を使用する場合のアドレスの計算に特に役立ちます。

8
youpilat13

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
5
toncsi