重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

参照のために行頭に行番号を付けます。
XX:
01: b8 57 61 6b 61 mov $0x616b6157,%eax
02: 53 push %ebx
03: 50 push %eax
04: ba 04 00 00 00 mov $0x4,%edx
05: bb 01 00 00 00 mov $0x1,%ebx
06: b8 04 00 00 00 mov $0x4,%eax
07: 89 e1 mov %esp,%ecx
08: cd 80 int $0x80
09: 58 pop %eax
10: 31 c0 xor %eax,%eax
11: 5b pop %ebx
12: c3 ret

上記を一行ごとに開設すると以下の通りです。
01: 'Waka'の4文字をeaxへ 57='W', 61='a', 6b='k'
02: ebxをスタックへ (元のebxを保存するため)
03: eax(='Waka')をスタックへ
04: edxに4を代入 4は4バイトの意
05: ebxに1を代入 1は標準出力の意
06: eaxに4を代入 4はシステムコール4番(write)
07: esp(スタックポインタ)をecxに代入
08: Intel x86系Linuxでの(レガシー)システムコール
09: スタックの値をeaxに取り出し (03:で入れた値を除去するため)
10: eaxをゼロにする (同じ値のxorは常に0でmovより速いのでxorを使う)
11:スタックの値をebxに取り出し (02:で保存した値を復元するため)
12: 関数から戻る

Cで書けば
write(1,"Waka",4);
の1行で書ける内容をアセンブラで(レガシー)システムコールを使って書いたものですね。
# Cの文字列はヌル終端で"Waka"は5バイトになるので
# 完全には一緒じゃないけど、やりたいことは同じ
呼び出されたシステムコール内ではeaxが4なのでwriteシステムコールとわかり、ebxが1なので標準出力へ、ecxにスタックポインタの先頭すなわち'Waka'のアドレスがあり、edxから4バイト書き込みと分かる。
ここでいう12の解説の関数から戻るというのはどういう意味なのでしょうか?教えて頂けると幸いです。

質問者からの補足コメント

  • では、関数から戻るの「から戻る」とはどこに戻るのかは、考えなくても良いと言うか、省略されていると言う事でしょうか?後、eaxの「0」は、なぜ使えるのでしょうか?教えて頂けると幸いです。

    No.5の回答に寄せられた補足コメントです。 補足日時:2024/10/26 13:15
  • 迅速な回答ありがとうございます!では、eaxの「0」を使用したのはなぜでしょうか?教えて頂けると幸いです。

    No.7の回答に寄せられた補足コメントです。 補足日時:2024/10/26 20:40
  • 当該のプログラム内でサブルーチン XX を呼び出したルーチン
    だからね。
    のそのルーチンは何なのでしょうか?教えて頂けると幸いです。

    No.8の回答に寄せられた補足コメントです。 補足日時:2024/10/26 20:50
  • 分かりました。所で、eaxの「0」をreturnの戻り値として使ったのはなぜでしょうか?教えて頂けると幸いです。

    No.9の回答に寄せられた補足コメントです。 補足日時:2024/10/26 21:28

A 回答 (11件中1~10件)

>関数から戻るの「から戻る」とはどこに戻るのかは、


>考えなくても良いと言うか、省略されていると言う事でしょうか?

省略じゃなくて戻り先はスクックに積まれてます。retはそれを見て
飛ぶだけです。

>後、eaxの「0」は、なぜ使えるのでしょうか?

こういうのはコンパイラやOS等で決まっている Calling Convension(呼び出し規約)を学びましょう。Cの関数呼び出しをマシン語でどう表現するかは一通りではありません。
    • good
    • 0

> return 0 を使っているとなぜわかったのでしょうか?



質問文で与えられた情報から、判るはずがない。
No.6 に書いたとおり、単なる憶測だ。

10: xor %eax,%eax で eax にセットしている 0 が
return 0 の 0 なのかどうかを確認するには、
関数 XX() を呼び出してるコードの方で
XX() の返値をどう扱ってるか検証するしか、方法が無い。
return 0; だと書いたのは、ヤマカンだよ。
    • good
    • 1

> そのルーチンは何なのでしょうか?教えて頂けると幸いです。



またまた、何を聞いてるのか判らん質問を...
日本語が苦手なの?

それが、関数 XX を呼び出したのは具体的にプログラム中のどこか?
という質問なら、答えは「知らんがな」。
呼ばれるほうのコードだけを提示して、どこから呼ばれたかを
回答者が知る方法は無い。ええかげんにせえよ。

どうしてもそれが知りたいなら、プログラムの逆アセンブルから
「call XX」の文字列を検索するか、
そのプログラムをデバッカ内で実行して
12: ret に置いたブレークポイントで停まったときに、
スタックの先頭を見るか、1ステップだけステップ実行すれば
戻る先がどこだったかが判る。

それとも、まさか「ルーチン」とは何か? と聞いてるのであれば、
ルーチンとは、 call, ret 無しで実行される一連の命令からなる
プログラムの断片のこと。高級言語の立場からは、それを
関数とか、プロシージャとか、メソッドとか、いろいろに呼ぶけれど、
要するにアセンブリプログラムから見ると、call で入っていって
ret で抜けてくる一連の命令のカタマリのこと。
この回答への補足あり
    • good
    • 0
この回答へのお礼

return0を使っているとなぜわかったのでしょうか?教えて頂けると幸いです。

お礼日時:2024/10/26 21:33

