• ベストアンサー

ret とretfについて。

アセンブリ言語では、retとretfとはどういう事でしょうか?nearリターンとfarリターンの違いは何でしょうか?教えていただけないでしょうか?すみません。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

あ、ミス#2さん指摘ありがと。 x86系は、PCじゃなくてIP=インストラクションポインタですね^^ こちら、80系出身なもので(んま、asm職人にはどっちでも通じますが^^)一応ミスはミス。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.3

>直訳するとセグメントは分割ですが、nearは現在の分割に戻る。farは、分割も復元して戻る。という意味になると思うのですが、どういう事でしょうか?差し支えなければ教えていただけないでしょうか? すみません。 英語的にも、認識としてもそれであってますよ。 32ビットだと、話が面倒なので16ビットモードで説明しますが。 call 0x1234 これは、今いるセグメント内の「1234番地をコールしますよね」 しかし、16ビットは、65536バイトしかありません。 初代8086は、1MByteのメモリを搭載可能でした。 しかし、16ビットでは、1MBをアクセスできないのですよ。 なので、セグメントという「区画わけ=部屋分け」=つまりは分割 する概念が入りました。 同じ、65536=64KB内にある、関数や番地は「Near」と呼ばれ 直接値を書けばジャンプなりコールできます。 しかし「それより外はどうするの?」 ということになり、16バイトを1つと数える セグメントが導入されました。 0000:0000=これは、0番地 0000:0010=これは、16番地こっちはNear 0001:0000=これも、16番地これはFarになる。 で、16ビットx16を1として数える=65536x16=1MB になったのです。 なので、 call near 0x1234 これは、SS:SPレジスタに「次の番地をスタックに入れて0x1234番地にジャンプ」する命令 ret スタックから1つの値を取り出す=これが、「次の番地」 そこにジャンプする。 となります。 今度は、 call far 0x1234:0x5678 この場合はSS:SPレジスタ位置に「現在のCSと次の番地を入れてから、CS=1234をセットした上で、0x5678へジャンプ」する命令になります。 なぜ、retが2つあるのかは、これでわかったと思いますが。 call far の後、retすると、上の例では、本来の位置ではなく、 CS=1234のままで、この命令の次の番地の「下位16ビットに飛んでしまいます」 これを避けるための命令がretf ってことです。 なお、ジャンプ命令と、コール命令をごちゃごちゃに書いてますが。 実は「同じ」です。 mov ax,offset next push ax jmp function :function ret このRET命令がaxに入れていたnextの番地を復元してそこにジャンプ :next ここにきます。 要するに、callとjmp命令は、スタックを使うか使わないかだけで、 同じ物なんです。 なお、スタックというのは、SP(スタックポインタ)ですが、 これも、16ビットなので、当然64Kしかないので、 これにもSS(スタックセグメント) を補うことで、1MB空間を表せるように拡張されています。 CS:PC CS=コードセグメント:PC=プログラムカウンタ これが、プログラム用の、セグメント データは、 DS:データセグメント(何もしなければ常にDSを指してます) と、用途ごとにセグメントが複数あるのもこのためです。 そうしないと、 「今いるセグメントのデータしか読み書きできない」為です。 特殊なもので、用途が決まっていないESなどもあります。 これらは、    mov ax,[0x1234] これは、DSセグメント内の0x1234番地にあるデータを16ビット取り出せ!の命令    mov ax,es:[0x1234] これは、ESセグメント内の0x1234番地にあるデータを16ビット取り出せ!の命令 (これをセグメントオーバーライドと言います) それが「さらに複雑になってページという扱いになってる」 286以降のセグメントレジスタです。 なので、説明したくないほど面倒です。 なので、勉強が目的なら、リアルモード(リニア)86で 止めておく方が、いいかと。

zasx1097
質問者

補足

しかしからもう少し詳しく教えていただけないでしょうか?すみません。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65535
  • ベストアンサー率43% (8536/19408)
回答No.2

