Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

自作言語でお絵描き

自作言語OpeLaでSDLを使い絵を描く方法を説明します。SDLはC言語で作られており、OpeLaから簡単に使えます。後半は可変長引数の対応方針を紹介します。

  • Be the first to comment

  • Be the first to like this

自作言語でお絵描き

  1. 1. 自作言語でお絵描き 2021年1月3日 第24回自作OSもくもく会 @uchan_nos
  2. 2. 自己紹介 名前:内田公太 Twitter:@uchan_nos  東京工業大学 情報工学系 特任助教(週2)  サイボウズ・ラボ株式会社(週3) 活動  osdev-jpの運営  OS、言語処理系の開発 『30日でできる! OS自作入門』 の校正を担当(2006年) 『自作エミュレータで学ぶ x86アーキテクチャ』著(2015年)
  3. 3. OpeLaプロジェクトとは OpeLa: Operating and Language processing system OSと言語処理系を全部自作するプロジェクト OS アセンブラ コンパイラ リンカ ライブラリ 特徴:完全なセルフホスト
  4. 4. OpeLaで書き初め
  5. 5. OpeLaで書き初めの仕組み OpeLaでSDLを使う SDLでウィンドウ、背景、線を表示 SDL: Simple DirectMedia Layer マルチメディアを扱うライブラリ シンプルなライブラリ故に対応機種 が幅広い C言語用インタフェースなのでいろ んな言語から簡単に使える! ロゴが明滅する様子
  6. 6. SDLの関数を呼び出す SDLの関数をextern宣言し、呼び出す ヘッダファイルは読み込めないのでマクロは使えない SDL_Window*の代わりにint* func main() int { if SDL_Init(0x20) < 0 { // SDL_INIT_VIDEO printf("Failed to initialize SDL: %sn", SDL_GetError()); return 1; } printf("Creating a windown"); window := SDL_CreateWindow("SDL by OpeLa", 0x1fff0000, 0x1fff0000, 300, 200, 0); extern "C" SDL_Init func(flag uint) int; extern "C" SDL_GetError func() *byte; extern "C" SDL_CreateWindow func(title *byte, x, y, w, h int, flags uint) *int;
  7. 7. イベントポーリング SDL_Eventの代わりに[16]uint32 var event [16]uint32; for { for SDL_PollEvent(&event[0]) != 0 { if event[0] == uint32(256) { // SDL_QUIT SDL_DestroyWindow(window); SDL_Quit(); return 0; } }
  8. 8. グラデーション背景 Colorを1ずつ変化させ、黒→青緑に徐々に変化させる SDL_SetRenderDrawColorで描画色を設定し SDL_RenderClearで背景を塗りつぶす color += dir; if color == 255 { dir = -1; } else if color == 0 { dir = 1; } SDL_SetRenderDrawColor(renderer, 0, color, color, 255); SDL_RenderClear(renderer);
  9. 9. ロゴ 長方形と直線の描画を駆使してロゴを描く SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // O DrawRect(renderer, 30, 60, logo_x + 40*0, logo_y); // p DrawRect(renderer, 30, 30, logo_x + 40*1, logo_y + 30); SDL_RenderDrawLine(renderer, logo_x + 40*1, logo_y + 60, logo_x + 40*1, logo_y + 90); func DrawRect(ren *int, w, h, x, y int) { var r [4]int32; r[0] = x; r[1] = y; r[2] = w; r[3] = h; SDL_RenderDrawRect(ren, &r[0]); }
  10. 10. SDLの関数を呼び出すときの注意 SDLに限らないが、関数を呼び出す際はスタックのアライメント に注意が必要  参考「x86-64 モードのプログラミングではスタックのアライメントに気を付けよう」  https://uchan.hateblo.jp/entry/2018/02/16/232029 関数を呼び出す直前でRSPが16の倍数でなければならない void Call(std::ostream& os, Register addr) override { os << " push rbxn"; os << " mov rbx, rspn"; os << " and rsp, -16n"; os << " call " << RegName(addr) << "n"; os << " mov rsp, rbxn"; os << " pop rbxn"; } RBXは関数呼び出し前後で保存されている必要があるから、スタックに保存してから使う and rsp, -16 = and rsp, 0xf…f0
  11. 11. SDLを使うサンプルのビルド sdl.oplをコンパイルしてsdl.sを得て libSDL2.soとリンクする cat sdl.opl | ../../opelac > sdl.s cc sdl.s -lSDL2
  12. 12. 可変長引数の対応
  13. 13. OpeLaで可変長引数 可変長引数:int printf(const char* format, ...);の... C言語で可変個の引数を渡す仕組み 呼び出し側 x86-64(SystemV AMD64 ABI) 普通の引数と同様に、レジスタ渡し RDI, RSI, RDX, RCX, R8, R9 AArch64(EABI) 可変長引数だけスタック渡し format 1 2 3 format 1 2 3 RDI RSI RDX RCX X0 SP
  14. 14. OpeLaの仕組みと可変長引数 OpeLaはスタックマシン 式はスタックに値を積む 「1 + 2」は右図 printf("%d:%d", 1, 2) x86-64:いったんスタック に引数を積み、最後にレジス タへ転写すれば良い 普通の関数呼び出しと同じ! 1 SP 2 1 SP 3 SP 文字列へのアドレス 1 2 SP for (int i = 0; i < num_args; ++i) { asmgen->Pop64(os, kArgRegs[i]); }
  15. 15. AArch64で可変長引数 printf("%d:%d", 1, 2) AArch64では、途中までレジ スタへ転写すればいいので は? →ダメだった AArch64ではスタックに式の 値を8バイト飛ばしで積んで いるから 文字列へのアドレス 1 2 SP レジスタへ スタックに残す 文字列へのアドレス 空き 1 SP 空き 2 空き AArch64だと 実はこうなってる AppleのABIではこうなっているが、Armの世界で一般 的なEABIでは可変長引数もレジスタ渡しらしい。 https://developer.apple.com/documentation/xcode/ writing_arm64_code_for_apple_platforms
  16. 16. なぜAArch64だと8バイト飛ばしなの? 16の倍数でないSPがベースアドレスとして使われると例外発生 str x0, [sp, #-16]! Spから16を引き、そのアドレスにx0の値を書く だから、opelacは8バイト飛ばしでスタックに値を積む →そのままでは可変長引数として使えない!
  17. 17. 私の今日の目標 AArch64で可変長引数をサポートする 引数省略記号「...」にパーサを対応させ、 可変長引数の部分はスタックに残し、 スタックの8バイトの隙間を詰め、 最後に関数を呼び出す とうまく行くかなあ…? 可変長引数1 空き 可変長引数2 SP 空き 可変長引数3 空き コピー コピー 可変長引数4 コピー
  18. 18. OpeLaに興味ある人を募集してます 開発の様子は Twitterの@uchan_nos osdev-jp Slackの#opelaチャンネル に書いてます 今は言語設計とコンパイラ実装を並走中 「配列リテラルを実装するかどうか」 「sizeof(uint2)は何を返すべきか」 などなど… 設計すべき部分がたくさんある 一緒にお話ししながらアイデアを練っていきたいです Wanted ・言語設計の話し相手 ・OpeLaロゴ制作 ・アプリ製作 ・実装のお手伝い

    Be the first to comment

自作言語OpeLaでSDLを使い絵を描く方法を説明します。SDLはC言語で作られており、OpeLaから簡単に使えます。後半は可変長引数の対応方針を紹介します。

Views

Total views

541

On Slideshare

0

From embeds

0

Number of embeds

6

Actions

Downloads

1

Shares

0

Comments

0

Likes

0

×