0

アセンブリについてもう少し理解したかったので、ちょっとした例を書きました:

#include <stdio.h>
#include <math.h>

void f() {
  unsigned char i[4];
  i[0] = 5;
  i[1] = 6;
  i[2] = 7;
  i[3] = 8;
  int j = 0;
  for(j=0; j < 20; j++)
    printf("%02X\n", i[j]);

}

int main() {
  int i[5];
  i[0] = 3;
  i[1] = 3;
  i[2] = 3;
  i[3] = 3;
  i[4] = 3;
  f();
  return 0;
}

私の目標は、f() を開始したときに main() で callq を呼び出すことによって設定された、命令ポインターの実際の戻りアドレスを確認することでした。

gdb を使用して main() を逆アセンブルし、次の結果を得ました。

 Dump of assembler code for function main:
 0x0000000100000eb0 <main+0>:   push   %rbp
 0x0000000100000eb1 <main+1>:   mov    %rsp,%rbp
 0x0000000100000eb4 <main+4>:   sub    $0x20,%rsp
 0x0000000100000eb8 <main+8>:   movl   $0x3,-0x1c(%rbp)
 0x0000000100000ebf <main+15>:  movl   $0x3,-0x18(%rbp)
 0x0000000100000ec6 <main+22>:  movl   $0x3,-0x14(%rbp)
 0x0000000100000ecd <main+29>:  movl   $0x3,-0x10(%rbp)
 0x0000000100000ed4 <main+36>:  movl   $0x3,-0xc(%rbp)
 0x0000000100000edb <main+43>:  callq  0x100000e40 <f>
 0x0000000100000ee0 <main+48>:  movl   $0x0,-0x8(%rbp)
 0x0000000100000ee7 <main+55>:  mov    -0x8(%rbp),%eax
 0x0000000100000eea <main+58>:  mov    %eax,-0x4(%rbp)
 0x0000000100000eed <main+61>:  mov    -0x4(%rbp),%eax
 0x0000000100000ef0 <main+64>:  add    $0x20,%rsp
 0x0000000100000ef4 <main+68>:  pop    %rbp
 0x0000000100000ef5 <main+69>:  retq 

したがって、これはcallqの次の命令であるため、配置された命令ポインターの戻りアドレスが0x0000000100000ee0になることを期待していました。プログラムを実行すると、次のようになります(読みやすいように、これらを4つのグループにグループ化しました):

05
06
07
08

40
1B
08
56

FF
7F
00
00

E0
EE
B7
09

01
00
00
00

00
00
00
00

03
00
00
00

03
00
00
00

03
00
00
00

03
00
00
00

わかりましたので、f() のローカル変数に書き込んだ 5,6,7,8 と、3 に設定された 4 バイト整数の main() のローカル変数を確認できます。 5,6,7,8 (これは 64 ビット システムです) 次の 8 バイトは %rbp レジスタの前の値をエンコードし、次の 8 バイトは命令ポインターの戻りアドレスを含むと予想していました。したがって、返品先住所は

E0
EE
B7
09

01
00
00
00

これを gdb から期待している 0x0000000100000ee0 と比較すると、最後の 4 バイトに 00000001 が表示され、最初のバイトに 00000ee0 からの e0 が表示されます。しかし、なぜ期待どおりの結果が得られないのでしょうか? 私はバイトオーダーについて考えました (Mac OS X はリトル エンディアンだと思います) が、それは私が理解していることから、ここに表示される内容を説明するものではありません。

任意の入力を歓迎します。

君たちありがとう、

クリストフ

4

1 に答える 1

2

このプログラムを試して、複数回実行してください。

#include <stdio.h>

int
main(int argc, char **argv)
{
    int foo;

    printf("%p %p\n", main, &foo);
    return 0;
}

毎回異なるアドレスを取得すると確信しています。MacOS には位置に依存しないバイナリがあり、スタックの位置も常に変化します。これはセキュリティ機能です。

gdb でプログラムを実行すると、デバッグを容易にするために gdb がランダム化を無効にするため、期待どおりの結果が得られるでしょう。

于 2012-12-03T14:29:01.670 に答える