KRAZY感情TEXTYLE

"くれいじー かんじよう てきしたいる" と読みます

30日でできる! OS自作入門 を読むために nasm_of_nask というコンパイラを作った話

この記事は はてなエンジニア Advent Calendar 2020の22日目の記事です。 昨日はid:motemen さんの PCを離れたらマイク音量を下げるmacOSアプリを作った - 詩と創作・思索のひろば でした!

qiita.com

経緯

とこぼしたところ、著者の 川合秀実 (@hkawai3) | Twitter さん*1 を始めとした各種大先生に目をつけられて*2しまい、やらなければ肉体が低レイヤから順に消されると思い読み始めました。

30日でできる! OS自作入門

30日でできる! OS自作入門

しかし、この本の初版は2006年であり時代はフロッピィ〜〜〜〜〜〜から†SSD†なわけで、macOS上で動かすための環境構築はqemuを使ったり、本の中で使われているツールのmacOS版を用意する必要があります。

github.com

このように、以前までは有志が用意をしてくれていたので何とかなっていました。あのOSが出るまでは。

macOS Catalina

macOS Catalinaからついに32ビットアップリが使えなくなりました。これの影響で上記のリポジトリで提供されているnaskを使おうとするとbad CPU type in executableするわけです。

代替手段としてのNASM

naskの代替手段としてはNASMを使ったりすると良いらしいです。しかし、naskとNASMはコンパチではないのでいくつかサンプルコードを修正する必要があります。

『30日でできる!OS自作入門』を macOS Catalina で実行する - Qiita から修正する表を引用したものがこちらです。

nask NASM
RESB 18 TIMES 18 DB 0
RESB 0x7dfe-$ TIMES 0x1fe-(−−$) DB 0
ALIGNB 16 ALIGN 16, DB 0
[FORMAT "WCOFF"] この行削除
[INSTRSET "i486p"] この行削除
[FILE "naskfunc.nas"] この行削除
[FORMAT "WCOFF"] この行削除
JMP entry JMP SHORT entry
_io_hlt( _ の付くもの) io_hlt( _ を削除)

な〜〜〜んだこれだけなんだ!簡単ですね!!!

しかし

この表を一々頭に覚えるのはめんどくさい、めんどくさいですよね?*3いっそのことnaskを作り直すのもいい*4が、多分その時間でこの本読み切れるな、という葛藤がありました。そこで僕なりのアプローチとして 「「「nask のコンパイリ*5を受け取って NASM にコンパイルするだけのめちゃくちゃ簡単なコンパイラ」」」を書けばいいんじゃないか?と思って用意したものがこちらになります。

nasm_of_nask

github.com

最近は趣味でocamllexとmenhirばっか書いてたし、OCamlと仲良くなりたかったので実装言語に選びました。本質っぽいところはここでそれ以外はまんまを吐き出す本当にやるだけのコンパイラです。命名規則OCaml の型変換関数 *6 をリスペクト*7しました!ℒℴѵℯ...

対応状況

対応してる共通部

  • DB
  • DW
  • DD
  • RESB
  • 16進数
  • 10進数
  • 文字列(エスケープ無し)
  • セミコロンを使ったコメント

naskとNASMの差分

nask NASM 対応してる?
RESB 18 TIMES 18 DB 0
RESB 0x7dfe-$ TIMES 0x1fe-(−−$) DB 0
ALIGNB 16 ALIGN 16, DB 0 ×
[FORMAT "WCOFF"] この行削除 ×
[INSTRSET "i486p"] この行削除 ×
[FILE "naskfunc.nas"] この行削除 ×
[FORMAT "WCOFF"] この行削除 ×
JMP entry JMP SHORT entry ×
_io_hlt( _ の付くもの) io_hlt( _ を削除) ×

Future work

  • 対応増やす
  • CIとかでいい感じにバイナリをビルドする
    • これから始める全人類がnaskの代わりにこれとnasmを使うコバンザメ戦法したい