> 質問の解説の12についてもう少し詳しく教えて頂けると



それを No.2 に書いたんだがな。

12: ret

12: 関数から戻る
と説明したということは、
サブルーチン XX を「関数」だと考えているということ。

ここで関数というのは、たぶん、返値を持つサブルーチンという意味で、
No.6 に書いたように、call XX の次に置かれた命令を実行する時点で
eax に入っている値が XX の返値だという規約なのだろう。

「戻る」ために ret が何をやっているのかは、No.2 に書いたとおり。

C っぽく、
int XX(void) {
  write(1,"Waka",4);
  return 0;
}
と書けば解る?


あと、くどいようだが、
12: ret
で「戻る」行き先は、OS でも、シェルでもなく、
当該のプログラム内でサブルーチン XX を呼び出したルーチン
だからね。
この回答への補足あり
    • good
    • 0

> OSに戻ると言う事はつまりどう言う事でしょうか?教えて頂けると幸いです。



すいません、書き漏れましたが、「OSに戻る」もあくまで一例です。
WindowsのExplorerから起動したプログラムであればExplorerに戻るし、
コマンドプロンプトから実行したプログラムであればコマンドプロンプトに戻ります。
とあるCプログラムから起動した別のプログラムなら、呼び出したCプログラムに戻ります。

そもそも、「戻る」という意味が分からないということですかね?

仕事中に、電話が掛かってきたら、その時やってた仕事を中断して電話に出て話しますよね?電話が終わったら(すぐ来いとかの命令電話でなかったのなら)、さっきまでやってた仕事に戻りますよね?その「戻る」と同じ意味です。

Cプログラムで言うと、

(前略)
f = fopen("filename.txt","r");
if(f) {
(後略)

と書くと、fopen関数が実行されて、そのfopen関数の実行が終わると、このプログラムの次の行であるif(f)が実行されますが、それが「fopen関数が終了する(= fopenプログラム内でreturnが実行されると)と呼び出したプログラムに戻る」という意味です。
この回答への補足あり
    • good
    • 0

> 関数から戻るの「から戻る」とはどこに戻るのかは、


> 考えなくても良いと言うか、省略されていると言う事でしょうか?

ret の機能は、No.2 に書いたとおり。
esp が指すメモリの中身で eip の値を書き換える。
eip が変わるから、次に実行される命令のアドレスが変わる。

どこに戻るのかは、XX の実行が始まった時点で
スタックの一番上に積まれていなければならない。
呼び出し元で call XX を実行して XX: へやって来たのならば、
call を行った時点でスタックはそうなっている。


> eaxの「0」は、なぜ使えるのでしょうか?

何を質問しているのかがよく判らないが...

10: xor %eax,%eax としても良い理由を聞いているのであれば、
呼び出し元(call XX を行った側のコード)で
サブルーチン XX が eax の値を保存することを期待してないからでしょう。

何のために 10: xor %eax,%eax としているのか? を聞いているのなら、
それは、この断片的なコードからは判断する方法がないが、
おそらく XX が eax に返値を入れて返すという規約にしてあるのでしょう。
 xor %eax,%eax
 ret
で、合わせて retuen 0; をやってるつもりというか。

システムコールの返値を扱わずに XX の返値を 0 に固定しているのは、
たぶん、XX の返値はエラーコードを意味していて、
システムコール4番でエラーが生じることは考えてないからでしょう。


あと、ちょっと気になったんだが、86系なら
mov は mov 移す先,移す元 の順だよね?
01: mov $0x616b6157,%eax は変だと思うのだけれど。
    • good
    • 1
この回答へのお礼

質問の解説の12についてもう少し詳しく教えて頂けると幸いです。

お礼日時:2024/10/26 15:06

int main() から return 0; すると、


制御は C のスタートアップルーチンに戻る。
OS に戻るには、スタートアップルーチンの中で
それなりのシステムコールを呼び出す必要がある。
この回答への補足あり
    • good
    • 0

Cが分かるのであれば、Cのreturn;のことです。


関数からreturn;すれば、関数呼び出しの直後に戻ります。
int main()から return 0; すると、OSに戻ります(返り値は 0 でなくてもい良いのであくまで一例です)。
    • good
    • 0
この回答へのお礼

OSに戻ると言う事はつまりどう言う事でしょうか?教えて頂けると幸いです。

お礼日時:2024/10/26 09:37

質問のコードが関数(サブルーチン)だということです。


ret で呼び出し元に戻ります。
正確にはサブルーチンを呼び出した命令の次の命令へ行きます。
    • good
    • 0
この回答へのお礼

では、関数から戻るの「から戻る」とはどこに戻るのかは、考えなくても良いと言うか、省略されていると言う事でしょうか?後、eaxの「0」は、なぜ使えるのでしょうか?教えて頂けると幸いです。

お礼日時:2024/10/25 17:50

86系の32ビットモードですかね。



ret は、スタックトップの内容を命令ポインタへポップする命令です。
あえて変なアセンブリもどきで書けば
 mov %eip,[%esp]
 add %esp,4
みたいなもの。
プログラムのどこかで
 call XX
を行って、このコードへやってきたはずですが、
ret を実行すると、その call の次の命令へ制御が移ります。

「12: 関数から戻る」とありますが、そこは
「ルーチンから戻る」のほうが穏当でしょう。
C の return など、高級言語でいう「関数から戻る」には
ret 以外にもいろいろな処理が必要です。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!