x86系CPUは、レジスタが16ビットなので、アドレスも16ビットで記憶しています。 16ビットだと、表現できるのは「0000~FFFF」の範囲だけなので、メモリ空間は64キロバイトまでしか表現できません。 しかし、x86系CPUのアドレスバスは20ビットなので、20ビットのアドレスを、16ビットのレジスタ2つの組み合わせで表す事にしました(実アドレス空間は0x00000~0xFFFFFまでの1メガバイトです) 具体的には「セグメントレジスタ×16+オフセットレジスタ」という計算で、20ビットの実アドレスを表現しています。 この時、16倍される上位の方を「セグメント」、そのまま足される下位の方を「オフセット」と言います。 つまり、1メガバイトのアドレス空間を「64キロバイトごとの空間」に分割して、表現しているのです。この「分割」の上位アドレスを表すのが「分割」を意味する「セグメント」なのです。 例えば、セグメント0x1F53、オフセット0x0106の場合、実アドレスは0x1F636になります。 X86系CPUの「プログラムカウンタ(今、どこのメモリのプログラムを実行しているかを覚えているレジスタ)は、セグメントの方はCSレジスタ、オフセットの方はIPレジスタが保持しています。 RET命令を実行すると、CPUは「戻り場所を記憶しているメモリ」から16ビット分のデータを取り出して、それをIPレジスタに代入して、IPレジスタの指す場所から実行を再開します。 RETF命令を実行すると、CPUは「戻り場所を記憶しているメモリ」から16ビット分のデータ2つを取り出して、それをCSレジスタとIPレジスタの2つに代入して、CSとIPレジスタの指す場所から実行を再開します。 なので、サブルーチンを呼び出す際は、呼び出されるサブルーチンがRETで終わっているかRETFで終わっているかを意識して、NEAR CALLで呼ぶべきかなのかFAR CALLで呼ぶべきなのかを明確にしないといけません。 RETで終わってるサブルーチンはNEARで呼ぶ、RETFで終わっているサブルーチンはFARで呼ぶ必要があります。間違うと、帰るアドレスが違ってしまい、プログラムが暴走します。

zasx1097
質問者

お礼

RET命令を実行すると、CPUは「戻り場所を記憶しているメモリ」から16ビット分のデータを取り出して、それをIPレジスタに代入して、IPレジスタの指す場所から実行を再開します。 RETF命令を実行すると、CPUは「戻り場所を記憶しているメモリ」から16ビット分のデータ2つを取り出して、それをCSレジスタとIPレジスタの2つに代入して、CSとIPレジスタの指す場所から実行を再開します。 ここを詳しく教えていただけないでしょうか?すみません。

zasx1097
質問者

補足

しかしから詳しく教えていただけないでしょうか?すみません。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

https://okwave.jp/qa/q9895187.html この板で、これ回答済みですが、 https://www.felixcloutier.com/x86/ret 説明文に、 Near return — A return to a calling procedure within the current code segment (the segment currently pointed to by the CS register), sometimes referred to as an intrasegment return. Far return — A return to a calling procedure located in a different segment than the current code segment, sometimes referred to as an intersegment return. と書いてますよ。 nearは現在のセグメント内で戻る。 farの方は、セグメントも復元して戻る。 の違いだと。 なお、CSってのが、CodeSegmentレジスタの事です。 あと、書くときIA32やx86と必ず書いた方がいいです。 世の中にIntel以外のCPUもたくさんあり、 当然、機械語も全部違うので、言語を特定しなければ 明後日の回答が付くことは避けられませんので。 さらに面倒なのが、x86はモードごとに命令が変わるので、 一つのCPUですら、命令が違うという問題も持っているので、 今は、32ビット以上のIntelCPUをアセンブラで書く人は ほぼいないですよ。 勉強したいならx86(リアルモード)が一番、お勧めですね。 https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%83%86%E3%82%AF%E3%83%88%E3%83%A2%E3%83%BC%E3%83%89 今説明に使ってるのは、「386のプロテクトモード」 の命令形ではあります。 IntelのCPUって上位互換=つまり、過去の命令も実行できる関係で、 相当複雑なので、勉強するには、一番最悪なCPUですんで。 勉強が目的ならRISC系の方がいいかとは思いますけどね。 んま、後は頑張って!

zasx1097
質問者

補足