締め

気づいた方は5000人ぐらいいらっしゃるとは思いますが、id:Krouton は1日目で出てくる差分しかやっていません。何故かと言えばまだ1日目しか読んでない*8からです!ガハハ!

オチもついたところで解散とします!明日の担当はid:pokutunaさんです!!

*1: 川合さんへ: 1年以上関わりがあるのにずっと読む読む詐欺しててすみません!!!!!

*2: ふぁぼられただけです、所でふぁぼって死語ですか?

*3: この記事書いてから気づいたんですけど、そんなに多くないな...

*4: DB命令だけ使えるnaskなら書けそう

*5: この人生が裏目りやすい!2021 on Twitter: "caller-callee-callの関係を考えればコンパイラ-コンパイリ-コンパイルの関係も自明"

*6:OCamlプリミティブな型変換関数は to_of_from といった命名規則が多い。例えば int から char だったら char_of_int みたいな

*7: 世の中にはOCaml から JSを吐く処理系もある GitHub - ocsigen/js_of_ocaml: Compiler from OCaml to Javascript.

*8: 参加してる読書会が2つあるのに気づいてそっちをやらないと本当にまずい

whywaitaはフッ軽

この記事は whywaita Advent Calendar 2020 の 22日目の記事です! 21日目の記事は id:yu_ki_kun_0 さんが担当でした!

adventar.org

ここ2ヶ月くらい whywaita と僕はラーメンをよく食べに行きます。そのうち2回とも当日の夕方に「行きたいね〜」「今日行くか!」となってる感じです。

1回目

f:id:Krouton:20201221202954p:plain
1回目食べに行った時の流れ

仕事終わりに渋谷から電車で40分かかる東京の端の方の梶原*1まで来てくれました! まあ僕は横浜から梶原*2まで行ったんですけどね!!!!! その後はHUBに行ったので本当に二郎からのセイクで優勝ですね!

食べに行ったお店

ramendb.supleks.jp

2回目

f:id:Krouton:20201221202825p:plain
2回目食べに行った時の流れ

f:id:Krouton:20201221204131j:plain
らーめん玄 / 小ラーメンブタ増し にんにく

食べに行ったお店

ramendb.supleks.jp

まとめ

この2回のラーメン*3から分かるようにwhywaitaさんはフッ軽*4なので例えば明後日のクリスマスイブやクリスマス当日、大晦日やお正月に寂しい方は誘ったら来てくれます*5!是非whywaitaと楽しい時間を!

明日の担当は id:kadokusei です〜

アイキャッチ

f:id:Krouton:20201221203934j:plain
アイキャッチ

*1: 渋谷から梶原までの乗換案内 - NAVITIME

*2: 横浜から梶原までの乗換案内 - NAVITIME

*3: ラーメン以外でも多分来ます、何故かと言えば1時間近く並んでこんなラーメン食べるなんて重たいイベントは他にないしそれに来てくれるんだから他の用事なんてもっと来てくれる。ディズニーとかでも多分

*4:もしかして僕もフッ軽なのか...!?これが深遠を覗く時はッって奴...!!

*5: 保証はしません

Kroutonの睡眠を支えるほげほげ

この記事は whywaita Advent Calendar 2020 - Adventar 11日目の記事です

adventar.org

前回は kyontan ICTSCのコンテストサイトを支えた技術 でした! 飛行機乗りたいけど免許も取りたいしそもそも机とかも欲しいので優先度ガタ落ちしてます!!!!ちなみにあんま元気じゃないです、kyontanさんは卒業できそうですか??

本筋

ところでみなさん睡眠してますか?してない方は成仏してくださいませ。僕は睡眠は好きなのですが、如何せん下手くそです。長く寝れないし寝付きもまともにできない...、車の中はもちろん、飛行機、新幹線や電車(グリーン車含む)でも寝れないし、旅行先の寝具が違う環境になるだけで寝れなくなります。

