アセンブリが読めなくて困っています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
安藤

アセンブリが読めなくて困っています。

#1

投稿記事 by 安藤 » 13年前

objdump -d (実行プログラム) 
で実行プログラムのアセンブリを読み、このプログラムが何をしているか説明しなければいけないのですが、読めなくて困っています。
出題者からヒントを出されて、逆アセンブリの結果の一部(以下に記載)である<fff>, <main>のところを読めばわかるとのことなのですが
理解できません。
何かしらの値が1以下か2以上かで分岐している処理があるのはわかるのですが、このプログラムが何をしているかと言われると答えられません。
環境は、zenithで動き、zenithのOSは64bitのlinux(Redhat)です。

コード:

00000000004004d8 <fff>:
  4004d8:       55                      push   %rbp
  4004d9:       48 89 e5                mov    %rsp,%rbp
  4004dc:       53                      push   %rbx
  4004dd:       48 83 ec 08             sub    $0x8,%rsp
  4004e1:       89 7d f4                mov    %edi,0xfffffffffffffff4(%rbp)
  4004e4:       83 7d f4 01             cmpl   $0x1,0xfffffffffffffff4(%rbp)
  4004e8:       74 06                   je     4004f0 <fff+0x18>
  4004ea:       83 7d f4 02             cmpl   $0x2,0xfffffffffffffff4(%rbp)
  4004ee:       75 09                   jne    4004f9 <fff+0x21>
  4004f0:       c7 45 f0 01 00 00 00    movl   $0x1,0xfffffffffffffff0(%rbp)
  4004f7:       eb 1d                   jmp    400516 <fff+0x3e>
  4004f9:       8b 7d f4                mov    0xfffffffffffffff4(%rbp),%edi
  4004fc:       83 ef 01                sub    $0x1,%edi
  4004ff:       e8 d4 ff ff ff          callq  4004d8 <fff>
  400504:       89 c3                   mov    %eax,%ebx
  400506:       8b 7d f4                mov    0xfffffffffffffff4(%rbp),%edi
  400509:       83 ef 02                sub    $0x2,%edi
  40050c:       e8 c7 ff ff ff          callq  4004d8 <fff>
  400511:       01 c3                   add    %eax,%ebx
  400513:       89 5d f0                mov    %ebx,0xfffffffffffffff0(%rbp)
  400516:       8b 45 f0                mov    0xfffffffffffffff0(%rbp),%eax
  400519:       48 83 c4 08             add    $0x8,%rsp
  40051d:       5b                      pop    %rbx
  40051e:       c9                      leaveq 
  40051f:       c3                      retq   

0000000000400520 <main>:
  400520:       55                      push   %rbp
  400521:       48 89 e5                mov    %rsp,%rbp
  400524:       48 83 ec 10             sub    $0x10,%rsp
  400528:       48 8d 75 fc             lea    0xfffffffffffffffc(%rbp),%rsi
  40052c:       bf 58 06 40 00          mov    $0x400658,%edi
  400531:       b8 00 00 00 00          mov    $0x0,%eax
  400536:       e8 b5 fe ff ff          callq  4003f0 <scanf@plt>
  40053b:       8b 7d fc                mov    0xfffffffffffffffc(%rbp),%edi
  40053e:       e8 95 ff ff ff          callq  4004d8 <fff>
  400543:       89 c6                   mov    %eax,%esi
  400545:       bf 5b 06 40 00          mov    $0x40065b,%edi
  40054a:       b8 00 00 00 00          mov    $0x0,%eax
  40054f:       e8 7c fe ff ff          callq  4003d0 <printf@plt>
  400554:       c9                      leaveq 
  400555:       c3                      retq   
  400556:       90                      nop    
  400557:       90                      nop    
  400558:       90                      nop    
  400559:       90                      nop    
  40055a:       90                      nop    
  40055b:       90                      nop    
  40055c:       90                      nop    
  40055d:       90                      nop    
  40055e:       90                      nop    
  40055f:       90                      nop 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#2

投稿記事 by softya(ソフト屋) » 13年前

mainはscanfして得られた値でfff関数をコールして戻り値をprintfしているだけですね。
fff関数は0xfffffffffffffff4(%rbp)とかに借りの変数名を付けてやれば読みやすくなるんではないでしょうか?
あと一行ごとにコメントを書いて、フローチャートとか書くと良いかと思います。
それとfff関数でリカーシブルコールをしているのは分かりますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

