page0055
のバックアップ(No.3)
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
バックアップ一覧
差分
を表示
現在との差分
を表示
ソース
を表示
page0055
へ行く。
1 (2013-07-30 (火) 18:49:45)
2 (2013-07-30 (火) 19:39:43)
3 (2013-07-31 (水) 15:55:51)
OSECPUのラベル命令
(by
K
, 2013.07.30)
↑
(0) はじめに
OSECPUのバイトコードにはラベル命令というのがあります。実はこれは非常に奥が深いので、ここで1ページかけて説明しようと思います。
参考:
page0043
の(8)
↑
(1) ラベル命令は特異な命令
まず、多くのCPUはこんな命令を持っていません。確かにアセンブラにはたいていラベル定義命令はあります。でもそれは疑似命令であって、対応するCPUの命令はないのです。
普通の機械語は、分岐先を指定するときに、○○バイト先へ進め、○○バイト前に戻れ、などと書きます。だからラベルなんてなくても分岐先を記述できるのです。実CPUではないJavaでさえ、この仕様になっています。・・・OSECPUがどれほど変わっているか分かるでしょうか。
そもそもラベル命令をわざわざ書かなければいけないというのは、機能密度の観点では不利です。他のCPUはそんなものを置いておかなくても分岐先を記述できるのですから。・・・にもかかわらず、OSECPUはラベル命令があり、そしてこれを使わなければ分岐できないのです。
↑
(2) ラベル命令のメリット
それでもラベル命令があるのは、つまり捨てがたいメリットがあるからです。
ラベル命令があって、分岐先に必ずこれを指定するということは、逆に言えばここ以外の場所には分岐しないということです。この情報はJITコンパイラにはとても助けになります。しかしまあこんなものはJITコンパイラのパスを増やせば同等のことができるのではありますが。
ラベル命令方式だと、命令の区切り以外の中途半端なところへ分岐するという可能性は確実に完全に排除できます。
ラベル番号だと、結果的に少ないバイト数で分岐先を表現できる可能性があります。いうなれば、ショートブランチが遠くまで届く、という感じです。これは有利です。先ほどは機能密度の観点から不利だと書きましたが、これを加味すると、不利じゃないかもしれません。
そして最後ですが、実はラベル命令は「分岐先を示すためだけの、何もしない命令」ではないのです。何かするのです。この説明を以下でしようと思います。
↑
(3) 無限ループ対策
seccamp2013
の(6)のPDFの「OSECPUのセキュアの仕組み #07」のところで、OSECPUには無限ループ対策があると書きました。そして
OSECPUでは、分岐命令を実行するたびに、分岐回数カウンタという内部変数が+1されます。
とも書きました。
この説明だと、いかにもJMP命令に細工をするように見えるかもしれませんが、実際は細工されるのはラベル命令の方です。つまりラベル命令は分岐回数カウンタをカウントアップするコードに変換されるのです。
ここで、なぜJMP命令ではなくてラベル命令の方に細工をするのかを説明します。これは単純で、JMP命令の個数はラベル命令の個数よりも多いからです(等しい場合もあり得ますが)。だったら細工する数が少ないほうがいいです。どっちにいれても結果は大差ないです。
なお、PDFにも書いていますが、16命令以上、ラベル命令以外が連続した場合は、そこにも強制的に分岐回数カウンタ++のコードを入れます。
↑
(4) OSECPUにおける割り込み処理
ちょうどいい機会なので、OSECPUにおける割り込み処理についてもついでに書きたいと思います。
OSECPUにも割り込みの仕組みはありますが、一般的な割り込み処理とは異なり、いつどこで割りこまれるかわからない、というものではありません。ラベル命令のところで割りこまれます。
なぜか?・・・それは割り込み処理が終了した後に、元の処理に戻らないといけないからです。戻るためにはラベルが必要です。だから他のところで割り込むわけにはいかないのです。
OSECPUには割り込み禁止命令(CLI)とか、割り込み許可命令(STI)はありません。ラベル命令さえ書かなければ割りこまれないからです。またラベル命令には何とオプションコードがあって、このオプションコードによって、どの程度の割り込み処理を許容するのかを指定することができます。
OSECPUは非常にレジスタが多く、タスク切り替えのコストは相当なものになる可能性があります。それに対して、このラベル命令のところで割り込みやタスク切り替えが発生するという仕様は、相性がいいです。というのは、アプリは処理が一段落したところでタスクスイッチを受けれればいいからです。これならすべてのレジスタを保存する必要はないでしょう。
平たく言えば、タスク切り替えを受け入れられるラベル命令は、レジスタを破壊する命令なのです。たとえば「R30~R3F, P30~P3Fの値は破壊されます」という仕様になるかもしれません。これはつまり、タスクスイッチに際して、これらのレジスタを保存していないということでもあります。
この仕様は結局、割り込み要求が来て待機状態になったら内部のフラグを1にして、ラベル命令のところでこのフラグをチェックしてCALLやタスク切り替えしているだけです。つまりハードウェアの割り込み機能を一切利用していません。だから割り込み機能を持っていないCPUへもOSECPUは移植可能なのです。
またタスク切り替えを許容するラベル命令が長い間来なかったら、それはセキュリティ例外です。長い間かどうかを決める基準は、もちろん分岐回数カウンタを使います。
↑
(5) そのほか
http://nerry.hatenablog.com/entry/2013/07/30/203428
によると、neriさんの意見としては、ラベル命令は機能密度的に有用で、アプリもJITコンパイラも小さくなるそうです。なるほどー。
↑
こめんと欄
コメント
お名前
NameLink