旅先

旅行先の睡眠

レム睡眠3割!!!旅行好きなのにホテルだと睡眠が大抵しんどいので困った...。大体悪夢見ますよね旅行先だと、前は歯が全部抜ける夢見ました。

自宅で普通に寝れた時

自宅睡眠

深い眠りが短く下手くそなのは今後の課題なのですが、それはそれとして前は自宅でも寝付くことができませんでした。

そんな自分が多少は寝付けるようになった色々を紹介していきたいと思います。

ロフテーキューブ(羽毛) 4号*1

https://www.lofty.co.jp/wordpress/wp-content/themes/lofty/images/common/product/standardpillow/standard_cube.jpg

社会人になってから真っ先に買ったものです。肩幅デカい族なので4号が良い。

他のメーカーの枕をあまり試していないのですが、とりあえず横浜の実店舗に行って試せたのがめっちゃプラス。店員さんが布団の硬さや自分の骨格と好みに合わせて選んでくれるのでとても助かる。

加重毛布

これがとても良い。このように全てを破壊してしまくらい寝相悪いので朝起きたら毛布無いなんてザラ。

これ被せてから起きた時に毛布かぶってる率が80%くらいまで上がった。その代わり二度寝率も上がったけど。

この寝相が悪い2020

メラトニン

jp.iherb.com

はい、メラトニンサプリメントです。多分19時とか20時くらいに飲むといい感じに眠くなるのですが、ゲームやコーディングしてるとすぐ飛んじゃうので結局それらが終わってからいつも飲んでます。

商品より送料のほうが高いし、60個入りのものを1つずつしか税関の都合上買えないのが難点。後述する薬を飲み始めるまではとても頼りにしていました。

リーゼ(クロチアゼパム) 5mg

medical.nikkeibp.co.jp

ついに出てきました、精神科/心療内科などで処方されるお薬です。寝る前に飲んでいます。不眠とは別で通っているのですが、そこそこ催眠作用が強い割に依存性が強くないのでいいですね。前は朝にも別の薬と同時に服用してましたが本当に仕事にならないので止めました。

飲酒をしない

上2つのサプリメントと薬を服用し始めてからかなり減らしました。飲むにしても早い時間とか、入眠失敗してもいい日だけ飲むようにしてます。もっとお酒飲みたい〜〜〜〜〜〜〜

結び

睡眠は大事にしましょう、明日は id:nersonu さんの当番です!!!!

追記 (2020/12/11 16:06)

Kroutonの睡眠を支えるほげほげ - KRAZY感情STYLE

枕良さそう.今使ってる枕なんか合ってない気がするので気になる.セニラン飲んでるのでだいたい仲間っぽい.ところで睡眠測定するアプリなんてやつですか

2020/12/11 11:41

Xiaomi の mi band 5 ってスマートウォッチをつけて寝てます!

play.google.com

*1:画像は公式サイトから引用

self.age++; // 今年で24歳になる

11/23が誕生日です、今年も無事に年齢がインクリメントされました。毎年この日は祝日なので学校とかで祝われたことがないまま全て卒業してしまいました。心はまだ14-17歳くらいなのに肉体は...助けて...。社会に出ていますが何もわからない...。とりあえずコンパイラと低レイヤとWeb(ReactとかTypeScriptは特に)はまだ切っても切れなさそうな関係にあるのでその辺りを重点的にやっていきたいと思います。あと何かの勉強会とかLTに登壇もやっていきたいな

例のアレ

sshuttleっていうOSSにcontributeした

色々あって sshuttle/sshuttle というPythonで書かれたOSSソースコードを読んでいたのですが、デグレっぽいところがあったのでPR投げてマージされました。
github.com

