私は楽しみと利益のためにコルーチンを実装しようと決心しました(私はそれを私がそれらと呼ぶべき方法だと思います)。アセンブラを使用する必要があると思います。これを実際に何かに役立てたい場合は、おそらくCを使用する必要があります。
これは教育目的であることに注意してください。すでに構築されているコルーチンライブラリを使用するのは簡単すぎます(そして実際には面白くありません)。
あなたたちは知っsetjmp
ていlongjmp
ますか?スタックを事前定義された場所まで巻き戻し、そこから実行を再開できます。ただし、スタックの「後で」に巻き戻すことはできません。早く戻ってくるだけです。
jmpbuf_t checkpoint;
int retval = setjmp(&checkpoint); // returns 0 the first time
/* lots of stuff, lots of calls, ... We're not even in the same frame anymore! */
longjmp(checkpoint, 0xcafebabe); // execution resumes where setjmp is, and now it returns 0xcafebabe instead of 0
私が欲しいのは、スレッド化せずに、異なるスタックで2つの関数を実行する方法です。(明らかに、一度に実行されるのは1つだけです。スレッド化はありません。)これら2つの関数は、もう一方の実行を再開できる(そして自身の実行を停止できる)必要があります。彼らがlongjmp
他の人と一緒にいた場合のように。他の関数に戻ると、元の場所(つまり、他の関数に制御を与えた呼び出し中または呼び出し後)から再開する必要があります。これは、にlongjmp
戻る方法と少し似ていますsetjmp
。
これは私がそれを考えた方法です:
- 関数
A
は、並列スタックを作成してゼロにします(メモリなどを割り当てます)。 - 関数
A
は、すべてのレジスタを現在のスタックにプッシュします。 - 関数
A
は、スタックポインターとベースポインターをその新しい場所に設定し、ジャンプバックする場所と命令ポインターを戻す場所を示す不思議なデータ構造をプッシュします。 - 関数
A
はそのレジスタのほとんどをゼロにし、命令ポインタを関数の先頭に設定しますB
。
これは初期化用です。これで、次の状況が無期限にループします。
- 関数
B
はそのスタックで機能し、必要な作業をすべて実行します。 - 機能は、中断して再び制御
B
を与える必要があるポイントに到達します。A
- 関数
B
は、すべてのレジスタをスタックにプッシュし、最初に与えられた不思議なデータ構造 を取得し、スタックポインタと命令ポインタを指示された場所に設定します。その過程で、再開する場所を指示する新しい変更されたデータ構造が返されます。A
A
A
B
- 関数はウェイクアップし、スタックにプッシュしたすべてのレジスタをポップバックし、割り込みをかけて再び制御
A
を与える必要があるポイントに到達するまで機能します。B
これはすべて私にはいいですね。しかし、私が完全に安心していないことがいくつかあります。
- どうやら、古き良きx86には、
pusha
すべてのレジスタをスタックに送信するこの命令がありました。ただし、プロセッサアーキテクチャは進化しており、x86_64では、より多くの汎用レジスタと、おそらくいくつかのSSEレジスタがあります。pusha
私は彼らを後押しする証拠を見つけることができませんでした。mordernx86CPUには約40個のパブリックレジスタがあります。私はすべてのことをpush
自分でしなければなりませんか?さらに、push
SSEレジスターはありません(同等のものは必ずありますが、私はこの「x86アセンブラー」全体に慣れていません)。 命令ポインタの変更は、言うのと同じくらい簡単ですか?ただmov rip, rax
(Intel構文)のようにできますか?また、それから値を取得することは、それが絶えず変化するので、いくらか特別でなければなりません。私が好きならmov rax, rip
(Intel構文も)、命令rip
の上、mov
その後の命令、またはその間のどこかに配置されますか?jmp foo
です。ダミー。- 不思議なデータ構造については何度か触れました。これまでは、ベースポインター、スタックポインター、および命令ポインターの少なくとも3つが含まれている必要があると想定していました。他に何かありますか?
- 何か忘れましたか?
- 私は物事がどのように機能するかを本当に理解したいのですが、それを実行するライブラリがいくつかあると確信しています。何でも知ってますか?スレッドのように、POSIXまたはBSDで定義された標準的な方法はあり
pthread
ますか?
私の質問のテキストウォールを読んでくれてありがとう。