安藤

Re: アセンブリが読めなくて困っています。

#3

投稿記事 by 安藤 » 13年前

softya(ソフト屋) さんが書きました: それとfff関数でリカーシブルコールをしているのは分かりますか?
わかりませんでした。
15、19行目の行目のcallというのは呼び出された行、pushの処理だけを行うのかjmpと同じように以下の作業も繰り返すかイマイチわかっていません。
softya(ソフト屋) さんが書きました:あと一行ごとにコメントを書いて、フローチャートとか書くと良いかと思います。
書いてみた内容をまとめてみましたので質問したいと思います。
0xfffffffffffffff4(%rbp)、0xfffffffffffffff0(%rbp)などをrbp(4)、rbp(0)とすると、rbp(4)に入れたediの値が1以上2より小さいならループは終わり、何かしらを返すようにし、値が2より大きければその値から1ずつ引いていき処理を繰り返し、ループを終了させると考えたのですが、
この値が何を表し、返すであろう値のもとのeaxがいきなり出てきたことも理解できません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#4

投稿記事 by softya(ソフト屋) » 13年前

安藤 さんが書きました:
softya(ソフト屋) さんが書きました: それとfff関数でリカーシブルコールをしているのは分かりますか?
わかりませんでした。
15、19行目の行目のcallというのは呼び出された行、pushの処理だけを行うのかjmpと同じように以下の作業も繰り返すかイマイチわかっていません。
再帰呼び出しの仕組みは理解されていますか?
それとcallqは、全て同じ命令ですね。15,19と35,37,41も全て同じcallqです。
安藤 さんが書きました:
softya(ソフト屋) さんが書きました:あと一行ごとにコメントを書いて、フローチャートとか書くと良いかと思います。
書いてみた内容をまとめてみましたので質問したいと思います。
0xfffffffffffffff4(%rbp)、0xfffffffffffffff0(%rbp)などをrbp(4)、rbp(0)とすると、rbp(4)に入れたediの値が1以上2より小さいならループは終わり、何かしらを返すようにし、値が2より大きければその値から1ずつ引いていき処理を繰り返し、ループを終了させると考えたのですが、
この値が何を表し、返すであろう値のもとのeaxがいきなり出てきたことも理解できません。
eaxは戻り値として使用していると思います。

●参考に。 呼び出し規約のcdecl だと思います。
「呼出規約 - Wikipedia」
http://ja.wikipedia.org/wiki/%E5%91%BC% ... F%E7%B4%84
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: アセンブリが読めなくて困っています。

#5

投稿記事 by かずま » 13年前

これなら読めますか?

コード:

#include <stdio.h>

// memory
int mem[4096];

// registers
int rax, eax;    // accumulator
int rbx, ebx;    // base index
int rsi, esi;    // source index
int rdi, edi;    // destination index
int *rbp, *ebp;  // base pointer
int *rsp, *esp = mem + 4096;  // stack pointer
// char *rip, *eip; // instruction pointer

void fff()
{
    *--esp = rbp, *--esp = ebp;  // push %rbp
    rbp = rsp, ebp = esp;        // mov  %rsp,%rbp
    *--esp = rbx, *--esp = ebx;  // push %rbx
    esp -= 2;                    // sub  $0x8,%rsp
    ebp[-3] = edi;               // mov  %edi,-12(&rbp)
    if (ebp[-3] == 1)            // cmpl $0x1,-12(%rbp)
        goto fff_0x18;           // je   4004f0 <fff+0x18>
    if (ebp[-3] != 2)            // cmpl $0x2,-12(%rbp)
        goto fff_0x21;           // jne  4004f9 <fff+0x21>
fff_0x18:
    ebp[-4] = 1;                 // movl $0x1,-16(%rbp)
    goto fff_0x3e;               // jmp  400516 <fff+0x3e>
fff_0x21:
    edi = ebp[-3];               // mov  -12(%rbp),%edi
    edi -= 1;                    // sub  $0x1,%edi
    fff();                       // callq 4004d8 <fff>
    ebx = eax;                   // mov  %eax,%ebx
    edi = ebp[-3];               // mov  -12(%rbp),%edi
    edi -= 2;                    // sub  $0x2,%edi
    fff();                       // callq 4004d8 <fff>
    ebx += eax;                  // add  %eax,%ebx
    ebp[-4] = ebx;               // mov  %ebx,-16(%rbp)
fff_0x3e:
    eax = ebp[-4];               // mov  -16(%rbp),%eax
    esp += 2;                    // add  $0x8,%rsp
    ebx = *esp++, rbx = *esp++;  // pop  %rbx
    ebp = *esp++, rbp = *esp++;  // leaveq
    //rip = *esp++, eip = *esp++;  // retq
}