これまで能動的なOSSプロダクトへのコントリビュートは予めIssueが立っているものの修正や、ドキュメントへのtypoぐらいだったんですけど初めてソースコードを眺めて自分から*1見つけることができたので嬉しいです。でも本質のソケットプログラミング的な部分はマジで何もわからんので助けて

*1: 僕が見つけて「これデグレってる?」って直接聞いてくれたのは同僚でした、感謝

ISUCON10にTrust Rustチームとして参加して予選敗退しました

てがきはてなブログがリリースされた日に書いたんですけど誤操作で消しちゃって萎えてましたが再度書きました。一緒に出てくれてた id:dekokunid:stefafafan には感謝です。僕は実装を読んでゴリゴリやる役目だったのに筋力が足りなくて全然出来ませんでした、来年はもっと強くなります。 f:id:Krouton:20201007170640j:plain

チームメイトのエントリ

具体的に何したとかはチームメイトの奴を読んだほうが早いです

dekotech.dekokun.info

stefafafan.hatenablog.com

std::sync::mpsc::channelで少しハマったのでメモ

std::sync::mpsc - Rustの挙動についてちょっと知見を持ったので綴っていく。

やりたいこと

めっちゃ重たいタスクがN個あって、それぞれにスレッドを作ってmpsc::channel経由でメインスレッドに値を返してもらう例を考える。

use std::thread;
use std::sync::mpsc;

let (tx, rx) = mpsc::channel();
for costly_task in costly_tasks.into_iter() {
    let tx = mpsc::Sender::clone(&tx);
    thread::spawn(move || {
        let val = costly_task();
        tx.send(val).unwrap();
    });
}

for val in rx {
    dbg!(val);
}

これだと実は下のfor文を抜けることは出来ない。実際にplaygroundでやると強制的にkillされていることが確認できる。

play.rust-lang.org

ではどうするのか?というと for文の前で drop(tx); を呼んであげる必要がある。

for costly_task in costly_tasks.into_iter() {
 // ...
}

drop(tx);

for val in rx {
//  ...
}

僕みたいになぜ?となった方へこの問題をもう少し簡単にしてみる。ならなかった人はスター押してはてブ追加して頂ければ大丈夫です。

簡単にした例

use std::sync::mpsc;

let (tx, rx) = mpsc::channel();
let tx1 = mpsc::Sender::clone(&tx);

tx1.send(1).unwrap();

for val in rx {
    dbg!(val);
}

これも同様にfor文を抜けることが出来ない。というわけで drop(tx); drop(tx1); を追加してみると同様に抜けることができる。

play.rust-lang.org

どうやらfor _ in rx { ... }はsenderが値が送りきるのを待つ挙動をしているようだ、とのことでドキュメント 1 を確認しに行く。

Returns an iterator that will block waiting for messages, but never panic!. It will return None when the channel has hung up.

うんうん、推測は当たっていたようだ。Sender::send&self なので、1回値を送っただけではdropしない。なので、rxtx達が生きていることが分かっているので明示的にdropしてあげないとforから抜けれなかったわけか。

ということは

use std::thread;
use std::sync::mpsc;

// このtxは使ってないけど明示的にdropさせる必要がある
let (tx, rx) = mpsc::channel();
for costly_task in costly_tasks.into_iter() {
    // ここの tx は for が回るたびにスコープから抜ける => drop する
    let tx = mpsc::Sender::clone(&tx);
    thread::spawn(move || {
        let val = costly_task();
        tx.send(val).unwrap();
    });
}

// 明示的にdropしてあげる
drop(tx);

// 全部のSenderがdropしているのでこのforはちゃんと抜けられる
for val in rx {
    dbg!(val);
}

ってわけですね、少しハマったのでメモです

宣伝

今回の挙動を確認したりドキュメントを読んだりするのにrust-jpのSlackで質問を投げていました。活発なコミュニティで優しい方が多いので皆さん入りましょう!!

rust-jp.herokuapp.com


  1. 本当はinto_iterなんだけどなかったしiterでも同じでしょう