nearは現在のセグメント内で戻る。 farの方は、セグメントも復元して戻る。 の違いだと。 直訳するとセグメントは分割ですが、nearは現在の分割に戻る。farは、分割も復元して戻る。という意味になると思うのですが、どういう事でしょうか?差し支えなければ教えていただけないでしょうか?すみません。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • retやretfについて。

    アセンブリ言語では、retとretfとはどういう事でしょうか?nearリターンとfarリターンの違いは何でしょうか?教えていただけないでしょうか?すみません。 nearは現在のセグメント内で戻る。 farの方は、セグメントも復元して戻る。 の違いだと。 直訳するとセグメントは分割ですが、nearは現在の分割に戻る。farは、分割も復元して戻る。という意味になると思うのですが、どういう事でしょうか?差し支えなければ教えていただけないでしょうか?すみません。

  • 機械語に直すことについて。

    (機械語データ) (アセンブリ言語) b8 57 61 6b 61 mov $0x616b6157,%eax 53 push %ebx 50 push %eax ba 04 00 00 00 mov $0x4,%edx bb 01 00 00 00 mov $0x1,%ebx b8 04 00 00 00 mov $0x4,%eax 89 e1 mov %esp,%ecx cd 80 int $0x80 58 pop %eax 31 c0 xor %eax,%eax 5b pop %ebx c3 ret これのintと movとxor の機械語が分かりません。後、retの機械語が、farなのかnearなのかも分かりません。教えていただけないでしょうか?すみません。

  • アセンブリ言語についてと言語の違いについて。

    高水準と低水準言語の違いは、まず、マシン語の2進数の羅列では分からないからアセンブリ言語が生まれ、 アセンブリ言語よりさらに人間が理解できる言語が、C言語やBASICなどでしょうか?教えていただけないでしょうか?合っていますでしょうか?

  • アセンブリ言語とニーモニックの違いってなんですか?

    アセンブリ言語とニーモニックの違いってなんですか?

  • 囚人のジレンマゲーム C言語

    囚人のジレンマゲームをC言語で作りました。そのうちのこの部分を変えて、相手が協調の際に9回まで裏切り、後は全部協調とするにはどうしたらいいのでしょうか。 int you(int bc) //PLAYER1 { int ret; /* if(bc==COOPERATION){ret=COOPERATION;} else{ret=DEFECTION;} */ ret=DEFECTION; return(ret); }

  • 機械語とアセンブリ言語の違いを教えてください

    機械語とアセンブリ言語の違いを詳しく教えていただけんか?

  • アセンブリのプログラムです。

    アセンブリのプログラムで質問があります。cのプログラムのオブジェクトファイルを生成して、objdumpというコマンドでアセンブリ言語を表示させてみたのですが、全然分からなくて、困っています 。どうか、アセンブリプログラムの、解説をよろしくお願いします。できれば、1文1文解説してもらえるとありがたいです。あと、スタックの動き、確保などの解説もあるとありがたいです。よろしくお願いします。 cのプログラム int fact(int p) { if(p<=1) return 1; else return fact(p-1); } アセンブリのプログラム push %ebp mov %esp,%ebp sub $0x8,%esp cmpl $0x1,0x8(%ebp) jg 15 <_fact+0x15> movl $0x1,-0x4(%ebp) jmp 24 <_fact+0x24> mov 0x8(%ebp),%eax dec %eax mov %eax,(%esp) call 0 <_fact> mov %eax,-0x4(%ebp) mov -0x4(%ebp),%eax leave ret nop nop nop

  • デバイスドライバー作りに関する質問

    デバイスドライバーでは、アセンブリ言語を使う部分があるとの事で、アセンブリ言語の技術を伸ばす為、デバイスドライバーを作ってみようと思うのですが 実際はどれくらいアセンブリ言語を使うのでしょうか またはデバイスドライバーというのは組み込みの分野ですか?

  • 低水準言語について。

    低水準言語があるのは、例えば、この人は、これができた。あの人は、これができた。しかし、一つだけできたのでは、意味がないから、それを総称(合併)して、アセンブリ言語という名前になった。で、 アセンブリ言語がなければ、C言語などの高水準言語は、誕生していなかった。という事で、合っていますでしょうか?教えていただけないでしょうか?すみません。

  • C言語の関数の質問です

    C言語の質問です 最近C言語を始めました。以下の問題がわかりません。 int型の数値を入力して結果をdouble型の戻り値を返すことはできないのか。 関数の値のやり取りでも暗黙の型変換や明示的な型変換はできるのか。 #include <stdio.h> double square(int x); int main(void) { int num;   double ret;   scanf("%d",num); ret = square(num);    printf("%ld",ret); return(0); } double square(int x){ return(x*x); }