int main(void)
{
    *--esp = rbp, *--esp = ebp;  // push %rbp
    rbp = rsp, ebp = esp;        // mov  %rsp,%rbp
    esp -= 4;                    // sub  $0x10,%rsp
    esi = &ebp[-1];              // lea  -4(%rbp),%rsi
    edi = "%d";                  // mov  $0x400658,%edi
    eax = scanf(edi, esi);       // callq 4003f0 <scanf@plt>
    edi = ebp[-1];               // mov  -4(%rbp),%edi
    fff();                       // callq 4004d8 <fff>
    esi = eax;                   // mov  %eax,%esi
    edi = "%d\n";                // mov  $40065b,%edi
    eax = 0;                     // mov  $0x0,%eax
    eax = printf(edi, esi);      // callq 4003d0 <printf@plt>
    ebp = *esp++, rbp = *esp++;  // leaveq
    //rip = *esp++, eip = *esp++;  // retq
    return eax;
}

安藤

Re: アセンブリが読めなくて困っています。

#6

投稿記事 by 安藤 » 13年前

かずま さんが書きました:これなら読めますか?
私なりに読んでみました。C言語仕様に書き換えていただきありがとうございます。
しかし読みやすくはなりましたが具体的に何をしているかは理解できませんでした、すみません。

<fff>について
ebp[-3]の値の分岐によって、2以外であれば2になるまで値を引いていき、(31行目)
2になれば再帰(32行目)を終わり
その後ediが-2され0になり、またfffが呼び出され(?)、
fff_0x3eへ??
fff_0x3eの作業は何を意味しているかはわかりませんでした。

<main>について
mainはscanfで入力されたものを、fffである処理をしてその結果をprintf("%d", eax)で出力するものですよね。
よって、fffの内容さえ理解できれば問題無いと思うのですがそれが把握しきれていません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#7

投稿記事 by softya(ソフト屋) » 13年前

やっている内容は自分でC言語に書き換えてみたらどうでしょうか?
fff_0x3eの作業はスタックフレームの操作と戻り値とリターン処理です。

「C言語関数辞典 - C言語用語集 スタックフレーム (stack frame)」
http://www.c-tipsref.com/words/stackframe.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

安藤

Re: アセンブリが読めなくて困っています。

#8

投稿記事 by 安藤 » 13年前

softya(ソフト屋) さんが書きました:やっている内容は自分でC言語に書き換えてみたらどうでしょうか?
fff_0x3eの作業はスタックフレームの操作と戻り値とリターン処理です。
回答ありがとうございます。4行にそれだけの処理が詰め込まれているのですね。
書ける自信はありませんがいろいろ調べて書いてみたいと思います。

それと、fffの解釈は上に書いたもので合っているでしょうか。



知識が少ないのでよろしければ回答のほど、詳しくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#9

投稿記事 by softya(ソフト屋) » 13年前

知識が無いのはだれでも最初は同じです。
アセンブラで一行毎にコメントを書き、C言語でどの命令にあたるか考えてみないと何時まで経っても理解できないと思います。

>ebp[-3]の値の分岐によって、2以外であれば2になるまで値を引いていき、(31行目)
>2になれば再帰(32行目)を終わり
>その後ediが-2され0になり、またfffが呼び出され(?)、

だいぶと解釈が違うと思いますので、上に書いたことをやってみてください。
if文、関数を呼び出す式と引数処理、return文などの処理が見受けられます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: アセンブリが読めなくて困っています。

#10

投稿記事 by かずま » 13年前

これでもだめですか?

コード:

#include <stdio.h>

// registers
int eax;  // 関数の返却値
int ebx;  // 一時領域
int edi;  // 関数の第1引数
int *ebp; // 関数のスタックフレームを指す

