buntan-pc #2
(0)
2025.04.11 Fri #0
- 今のbuntan-pcにはasという専用のアセンブラがあるのだけど、これの互換品をささっと作ってしまいたい。これが当面の目標。
- そのために、どういうソースを渡せばどういうバイナリがでてくるかという、テストセットが欲しい。それがあればはかどる。
- uchanさんに、「・・・ということでテストセットを3組くらいちょうだい!」と頼んだら、「それくらい公開済みのCコンパイラとアセンブラがあれば自分でできるでしょ」といわれて、確かにそれもそうだと思った。ということでやってみる。こちらの環境はWindows+MS-C。
- uas.exeを作っていたらコンパイルエラーが出た。「//」のコメントの末尾が「取得」になっていると、次の行までコメント扱いされて、コンパイルエラーがいっぱい出る。半角ピリオドを追加してVCをなだめる。UTF-8で書かれたテキストなのに、なんでそうなるのか分からないけど、まあ対処法は簡単なので問題はない。
- 上記のコメント問題を直したら、7個の警告が出るだけでビルドは問題なくできた。
- なるほどね、MS-Cには「/utf-8」っていうオプションがあるのかー。これを付けたらコメントいじらなくてもおとなしくなった。
- 次はucc.exe。
- まずmakeを用意するのが面倒だったので以下のucc.cを作って代用。
#include "main.c"
#include "ast.c"
#include "insn.c"
#include "symbol.c"
#include "token.c"
#include "type.c"
- 問題は2つ。
- libgen.hがないので、dirname()がない。
- 以下の記述を嫌がる。
struct GenContext gen_ctx = {
parse_ctx.scope,
0, 0, 0, {}, {-1, -1}, 0, {}, print_ast, 0
};
- さてどうしたものか。
0, 0, 0, {0}, {-1, -1}, 0, {0}, print_ast, 0
- じゃあ残るはdirname()だけだな。どこかに落ちてないかな。
- Cursorさんに「<libgen.h>のdirnameを作ってください。」って頼んでみたら、作ってくれた。
#include <stdio.h>
#include <string.h>
char* my_dirname(char* path) {
static char buffer[256];
char* last_slash;
// パスがNULLまたは空の場合、"."を返す
if (path == NULL || *path == '\0') {
return ".";
}
// パスをコピー
strncpy(buffer, path, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
// 最後のスラッシュを探す
last_slash = strrchr(buffer, '/');
// スラッシュが見つからない場合、"."を返す
if (last_slash == NULL) {
return ".";
}
// スラッシュの後ろを終端文字に置き換える
if (last_slash != buffer) {
*last_slash = '\0';
} else {
// ルートディレクトリの場合
*(last_slash + 1) = '\0';
}
return buffer;
}
- これでucc.exeはビルドできるようになったけど、できたucc.exeは挙動が怪しい。じゃあ次の作業はデバッグだな。
- いやでも、uas.exeは問題なく動いているっぽいし、ucc/testsの中にarray.sとかもあるから、とりあえずuccはデバッグしなくてもいいのかー。
2025.04.11 Fri #1
- ある程度テストしてみたところ、手元でビルドしたuas.exeは完璧に動いているっぽい。
2025.04.14 Mon #0
- とりあえずK版のアセンブラは半分くらいできた。
- 今のところ、289行。
- 本家は section .data の次に section .text を書くというルールで、セクションをこまめに切り替えたりはできないけれど、今作っている版では、セクションの宣言順序は自由だし、途中で何度もセクションを切り替えられる。
2025.04.15 Tue #0
- array.sくらいならアセンブルできるようになった!(かも)。
- まだ出力部を書いてないので、メモリの中でアセンブルできているだけ。バグっているかどうかは分からない。
- 数値計算を本家よりは頑張ったので、 push lb3-lb2+1 くらいならできるはず(バグってなければ)。つまりカッコなしの加減算ができる。
- 今は356行。
2025.04.15 Tue #1
- db命令にも対応して、サンプルの.sファイルは全部アセンブルできるようになった。
- あとは出力部をかかないとな・・・。
2025.04.15 Tue #2
- 出力部もできた。ちょっとバクもあったけど、それも直して、ついに本家のアセンブラと同じバイナリを出せるようになった!
- 今は408行。まあでも行数はそんなに重要じゃない。1行に詰め込めばどうにでもなるのだから。
- 一番苦戦したデバッグは、fopen(exe, "wb")が失敗してNULLを返すというもの。・・・いやいや、なんで失敗するのさ!readじゃないよwriteだよ、普通失敗しないじゃないか!
- BZエディタで開いているファイルをfopenで書き込みオープンすると、fp==NULLにされる。なるほど、アクセス権が取れなかったんだね。
- これに気づくまでに30分くらい悩んだ。まさかここで失敗しているなんて思わなかったので・・・。
- あとは些細な問題として、途中から本家が出力している実行ファイルと一致しないで、1バイトずれるという問題があった。でもそれは数秒でわかった。本家は"w"でオープンしていたから、テキストモードになっていたわけだ。それで0x0aを出力すると勝手に0x0dが追加されてしまう。ということで、本家も"wb"でオープンするようにしたら、完璧に出力結果が一致するようになった。
2025.04.16 Wed #0
- 今回アセンブラを作るために使ったaclminiというライブラリについて、自分用のメモ。
Ai intptr_t のtypedef (頻出なので短く書けるようにした、以下同じ動機)
Ap void * のtypedef
Av void のtypedef
Auc unsigned char のtypedef
Asc signed char のtypedef
AStr char * のtypedef
As static の#define
AClass(Abc) { ... }; → structしてtypedefしてくれるマクロ
aSz(Abc) (intptr_t) sizeof(Abc) の代わり (sizeofはunsignedなので使いにくいから) → (追記)のちに Asz に改名した
AMlc : AMalloc - 汎用メモリアロケータ・インターフェース
AMlcStd : AMlc Standard - malloc/free/reallocを使って作ったAMlc
AMlcStdNumSz : AMlcStd Number/Size - mallocしたブロック数と総mallocバイト数をいつでも確認できるようにしたAMlcStd (メモリリークがないことを確認しやすい)
ATokenMgr : ATokenManager - 文字列に対して出現順に0,1,2,...と番号を付けるためのクラス (内部で二分探索するので検索は速い)
AExpMem : AExpandableMemory - 可変長配列
- aSzはASzにした方がいいかもしれない。そうすればAで始まる名前がこのライブラリ所属だとわかる。aで始まる名前は解放される。
- (追記)ということで aSz は廃止して ASz にした。
2025.04.16 Wed #1
- https://essen.osask.jp/files/kuas00a.zip (4.79KB)
- ソースファイルのみです。書いてないけどライセンスはKL-01です。
- buntan-pcにマージされたものは、MITライセンスになります。
- コンパイルの際は、 kuas.c のみコンパイルすればいいです。aclmini.cは勝手にインクルードされます。
- うわー、ソースコードだけでzip化すると5KB未満かー。小さいなー。
- 今回かなり短期間で書けたわけですが、それで思ったのは、もう整合性の取れた仕様が決まっていて、それに合わせて作るだけでよければ、それほど大変じゃないってことなんだろうと思います。それに本家のuasはシンプルに作れるように仕様が工夫されているのもあると思います。