void fff(void)
{
    int mem[5];      // スタックフレーム
    mem[4] = ebp;    // 関数呼び出し元の ebp を退避
    ebp = mem + 4;   // この関数のスタックフレームを設定
    ebp[-2] = ebx;   // ebx を退避 (この関数で ebx が使えるようになった)
    ebp[-3] = edi;   // edi を退避 (再帰呼出しで壊れるから)
    if (ebp[-3] == 1 || ebp[-3] == 2) {
        ebp[-4] = 1;
    } else {
        edi = ebp[-3];
        edi -= 1;
        fff(edi);
        ebx = eax;
        edi = ebp[-3];
        edi -= 2;
        eax = fff(edi);
        ebx += eax;
        ebp[-4] = ebx;
    }
    eax = ebp[-4];   // 返却値の設定
    ebx = ebp[-2];   // ebx の復元
    ebp = mem[4];    // ebp の復元
    return eax;
}

int main(void)
{
    int n;
    scanf("%d", &n);
    printf("%d\n", fff(n));
    return 0;
}
レジスタをローカル変数にしたら、退避復元が不要になります
非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#11

投稿記事 by softya(ソフト屋) » 13年前

かずまさんお気持はわかりますが性急に回答を出し過ぎだと私は思います。
もう少し安藤さんの回答を待っても良いのではないでしょうか?

一時的にhiddenとさしていただきました。かずまさんのコメントをお待ちしております。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: アセンブリが読めなくて困っています。

#12

投稿記事 by かずま » 13年前

softya(ソフト屋) さんが書きました:一時的にhiddenとさしていただきました。かずまさんのコメントをお待ちしております。
確かに焦りすぎました。すみません。

ところで、最初のプログラムですが、間違っていました。
void fff(void) で、引数なし、返却値なしなのに、
fff(edi) で呼び出したり、return eax; があったりしています。
訂正します。

コード:

#include <stdio.h>

// registers
int eax;  // 関数の返却値
int ebx;  // 一時領域
int edi;  // 関数の第1引数
int *ebp; // 関数のスタックフレームを指す

void fff(void)
{
    int mem[5];      // スタックフレーム
    mem[4] = ebp;    // 関数呼び出し元の ebp を退避
    ebp = mem + 4;   // この関数のスタックフレームを設定
    ebp[-2] = ebx;   // ebx を退避 (この関数で ebx が使えるようになった)
    ebp[-3] = edi;   // edi を退避 (再帰呼出しで壊れるから)
    if (ebp[-3] == 1 || ebp[-3] == 2) {
        ebp[-4] = 1;
    } else {
        edi = ebp[-3];
        edi -= 1;
        fff();
        ebx = eax;
        edi = ebp[-3];
        edi -= 2;
        fff();
        ebx += eax;
        ebp[-4] = ebx;
    }
    eax = ebp[-4];   // 返却値の設定
    ebx = ebp[-2];   // ebx の復元
    ebp = mem[4];    // ebp の復元
}

int main(void)
{
    int n;
    scanf("%d", &n);
	edi = n;
	fff();
    printf("%d\n", eax);
    return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#13

投稿記事 by softya(ソフト屋) » 13年前

ご本人が考えないと何にもならないので回答のバランスは難しいですね。
答えだけもらって終わりという人も多いので、この掲示板の趣旨としてはプログラミングを理解して欲しいと言うことですから、お手伝いの範囲で留めるべきなのでが出し渋ると諦める人が出るので難しいなと日頃から思っております。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

安藤

Re: アセンブリが読めなくて困っています。

#14

投稿記事 by 安藤 » 13年前

softya(ソフト屋)さん
fffにおいて、1行毎にコメントや質問をさせていただきます。
せっかくですので"かずま"さんに書いていただいたコードを参考にさせていただきます。
指導をお願いします。

コード:

#include <stdio.h>

// memory
int mem[4096];

// registers
int rax, eax;    // accumulator
int rbx, ebx;    // base index
int rsi, esi;    // source index
int rdi, edi;    // destination index
int *rbp, *ebp;  // base pointer
int *rsp, *esp = mem + 4096;  // stack pointer
// char *rip, *eip; // instruction pointer

void fff()
{
    *--esp = rbp, *--esp = ebp;  // push %rbp スタックespにrbp,ebpを順に格納
    rbp = rsp, ebp = esp;        // mov  %rsp,%rbp rbpにrsp、ebpにespを格納
    *--esp = rbx, *--esp = ebx;  // push %rbx スタックespにrbx,ebxを順に格納
    esp -= 2;                    // sub  $0x8,%rsp  rsp=rsp-$0x8(10進数の8)と思ったのですがなぜ左式になったかわかりません。
    ebp[-3] = edi;               // mov  %edi,-12(&rbp) ediをrbp(-12)の中身にコピー(ここでのediはscanfで入力した値?)なぜebp[-3]?
    if (ebp[-3] == 1)            // cmpl $0x1,-12(%rbp) 1とrbpの中身を比較し、1の方が小さい
        goto fff_0x18;           // je   4004f0 <fff+0x18> 上の比較が正しければ4004f0へジャンプ
    if (ebp[-3] != 2)            // cmpl $0x2,-12(%rbp) 2とrbpの中身を比較し、2の方が低い
        goto fff_0x21;           // jne  4004f9 <fff+0x21> 上の比較があやまりならば4004f9へジャンプ
fff_0x18:
    ebp[-4] = 1;                 // movl $0x1,-16(%rbp) 1をrbp(-16)の中身にコピー
    goto fff_0x3e;               // jmp  400516 <fff+0x3e> 400516へジャンプ
fff_0x21:
    edi = ebp[-3];               // mov  -12(%rbp),%edi rbp(-12)の中身をediにコピー
    edi -= 1;                    // sub  $0x1,%edi edi=edi-1
    fff();                       // callq 4004d8 <fff> fffの呼び出し(再帰)・・・これにより結果的にediの値を1ずつ引いていってる
    ebx = eax;                   // mov  %eax,%ebx eaxをebxにコピー
    edi = ebp[-3];               // mov  -12(%rbp),%edi rbp(-12)の中身をediにコピー
    edi -= 2;                    // sub  $0x2,%edi edi=edi-2
    fff();                       // callq 4004d8 <fff> fffの呼び出し(再帰)・・・これにより結果的にediの値を2ずつ引いていってる?また?
    ebx += eax;                  // add  %eax,%ebx ebx=ebx+eax
    ebp[-4] = ebx;               // mov  %ebx,-16(%rbp) ebxをrbp(-16)の中身へコピー
fff_0x3e:
    eax = ebp[-4];               // mov  -16(%rbp),%eax rbp(-16)の中身をeaxへコピー
    esp += 2;                    // add  $0x8,%rsp rsp=rsp+8?
    ebx = *esp++, rbx = *esp++;  // pop  %rbx rbxの中身を取り出す?
    ebp = *esp++, rbp = *esp++;  // leaveq 開放?
    //rip = *esp++, eip = *esp++;  // retq 
}

int main(void)
{
    *--esp = rbp, *--esp = ebp;  // push %rbp
    rbp = rsp, ebp = esp;        // mov  %rsp,%rbp
    esp -= 4;                    // sub  $0x10,%rsp
    esi = &ebp[-1];              // lea  -4(%rbp),%rsi
    edi = "%d";                  // mov  $0x400658,%edi
    eax = scanf(edi, esi);       // callq 4003f0 <scanf@plt>
    edi = ebp[-1];               // mov  -4(%rbp),%edi
    fff();                       // callq 4004d8 <fff>
    esi = eax;                   // mov  %eax,%esi
    edi = "%d\n";                // mov  $40065b,%edi
    eax = 0;                     // mov  $0x0,%eax
    eax = printf(edi, esi);      // callq 4003d0 <printf@plt>
    ebp = *esp++, rbp = *esp++;  // leaveq
    //rip = *esp++, eip = *esp++;  // retq
    return eax;
}
[/quote]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#15

投稿記事 by softya(ソフト屋) » 13年前

>sub $0x8,%rsp rsp=rsp-$0x8(10進数の8)と思ったのですがなぜ左式になったかわかりません。
C言語のポインタ演算だからです。8バイトのアドレス変更でも4バイトのintが2つ分ですよね?

>ediをrbp(-12)の中身にコピー(ここでのediはscanfで入力した値?)なぜebp[-3]?
これも上と同様の考え方です。12バイトはint型3つ分です。

>cmpl $0x1,-12(%rbp) 1とrbpの中身を比較し、1の方が小さい
cmpl 命令の理解が間違っています。調べなおしましょう。

>fffの呼び出し(再帰)・・・これにより結果的にediの値を1ずつ引いていってる
この発想を止めたほうが良いかも知れませんね。
edi-1の値で呼び出す。と言う理解で留めるべきです。どっちかと言うと再帰の考え方を見直すべきかな。

【追記】
これは変数であるとか、C言語的に書くとこうなるというのもコメントに付け加えていってください。
あと数行の処理単位で何をしているか別にコメントを書いたほうが良いでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

安藤

Re: アセンブリが読めなくて困っています。

#16

投稿記事 by 安藤 » 13年前

お二方、回答ありがとうございます。
前回の私の投稿は12時台のお二人のお返事を見てませんでした。

知識があまりにも不足しているので
少し勉強してからまた投稿し、質問します。
すぐには質問内容をまとめて投稿できなさそうなので時間がかかると思いますがそのときまた質問させてください。

すぐには私の考えを出せそうにないのでその旨だけ伝えさせていただきます。

安藤

Re: アセンブリが読めなくて困っています。

#17

投稿記事 by 安藤 » 13年前

考えがまとまったので投稿させていただきます。

このプログラムにおけるfffは入力した自然数値毎のフィボナッチ数を求めている。
入力値が1もしくは2の場合は1を出力するようになっており、それ以外の時はその入力値の1個前、2個前まで戻りその値のフィボナッチ数を
出し、最終的にその値を足して入力値のフィボナッチ数を出力している。

コード:

00000000004004d8 <fff>:
  4004d8:       55                      push   %rbp
  4004d9:       48 89 e5                mov    %rsp,%rbp
  4004dc:       53                      push   %rbx
  4004dd:       48 83 ec 08             sub    $0x8,%rsp
  4004e1:       89 7d f4                mov    %edi,0xfffffffffffffff4(%rbp) 入力から受け取ったediの中身をrbp4に。
  4004e4:       83 7d f4 01             cmpl   $0x1,0xfffffffffffffff4(%rbp) 1とrbp4を比較
  4004e8:       74 06                   je     4004f0 <fff+0x18> 1=rbp4ならジャンプ
  4004ea:       83 7d f4 02             cmpl   $0x2,0xfffffffffffffff4(%rbp) 2とrbp4を比較
  4004ee:       75 09                   jne    4004f9 <fff+0x21> 2≠rbp4ならジャンプ
  4004f0:       c7 45 f0 01 00 00 00    movl   $0x1,0xfffffffffffffff0(%rbp) 1をrbp0に。
  4004f7:       eb 1d                   jmp    400516 <fff+0x3e> ジャンプ
  4004f9:       8b 7d f4                mov    0xfffffffffffffff4(%rbp),%edi rbp4の中身をediに。
  4004fc:       83 ef 01                sub    $0x1,%edi ediから1ひく
  4004ff:       e8 d4 ff ff ff          callq  4004d8 <fff> fffの再帰呼び出し
  400504:       89 c3                   mov    %eax,%ebx eaxの中身をebxへ。
  400506:       8b 7d f4                mov    0xfffffffffffffff4(%rbp),%edi rbp4の値をediへ。
  400509:       83 ef 02                sub    $0x2,%edi ediから2ひく
  40050c:       e8 c7 ff ff ff          callq  4004d8 <fff> fffの再帰呼び出し
  400511:       01 c3                   add    %eax,%ebx ebxにeaxを足す
  400513:       89 5d f0                mov    %ebx,0xfffffffffffffff0(%rbp) ebxの値をrbp0へ。
  400516:       8b 45 f0                mov    0xfffffffffffffff0(%rbp),%eax rbp0の値をeaxへ。これが最終的に返す値
  400519:       48 83 c4 08             add    $0x8,%rsp
  40051d:       5b                      pop    %rbx
  40051e:       c9                      leaveq 
  40051f:       c3                      retq   

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: アセンブリが読めなくて困っています。

#18

投稿記事 by softya(ソフト屋) » 13年前

合っていると思います。ご苦労様でした。
%eaxに関しては戻り値と表現したほうがより分かりやすいと思います。
あとC言語に逆変換できたり、一行ごとではなく機能単位にコメントが書けるぐらい自在になればよりベストです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

安藤

Re: アセンブリが読めなくて困っています。

#19

投稿記事 by 安藤 » 13年前

何度にもわたって回答していただきありがとうございました。

ここでようやく少しだけアセンブリが読むことがわかったのでこれから徐々に逆変換等もできるようにしていきたいと思います。

閉鎖

“C言語何でも質問掲示板” へ戻る