{"id":15060154,"url":"https://github.com/mati365/ts-c-compiler","last_synced_at":"2025-05-16T04:06:14.452Z","repository":{"id":38070403,"uuid":"66721310","full_name":"Mati365/ts-c-compiler","owner":"Mati365","description":"⚙️ C99-compatible multipass compiler written in TypeScript with GCC extensions support. Features a handcrafted left-recursive parser, custom IR, SSA-based optimizer, and a full frontend/backend pipeline. Compiles to x86 machine code with integrated assembler and emulator.","archived":false,"fork":false,"pushed_at":"2024-10-14T20:19:36.000Z","size":20080,"stargazers_count":379,"open_issues_count":6,"forks_count":21,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-16T04:06:08.895Z","etag":null,"topics":["8086","8086-emulator","assembler","assembler-x86","assembly","c-compiler","compiler","emulator","es6","i8086","intel-8086","nasm","preprocessor","repl","simulator","toy-compiler","typescript","x86","x86-16"],"latest_commit_sha":null,"homepage":"https://mati365.github.io/ts-c-compiler/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mati365.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-27T15:29:21.000Z","updated_at":"2025-05-14T04:57:04.000Z","dependencies_parsed_at":"2024-10-12T20:41:15.567Z","dependency_job_id":"59baceab-9377-41e6-9cfb-199456b29b34","html_url":"https://github.com/Mati365/ts-c-compiler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mati365%2Fts-c-compiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mati365%2Fts-c-compiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mati365%2Fts-c-compiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mati365%2Fts-c-compiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mati365","download_url":"https://codeload.github.com/Mati365/ts-c-compiler/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464895,"owners_count":22075570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["8086","8086-emulator","assembler","assembler-x86","assembly","c-compiler","compiler","emulator","es6","i8086","intel-8086","nasm","preprocessor","repl","simulator","toy-compiler","typescript","x86","x86-16"],"created_at":"2024-09-24T22:53:47.895Z","updated_at":"2025-05-16T04:06:09.442Z","avatar_url":"https://github.com/Mati365.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align='center'\u003e\n  \u003cimg src='doc/logo.png' alt='Banner' width='168px'\u003e\n\u003c/p\u003e\n\n# ts-c-compiler\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)\n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/mati365/i8086.js?style=flat-square)\n[![GitHub issues](https://img.shields.io/github/issues/mati365/i8086.js?style=flat-square)](https://github.com/Mati365/ts-c-compiler/issues)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)\n[![CI](https://github.com/Mati365/ts-c-compiler/actions/workflows/test.yml/badge.svg)](https://github.com/Mati365/ts-c-compiler/actions/workflows/test.yml)\n\nMultipass portable C lang compiler toolkit with IR code generator including backend, frontend, and optimizer phases. Designed to simple prototyping 16bit toy operating systems and games.\n\nCurrently supported architectures:\n\n1. X86 16bit real mode code emitter with floating point X87 coprocessor support\n\n**🚧 Warn! The project is unstable so please do not use it on production!**\n\n## What does it offer? ⭐\n\n1. Reasonable assembly code quality in NASM syntax\n2. Simple prototyping boot sector games\n3. Designed especially for old-school 16bit computers with Intel 80286 (and newer) CPU and produces only simple ASM instructions\n4. Backend / Frontend architecture that allows you to add new backends in TypeScript (especially useful for homebrew FPGA CPU)\n5. Peephole optimization of IR code, precompute of constant expressions during compile time and optimizer phase\n6. Slow compile times - feel the vibe of old computing\n\n### What works? 🔥\n\n- [x] Multi-pass branch optimisation (it uses `jmp rel8` instructions when offset is smaller than `rel16`)\n- [x] Local / Global variables\n- [x] `float` / `double` operations using X87 stack-based registers\n- [x] Advanced types `struct`, `union`, `enum`\n- [x] Loops and if conditions `while`, `if`, `do while`, `for`, `break`, `continue`\n- [x] Basic preprocessor with `#ifdef`, `#define`, `#include`\n- [x] `goto` jumps\n- [x] VA lists `va_arg`, `va_end`, `va_start`\n- [x] In expression compound statements\n- [x] Ternary operators `a \u003e 1 ? 1 : 2`\n- [x] Arithmetic operations `a + b`, `a * b`, `a / b`, etc.\n- [x] Binary operations `a | b`, `a \u0026 b` etc.\n- [x] Logic operations that are casted to numbers `a \u0026\u0026 2 || 2 \u003e 1`\n- [x] Assign operators `a += 1`, `a \u003c\u003c= b`, etc.\n- [x] Designated and C89 initializers\n- [x] Dynamic stack alloc using `alloca`\n- [x] Type aliasing `typedef`\n- [x] Variable and function pointers\n- [x] `RVO` optimization of larger structs\n- [x] Peephole optimization of expensive instruction like `a *= 2` -\u003e `a \u003c\u003c= 1`\n- [x] Constant expressions eval optimizations `a = 2 * 4` -\u003e `a = 8`\n- [x] Constant branch optimization for loops and ifs `for (;;) {}` -\u003e `L1: jmp L1`\n\n### What does not work? 🚧\n\n- [ ] Bitfields\n- [ ] Multiple files support\n- [ ] Linker\n\n## Online editor\n\nAvailable at: \u003chttps://mati365.github.io/ts-c-compiler/\u003e\n\n![REPL](/doc/repl.png)\n\n## Install\n\n```bash\nyarn add @ts-cc/cli @ts-cc/machine\n```\n\n```bash\nUsage: ts-c [options] \u003csource\u003e\n\nArguments:\n  source                       Relative or absolute path to source file\n\nOptions:\n  -b, --binary                 Emits binary stdout\n  -o, --output \u003cstring\u003e        Relative path to your output binary\n  -d, --debug                  Print AST tree and assembly output\n  -ps, --print-assembly        Print assembly output\n  -pjs, --print-jump-assembly  Print assembly output with jmps\n  -bs, --bootsector            Generate 512B bootsector output. Remember to\n                               have main entrypoint.\n  -h, --help                   display help for command\n```\n\n## Usage\n\nExample `main.c` file:\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003ckernel/textmode.h\u003e\n\nint main() {\n  int rows = 8, coef = 1, space, i, j;\n\n  kernel_screen_clear();\n\n  for (i = 0; i \u003c rows; i++) {\n    for (space = 1; space \u003c= rows - i; space++) {\n      printf(\"  \");\n    }\n\n    for (j = 0; j \u003c= i; j++) {\n      if (j == 0 || i == 0) {\n        coef = 1;\n      } else {\n        coef = coef * (i - j + 1) / j;\n      }\n\n      printf(\"%4d\", coef);\n    }\n\n    printf(\"\\n\");\n  }\n\n  for (;;) {}\n  return 0;\n}\n```\n\nCompile `main.c` and boot-it in 16bit VM available in web-browser:\n\n```bash\nnpx ts-c main.c --bootsector --binary | APP_PORT=3002 npx run-x86_16-vm\n```\n\nCompile `main.c` to x86-16 binary:\n\n```bash\nnpx ts-c ./main.c -o ./output.bin\n```\n\nPrint assembly output without generate binary file:\n\n```bash\nnpx ts-c ./main.c -ps\n\n0x000000                      55                            push bp\n0x000001                      89 e5                         mov bp, sp\n0x000003                      83 ec 02                      sub sp, 0x2\n0x000006                      c7 46 fe 04 00                mov word [bp-2], 0x4\n0x00000b                      89 ec                         mov sp, bp\n0x00000d                      5d                            pop bp\n0x00000e                      c3                            ret\n```\n\n## Examples\n\n### Simple macros with constant expressions optimization\n\n```c\n#include \"file.h\"\n\n#define PRINT_SUM 1\n#define A 1\n#define B 1\n\n#define esum(...) sum(__VA_ARGS__)\n#define internal_fn(name) internal_ ## name\n\n#define min(a,b) ((a)\u003c(b)?(a):(b))\n#define max(a,b) ((a)\u003e(b)?(a):(b))\n#define sum(a,b) (min(a, b) + max(a, b))\n\nenum {\n  TEN = 10,\n  FIVE = 5\n};\n\n#ifdef PRINT_SUM\n  #if A + B == 12 || A - B == 0\n    int main() {\n      int k = esum(TEN, FIVE + 1);\n    }\n  #endif\n#elifdef ABC\n  int s = 2;\n#elifndef DBEF\n  struct Vec2 { int x, y; };\n\n  struct Vec2 sum_vec(int k, struct Vec2 vec, int x) {\n    struct Vec2 result = {\n      .x = k + vec.x * vec.y - x,\n      .y = vec.y * 3\n    };\n\n    return result;\n  }\n\n  int main() {\n    struct Vec2 vec = { .x = 4, .y = 3 };\n    struct Vec2 k = sum_vec(2, vec, 5);\n\n    int d = k.x + k.y;\n    asm(\"xchg dx, dx\");\n  }\n#else\n  int internal_fn(main)() {\n    int k = 2;\n  }\n#endif\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block main ---\ndef main(): [ret: int2B]\n  k{0}: int*2B = alloca int2B\n  *(k{0}: int*2B) = store %16: int2B\n  ret\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000                      55                            push bp\n0x000001                      89 e5                         mov bp, sp\n0x000003                      83 ec 02                      sub sp, 0x2\n0x000006                      c7 46 fe 10 00                mov word [bp-2], 0x10\n0x00000b                      89 ec                         mov sp, bp\n0x00000d                      5d                            pop bp\n0x00000e                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Floating point operations\n\n```c\nfloat calculate_pi(int nbofterms) {\n  float x = 0.0;\n\n  for (int n = 0; n \u003c nbofterms; n++) {\n    float z = 1.0 / (2 * n + 1);\n\n    if (n % 2 == 1) {\n      z *= -1;\n    }\n\n    x = (x + z);\n  }\n\n  return 4 * x;\n}\n\nint main() {\n  float pi = calculate_pi(500);\n  int trunc_pi = pi;\n  asm(\"xchg bx, bx\");\n  return 0;\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block calculate_pi ---\ndef calculate_pi(nbofterms{0}: int*2B): [ret: float4B]\n  x{0}: float*2B = alloca float4B\n  *(x{0}: float*2B) = store %0: float4B\n  n{0}: int*2B = alloca int2B\n  *(n{0}: int*2B) = store %0: int2B\n  L1:\n  %t{0}: int2B = load n{0}: int*2B\n  %t{1}: int2B = load nbofterms{0}: int*2B\n  %t{2}: i1:zf = icmp %t{0}: int2B less_than %t{1}: int2B\n  br %t{2}: i1:zf, true: L2, false: L3\n  L2:\n  z{0}: float*2B = alloca float4B\n  %t{5}: int2B = load n{0}: int*2B\n  %t{6}: int2B = %t{5}: int2B mul %2: char1B\n  %t{7}: int2B = %t{6}: int2B plus %1: char1B\n  %t{8}: float4B = cast %t{7}: int2B\n  %t{9}: float4B = %1: float4B div %t{8}: float4B\n  *(z{0}: float*2B) = store %t{9}: float4B\n  %t{11}: int2B = %t{5}: int2B mod %2: char1B\n  %t{12}: i1:zf = icmp %t{11}: int2B equal %1: char1B\n  br %t{12}: i1:zf, false: L4\n  L5:\n  %t{14}: float4B = load z{0}: float*2B\n  %t{15}: float4B = %t{14}: float4B mul %-1: char1B\n  *(z{0}: float*2B) = store %t{15}: float4B\n  L4:\n  %t{16}: float4B = load x{0}: float*2B\n  %t{17}: float4B = load z{0}: float*2B\n  %t{18}: float4B = %t{16}: float4B plus %t{17}: float4B\n  *(x{0}: float*2B) = store %t{18}: float4B\n  %t{3}: int2B = load n{0}: int*2B\n  %t{4}: int2B = %t{3}: int2B plus %1: int2B\n  *(n{0}: int*2B) = store %t{4}: int2B\n  jmp L1\n  L3:\n  %t{19}: float4B = load x{0}: float*2B\n  %t{20}: float4B = %t{19}: float4B mul %4: char1B\n  ret %t{20}: float4B\n  end-def\n\n\n# --- Block main ---\ndef main(): [ret: int2B]\n  pi{0}: float*2B = alloca float4B\n  %t{22}: float4B = call label-offset calculate_pi :: (%500: int2B)\n  *(pi{0}: float*2B) = store %t{22}: float4B\n  trunc_pi{0}: int*2B = alloca int2B\n  %t{23}: float4B = load pi{0}: float*2B\n  %t{24}: int2B = cast %t{23}: float4B\n  *(trunc_pi{0}: int*2B) = store %t{24}: int2B\n  asm \"xchg bx, bx\"\n  ret %0: char1B\n  end-def\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000  \u003c──────╮            55                            push bp\n0x000001         │            89 e5                         mov bp, sp\n0x000003         │            83 ec 0c                      sub sp, 0xc\n0x000006         │            d9 06 9b 00                   fld dword [@@_$lc_0]\n0x00000a         │            d9 5e fc                      fstp dword [bp-4]\n0x00000d         │            c7 46 fa 00 00                mov word [bp-6], 0x0\n0x000012  \u003c────╮ │            8b 46 04                      mov ax, word [bp+4]\n0x000015       │ │            39 46 fa                      cmp word [bp-6], ax\n0x000018  ─╮   │ │            7c 02                         jl 0x1c\n0x00001a  ─┼─╮ │ │            7d 4b                         jge 0x67\n0x00001c  \u003c╯ │ │ │            8b 46 fa                      mov ax, word [bp-6]\n0x00001f     │ │ │            89 c3                         mov bx, ax\n0x000021     │ │ │            d1 e0                         shl ax, 0x1\n0x000023     │ │ │            05 01 00                      add ax, 0x1\n0x000026     │ │ │            89 46 f4                      mov word [bp-12], ax\n0x000029     │ │ │            df 46 f4                      fild word [bp-12]\n0x00002c     │ │ │            d9 e8                         fld1\n0x00002e     │ │ │            d8 f1                         fdiv st0, st1\n0x000030     │ │ │            dd c1                         ffree st1\n0x000032     │ │ │            d9 5e f6                      fstp dword [bp-10]\n0x000035     │ │ │            89 d8                         mov ax, bx\n0x000037     │ │ │            bb 02 00                      mov bx, 0x2\n0x00003a     │ │ │            66 99                         cdq\n0x00003c     │ │ │            f7 fb                         idiv bx\n0x00003e     │ │ │            83 fa 01                      cmp dx, 0x1\n0x000041  ─╮ │ │ │            75 0a                         jnz 0x4d\n0x000043   │ │ │ │            d9 46 f6                      fld dword [bp-10]\n0x000046   │ │ │ │            d8 0e 9f 00                   fmul dword [@@_$lc_1]\n0x00004a   │ │ │ │            d9 5e f6                      fstp dword [bp-10]\n0x00004d  \u003c╯ │ │ │            d9 46 fc                      fld dword [bp-4]\n0x000050     │ │ │            d9 46 f6                      fld dword [bp-10]\n0x000053     │ │ │            d9 c9                         fxch st1\n0x000055     │ │ │            d8 c1                         fadd st0, st1\n0x000057     │ │ │            dd c1                         ffree st1\n0x000059     │ │ │            d9 5e fc                      fstp dword [bp-4]\n0x00005c     │ │ │            8b 46 fa                      mov ax, word [bp-6]\n0x00005f     │ │ │            05 01 00                      add ax, 0x1\n0x000062     │ │ │            89 46 fa                      mov word [bp-6], ax\n0x000065  ───┼─╯ │            eb ab                         jmp 0x12\n0x000067  \u003c──╯   │            d9 46 fc                      fld dword [bp-4]\n0x00006a         │            d8 0e a3 00                   fmul dword [@@_$lc_2]\n0x00006e         │            89 ec                         mov sp, bp\n0x000070         │            5d                            pop bp\n0x000071         │            c2 02 00                      ret 0x2\n0x000074         │            55                            push bp\n0x000075         │            89 e5                         mov bp, sp\n0x000077         │            83 ec 0c                      sub sp, 0xc\n0x00007a         │            68 f4 01                      push 0x1f4\n0x00007d  ───────╯            e8 80 ff                      call 0x0\n0x000080                      d9 56 f8                      fst dword [bp-8]\n0x000083                      d9 5e fc                      fstp dword [bp-4]\n0x000086                      d9 46 fc                      fld dword [bp-4]\n0x000089                      df 5e f4                      fistp word [bp-12]\n0x00008c                      8b 46 f4                      mov ax, word [bp-12]\n0x00008f                      89 46 f6                      mov word [bp-10], ax\n0x000092                      87 db                         xchg bx, bx\n0x000094                      b8 00 00                      mov ax, 0x0\n0x000097                      89 ec                         mov sp, bp\n0x000099                      5d                            pop bp\n0x00009a                      c3                            ret\n0x00009b                      00 00 00 00                   dd 0.0\n0x00009f                      00 00 80 bf                   dd -1.0\n0x0000a3                      00 00 80 40                   dd 4.0\n```\n\n### Simple VA lists with primitive types\n\n```c\n#include \u003cstdarg.h\u003e\n\nint sum_vector(int total_args, ...) {\n  va_list ap;\n  va_start(ap, total_args);\n\n  int sum = 0;\n\n  for (int i = 0; i \u003c total_args; ++i) {\n    sum += va_arg(ap, int);\n  }\n\n  va_end(ap);\n  return sum;\n}\n\nvoid main() {\n  int result = sum_vector(3, 5, 8, 10);\n  asm(\"xchg dx, dx\");\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block sum_vector ---\ndef sum_vector(total_args{0}: int*2B, ...): [ret: int2B]\n  ap{0}: struct __builtin_va_list*2B = alloca struct __builtin_va_list2B\n  %t{1}: struct __builtin_va_list**2B = lea ap{0}: struct __builtin_va_list*2B\n  %t{2}: int**2B = lea total_args{0}: int*2B\n  call label-offset __builtin_va_start :: (%t{1}: struct __builtin_va_list**2B, %t{2}: int**2B)\n  sum{0}: int*2B = alloca int2B\n  *(sum{0}: int*2B) = store %0: int2B\n  i{0}: int*2B = alloca int2B\n  *(i{0}: int*2B) = store %0: int2B\n  L1:\n  %t{3}: int2B = load i{0}: int*2B\n  %t{4}: int2B = load total_args{0}: int*2B\n  %t{5}: i1:zf = icmp %t{3}: int2B less_than %t{4}: int2B\n  br %t{5}: i1:zf, true: L2, false: L3\n  L2:\n  %t{9}: struct __builtin_va_list**2B = lea ap{0}: struct __builtin_va_list*2B\n  %t{10}: char[2]*2B = alloca char[2]2B\n  %t{11}: char[2]*2B = lea %t{10}: char[2]*2B\n  call label-offset __builtin_va_arg :: (%t{9}: struct __builtin_va_list**2B, %2: int2B, %t{11}: char[2]*2B)\n  %t{12}: int2B = load sum{0}: int*2B\n  %t{13}: int2B = %t{12}: int2B plus %t{10}: char[2]*2B\n  *(sum{0}: int*2B) = store %t{13}: int2B\n  %t{6}: int2B = load i{0}: int*2B\n  %t{7}: int2B = %t{6}: int2B plus %1: int2B\n  *(i{0}: int*2B) = store %t{7}: int2B\n  jmp L1\n  L3:\n  %t{15}: int2B = load sum{0}: int*2B\n  ret %t{15}: int2B\n  end-def\n\n\n# --- Block main ---\ndef main():\n  result{0}: int*2B = alloca int2B\n  %t{17}: int2B = call label-offset sum_vector :: (%3: char1B, %5: char1B, %8: char1B, %10: char1B)\n  *(result{0}: int*2B) = store %t{17}: int2B\n  asm \"xchg dx, dx\"\n  ret\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000  \u003c──────╮            55                            push bp\n0x000001         │            89 e5                         mov bp, sp\n0x000003         │            83 ec 08                      sub sp, 0x8\n0x000006         │            8d 5e fe                      lea bx, word [bp-2]\n0x000009         │            8d 7e 04                      lea di, word [bp+4]\n0x00000c         │            89 3f                         mov word [bx], di\n0x00000e         │            c7 46 fc 00 00                mov word [bp-4], 0x0\n0x000013         │            c7 46 fa 00 00                mov word [bp-6], 0x0\n0x000018  \u003c────╮ │            8b 46 04                      mov ax, word [bp+4]\n0x00001b       │ │            39 46 fa                      cmp word [bp-6], ax\n0x00001e  ─╮   │ │            7c 02                         jl 0x22\n0x000020  ─┼─╮ │ │            7d 25                         jge 0x47\n0x000022  \u003c╯ │ │ │            8d 5e fe                      lea bx, word [bp-2]\n0x000025     │ │ │            8d 7e f8                      lea di, word [bp-8]\n0x000028     │ │ │            8b 37                         mov si, word [bx]\n0x00002a     │ │ │            83 c6 02                      add si, 0x2\n0x00002d     │ │ │            8b 04                         mov ax, word [si]\n0x00002f     │ │ │            89 05                         mov word [di], ax\n0x000031     │ │ │            89 37                         mov word [bx], si\n0x000033     │ │ │            8b 46 fc                      mov ax, word [bp-4]\n0x000036     │ │ │            03 46 f8                      add ax, word [bp-8]\n0x000039     │ │ │            89 46 fc                      mov word [bp-4], ax\n0x00003c     │ │ │            8b 5e fa                      mov bx, word [bp-6]\n0x00003f     │ │ │            83 c3 01                      add bx, 0x1\n0x000042     │ │ │            89 5e fa                      mov word [bp-6], bx\n0x000045  ───┼─╯ │            eb d1                         jmp 0x18\n0x000047  \u003c──╯   │            8b 46 fc                      mov ax, word [bp-4]\n0x00004a         │            89 ec                         mov sp, bp\n0x00004c         │            5d                            pop bp\n0x00004d         │            c2 02 00                      ret 0x2\n0x000050         │            55                            push bp\n0x000051         │            89 e5                         mov bp, sp\n0x000053         │            83 ec 02                      sub sp, 0x2\n0x000056         │            6a 0a                         push 0xa\n0x000058         │            6a 08                         push 0x8\n0x00005a         │            6a 05                         push 0x5\n0x00005c         │            6a 03                         push 0x3\n0x00005e  ───────╯            e8 9f ff                      call 0x0\n0x000061                      83 c4 06                      add sp, 0x6\n0x000064                      89 46 fe                      mov word [bp-2], ax\n0x000067                      87 d2                         xchg dx, dx\n0x000069                      89 ec                         mov sp, bp\n0x00006b                      5d                            pop bp\n0x00006c                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Advanced structures with recursive calls\n\n```c\nint fibbonacci(int n)\n{\n  if (n == 1)\n    return 0;\n\n  if (n \u003c= 3)\n    return 1;\n\n  return fibbonacci(n-1) + fibbonacci(n-2);\n}\n\nstruct Vec2 { int x, y; };\n\nstruct Vec2 sum_vec(int k, struct Vec2 vec, int x) {\n  struct Vec2 result = {\n    .x = k + vec.x * vec.y - x,\n    .y = vec.y * 3 + (fibbonacci(10) * 2 + fibbonacci(10) * 15)\n  };\n\n  return result;\n}\n\nint main() {\n  struct Vec2 vec = { .x = 4, .y = 3 };\n  struct Vec2 k = sum_vec(2, vec, 5);\n\n  int d = k.x + k.y;\n  asm(\"xchg dx, dx\");\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block fibbonacci ---\ndef fibbonacci(n{0}: int*2B): [ret: int2B]\n  %t{0}: int2B = load n{0}: int*2B\n  %t{1}: i1:zf = icmp %t{0}: int2B equal %1: char1B\n  br %t{1}: i1:zf, false: L1\n  L2:\n  ret %0: char1B\n  L1:\n  %t{2}: int2B = load n{0}: int*2B\n  %t{3}: i1:zf = icmp %t{2}: int2B less_eq_than %3: char1B\n  br %t{3}: i1:zf, false: L3\n  L4:\n  ret %1: char1B\n  L3:\n  %t{5}: int2B = load n{0}: int*2B\n  %t{6}: int2B = %t{5}: int2B minus %1: char1B\n  %t{7}: int2B = call label-offset fibbonacci :: (%t{6}: int2B)\n  %t{10}: int2B = %t{5}: int2B minus %2: char1B\n  %t{11}: int2B = call label-offset fibbonacci :: (%t{10}: int2B)\n  %t{12}: int2B = %t{7}: int2B plus %t{11}: int2B\n  ret %t{12}: int2B\n  end-def\n\n\n# --- Block sum_vec ---\ndef sum_vec(k{0}: int*2B, vec{0}: struct Vec2*2B, x{0}: int*2B, rvo: %out{0}: struct Vec2*2B):\n  result{0}: struct Vec2*2B = alloca struct Vec24B\n  %t{13}: int2B = load k{0}: int*2B\n  %t{14}: struct Vec2**2B = lea vec{0}: struct Vec2*2B\n  %t{15}: int2B = load %t{14}: struct Vec2**2B\n  %t{17}: struct Vec2**2B = %t{14}: struct Vec2**2B plus %2: int2B\n  %t{18}: int2B = load %t{17}: struct Vec2**2B\n  %t{19}: int2B = %t{15}: int2B mul %t{18}: int2B\n  %t{20}: int2B = %t{13}: int2B plus %t{19}: int2B\n  %t{21}: int2B = load x{0}: int*2B\n  %t{22}: int2B = %t{20}: int2B minus %t{21}: int2B\n  *(result{0}: struct Vec2*2B) = store %t{22}: int2B\n  %t{24}: struct Vec2**2B = %t{14}: struct Vec2**2B plus %2: int2B\n  %t{25}: int2B = load %t{24}: struct Vec2**2B\n  %t{26}: int2B = %t{25}: int2B mul %3: char1B\n  %t{28}: int2B = call label-offset fibbonacci :: (%10: char1B)\n  %t{29}: int2B = %t{28}: int2B mul %2: char1B\n  %t{31}: int2B = call label-offset fibbonacci :: (%10: char1B)\n  %t{32}: int2B = %t{31}: int2B mul %15: char1B\n  %t{33}: int2B = %t{29}: int2B plus %t{32}: int2B\n  %t{34}: int2B = %t{26}: int2B plus %t{33}: int2B\n  *(result{0}: struct Vec2*2B + %2) = store %t{34}: int2B\n  ret result{0}: struct Vec2*2B\n  end-def\n\n\n# --- Block main ---\ndef main(): [ret: int2B]\n  vec{1}: struct Vec2*2B = alloca struct Vec24B\n  *(vec{1}: struct Vec2*2B) = store %4: int2B\n  *(vec{1}: struct Vec2*2B + %2) = store %3: int2B\n  k{1}: struct Vec2*2B = alloca struct Vec24B\n  %t{36}: struct Vec2**2B = lea k{1}: struct Vec2*2B\n  call label-offset sum_vec :: (%2: char1B, vec{1}: struct Vec2*2B, %5: char1B, %t{36}: struct Vec2**2B)\n  d{0}: int*2B = alloca int2B\n  %t{37}: struct Vec2**2B = lea k{1}: struct Vec2*2B\n  %t{38}: int2B = load %t{37}: struct Vec2**2B\n  %t{40}: struct Vec2**2B = %t{37}: struct Vec2**2B plus %2: int2B\n  %t{41}: int2B = load %t{40}: struct Vec2**2B\n  %t{42}: int2B = %t{38}: int2B plus %t{41}: int2B\n  *(d{0}: int*2B) = store %t{42}: int2B\n  asm \"xchg dx, dx\"\n  ret\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000  \u003c──╮\u003c╮\u003c╮\u003c╮          55                            push bp\n0x000001     │ │ │ │          89 e5                         mov bp, sp\n0x000003     │ │ │ │          83 7e 04 01                   cmp word [bp+4], 0x1\n0x000007  ─╮ │ │ │ │          75 09                         jnz 0x12\n0x000009   │ │ │ │ │          b8 00 00                      mov ax, 0x0\n0x00000c   │ │ │ │ │          89 ec                         mov sp, bp\n0x00000e   │ │ │ │ │          5d                            pop bp\n0x00000f   │ │ │ │ │          c2 02 00                      ret 0x2\n0x000012  \u003c╯ │ │ │ │          83 7e 04 03                   cmp word [bp+4], 0x3\n0x000016  ─╮ │ │ │ │          7f 09                         jg 0x21\n0x000018   │ │ │ │ │          b8 01 00                      mov ax, 0x1\n0x00001b   │ │ │ │ │          89 ec                         mov sp, bp\n0x00001d   │ │ │ │ │          5d                            pop bp\n0x00001e   │ │ │ │ │          c2 02 00                      ret 0x2\n0x000021  \u003c╯ │ │ │ │          8b 46 04                      mov ax, word [bp+4]\n0x000024     │ │ │ │          89 c3                         mov bx, ax\n0x000026     │ │ │ │          2d 01 00                      sub ax, 0x1\n0x000029     │ │ │ │          53                            push bx\n0x00002a     │ │ │ │          50                            push ax\n0x00002b  ───╯ │ │ │          e8 d2 ff                      call 0x0\n0x00002e       │ │ │          5b                            pop bx\n0x00002f       │ │ │          83 eb 02                      sub bx, 0x2\n0x000032       │ │ │          91                            xchg ax, cx\n0x000033       │ │ │          51                            push cx\n0x000034       │ │ │          53                            push bx\n0x000035  ─────╯ │ │          e8 c8 ff                      call 0x0\n0x000038         │ │          59                            pop cx\n0x000039         │ │          01 c1                         add cx, ax\n0x00003b         │ │          89 c8                         mov ax, cx\n0x00003d         │ │          89 ec                         mov sp, bp\n0x00003f         │ │          5d                            pop bp\n0x000040         │ │          c2 02 00                      ret 0x2\n0x000043  \u003c╮     │ │          55                            push bp\n0x000044   │     │ │          89 e5                         mov bp, sp\n0x000046   │     │ │          83 ec 04                      sub sp, 0x4\n0x000049   │     │ │          8d 5e 06                      lea bx, word [bp+6]\n0x00004c   │     │ │          8b 07                         mov ax, word [bx]\n0x00004e   │     │ │          89 d9                         mov cx, bx\n0x000050   │     │ │          83 c3 02                      add bx, 0x2\n0x000053   │     │ │          8b 17                         mov dx, word [bx]\n0x000055   │     │ │          0f af c2                      imul ax, dx\n0x000058   │     │ │          8b 7e 04                      mov di, word [bp+4]\n0x00005b   │     │ │          01 c7                         add di, ax\n0x00005d   │     │ │          2b 7e 0a                      sub di, word [bp+10]\n0x000060   │     │ │          89 7e fc                      mov word [bp-4], di\n0x000063   │     │ │          83 c1 02                      add cx, 0x2\n0x000066   │     │ │          89 cb                         mov bx, cx\n0x000068   │     │ │          8b 07                         mov ax, word [bx]\n0x00006a   │     │ │          6b c0 03                      imul ax, ax, 0x3\n0x00006d   │     │ │          93                            xchg ax, bx\n0x00006e   │     │ │          53                            push bx\n0x00006f   │     │ │          6a 0a                         push 0xa\n0x000071  ─┼─────╯ │          e8 8c ff                      call 0x0\n0x000074   │       │          5b                            pop bx\n0x000075   │       │          d1 e0                         shl ax, 0x1\n0x000077   │       │          91                            xchg ax, cx\n0x000078   │       │          53                            push bx\n0x000079   │       │          51                            push cx\n0x00007a   │       │          6a 0a                         push 0xa\n0x00007c  ─┼───────╯          e8 81 ff                      call 0x0\n0x00007f   │                  59                            pop cx\n0x000080   │                  5b                            pop bx\n0x000081   │                  6b c0 0f                      imul ax, ax, 0xf\n0x000084   │                  01 c1                         add cx, ax\n0x000086   │                  01 cb                         add bx, cx\n0x000088   │                  89 5e fe                      mov word [bp-2], bx\n0x00008b   │                  8d 7e fc                      lea di, word [bp-4]\n0x00008e   │                  8b 76 0c                      mov si, word [bp+12]\n0x000091   │                  8b 15                         mov dx, word [di]\n0x000093   │                  89 14                         mov word [si], dx\n0x000095   │                  8b 55 02                      mov dx, word [di+2]\n0x000098   │                  89 54 02                      mov word [si+2], dx\n0x00009b   │                  89 ec                         mov sp, bp\n0x00009d   │                  5d                            pop bp\n0x00009e   │                  c2 08 00                      ret 0x8\n0x0000a1   │                  55                            push bp\n0x0000a2   │                  89 e5                         mov bp, sp\n0x0000a4   │                  83 ec 0a                      sub sp, 0xa\n0x0000a7   │                  c7 46 fc 04 00                mov word [bp-4], 0x4\n0x0000ac   │                  c7 46 fe 03 00                mov word [bp-2], 0x3\n0x0000b1   │                  8d 5e f8                      lea bx, word [bp-8]\n0x0000b4   │                  53                            push bx\n0x0000b5   │                  6a 05                         push 0x5\n0x0000b7   │                  ff 76 fe                      push word [bp-2]\n0x0000ba   │                  ff 76 fc                      push word [bp-4]\n0x0000bd   │                  6a 02                         push 0x2\n0x0000bf  ─╯                  e8 81 ff                      call 0x43\n0x0000c2                      8d 5e f8                      lea bx, word [bp-8]\n0x0000c5                      8b 07                         mov ax, word [bx]\n0x0000c7                      83 c3 02                      add bx, 0x2\n0x0000ca                      8b 0f                         mov cx, word [bx]\n0x0000cc                      01 c8                         add ax, cx\n0x0000ce                      89 46 f6                      mov word [bp-10], ax\n0x0000d1                      87 d2                         xchg dx, dx\n0x0000d3                      89 ec                         mov sp, bp\n0x0000d5                      5d                            pop bp\n0x0000d6                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Compound statements\n\n[GCC Docs](https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html)\n\n```c\nvoid main() {\n  int dupa = (({\n                int c = 3, k, d;\n\n                k = 16;\n                d = 20;\n                c + k + d * 4;\n              }) *\n              2 * ({\n                int k = 15;\n                k * 2;\n              })) *\n             ({ 5 + 2; });\n\n  asm(\"xchg dx, dx\");\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block main ---\ndef main():\n  dupa{0}: int*2B = alloca int2B\n  c{0}: int*2B = alloca int2B\n  *(c{0}: int*2B) = store %3: int2B\n  k{0}: int*2B = alloca int2B\n  d{0}: int*2B = alloca int2B\n  *(k{0}: int*2B) = store %16: char1B\n  *(d{0}: int*2B) = store %20: char1B\n  %t{0}: int2B = load c{0}: int*2B\n  %t{1}: int2B = load k{0}: int*2B\n  %t{3}: int2B = load d{0}: int*2B\n  %t{8}: int2B = %t{0}: int2B plus %t{1}: int2B\n  %t{10}: int2B = %t{3}: int2B mul %4: char1B\n  %t{11}: int2B = %t{8}: int2B plus %t{10}: int2B\n  %t{12}: int2B = %t{11}: int2B mul %2: char1B\n  k{1}: int*2B = alloca int2B\n  *(k{1}: int*2B) = store %15: int2B\n  %t{13}: int2B = load k{1}: int*2B\n  %t{16}: int2B = %t{13}: int2B mul %2: char1B\n  %t{17}: int2B = %t{12}: int2B mul %t{16}: int2B\n  %t{20}: int2B = %t{17}: int2B mul %7: char1B\n  *(dupa{0}: int*2B) = store %t{20}: int2B\n  asm \"xchg dx, dx\"\n  ret\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000                      55                            push bp\n0x000001                      89 e5                         mov bp, sp\n0x000003                      83 ec 0a                      sub sp, 0xa\n0x000006                      c7 46 fc 03 00                mov word [bp-4], 0x3\n0x00000b                      c7 46 fa 10 00                mov word [bp-6], 0x10\n0x000010                      c7 46 f8 14 00                mov word [bp-8], 0x14\n0x000015                      8b 46 fc                      mov ax, word [bp-4]\n0x000018                      03 46 fa                      add ax, word [bp-6]\n0x00001b                      8b 5e f8                      mov bx, word [bp-8]\n0x00001e                      c1 e3 02                      shl bx, 0x2\n0x000021                      01 d8                         add ax, bx\n0x000023                      d1 e0                         shl ax, 0x1\n0x000025                      c7 46 f6 0f 00                mov word [bp-10], 0xf\n0x00002a                      8b 4e f6                      mov cx, word [bp-10]\n0x00002d                      d1 e1                         shl cx, 0x1\n0x00002f                      0f af c1                      imul ax, cx\n0x000032                      6b c0 07                      imul ax, ax, 0x7\n0x000035                      89 46 fe                      mov word [bp-2], ax\n0x000038                      87 d2                         xchg dx, dx\n0x00003a                      89 ec                         mov sp, bp\n0x00003c                      5d                            pop bp\n0x00003d                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Advanced array / pointers / ternary expressions\n\n```c\n  int strlen(const char* str) {\n    for (int i = 0;;++i) {\n      if (*(str + i) == 0) {\n        return i;\n      }\n    }\n\n    return -1;\n  }\n\n  typedef struct Box {\n    int x, y;\n    const char* str;\n  } box_t;\n\n  int max (int a, int b) {\n    return a \u003e b ? a : b;\n  }\n\n  void main() {\n    box_t vec[] = { { .y = 5 }, { .x = 4, .str = \"ABC\" } };\n\n    vec[0].str = \"Hello world!\";\n    vec[0].y++;\n    vec[1].x += 3;\n\n    int k = vec[1].x * vec[0].y + strlen(vec[0].str);\n    int d = max(666, k * 20);\n\n    asm(\"xchg dx, dx\");\n  }\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block strlen ---\ndef strlen(str{0}: const char**2B): [ret: int2B]\n  i{0}: int*2B = alloca int2B\n  *(i{0}: int*2B) = store %0: int2B\n  L1:\n  %t{2}: const char*2B = load str{0}: const char**2B\n  %t{3}: int2B = load i{0}: int*2B\n  %t{4}: const char*2B = %t{2}: const char*2B plus %t{3}: int2B\n  %t{5}: const char1B = load %t{4}: const char*2B\n  %t{6}: i1:zf = icmp %t{5}: const char1B equal %0: char1B\n  br %t{6}: i1:zf, false: L4\n  L5:\n  %t{7}: int2B = load i{0}: int*2B\n  ret %t{7}: int2B\n  L4:\n  %t{0}: int2B = load i{0}: int*2B\n  %t{1}: int2B = %t{0}: int2B plus %1: int2B\n  *(i{0}: int*2B) = store %t{1}: int2B\n  jmp L1\n  L3:\n  ret %-1: char1B\n  end-def\n\n\n# --- Block max ---\ndef max(a{0}: int*2B, b{0}: int*2B): [ret: int2B]\n  %t{9}: int2B = alloca int2B\n  %t{10}: int2B = load a{0}: int*2B\n  %t{11}: int2B = load b{0}: int*2B\n  %t{12}: i1:zf = icmp %t{10}: int2B greater_than %t{11}: int2B\n  br %t{12}: i1:zf, false: L8\n  L7:\n  %t{15}: int2B = load a{0}: int*2B\n  %t{13}: int2B = assign:φ %t{15}: int2B\n  jmp L6\n  L8:\n  %t{16}: int2B = load b{0}: int*2B\n  %t{14}: int2B = assign:φ %t{16}: int2B\n  L6:\n  %t{9}: int2B = φ(%t{13}: int2B, %t{14}: int2B)\n  ret %t{9}: int2B\n  end-def\n\n\n# --- Block main ---\ndef main():\n  vec{0}: struct Box[3]*2B = alloca struct Box[3]18B\n  *(vec{0}: struct Box[3]*2B + %2) = store %5: int2B\n  *(vec{0}: struct Box[3]*2B + %6) = store %4: int2B\n  *(vec{0}: int*2B + %10) = store %16961: int2B\n  *(vec{0}: int*2B + %12) = store %67: int2B\n  %t{17}: struct Box[3]*2B = lea vec{0}: struct Box[3]*2B\n  %t{20}: const char**2B = label-offset c{0}\n  %t{21}: const char*2B = load %t{20}: const char**2B\n  *(vec{0}: struct Box[3]*2B + %4) = store %t{21}: const char*2B\n  %t{24}: int*2B = %t{17}: struct Box[3]*2B plus %2: int2B\n  %t{25}: int2B = load %t{24}: int*2B\n  %t{26}: int2B = %t{25}: int2B plus %1: int2B\n  *(vec{0}: struct Box[3]*2B + %2) = store %t{26}: int2B\n  %t{28}: struct Box[3]*2B = %t{17}: struct Box[3]*2B plus %6: int2B\n  %t{29}: int2B = load %t{28}: int*2B\n  %t{30}: int2B = %t{29}: int2B plus %3: char1B\n  *(vec{0}: struct Box[3]*2B + %6) = store %t{30}: int2B\n  k{0}: int*2B = alloca int2B\n  %t{32}: struct Box[3]*2B = %t{17}: struct Box[3]*2B plus %6: int2B\n  %t{33}: int2B = load %t{32}: int*2B\n  %t{36}: int*2B = %t{17}: struct Box[3]*2B plus %2: int2B\n  %t{37}: int2B = load %t{36}: int*2B\n  %t{38}: int2B = %t{33}: int2B mul %t{37}: int2B\n  %t{42}: const char**2B = %t{17}: struct Box[3]*2B plus %4: int2B\n  %t{43}: const char*2B = load %t{42}: const char**2B\n  %t{44}: int2B = call label-offset strlen :: (%t{43}: const char*2B)\n  %t{45}: int2B = %t{38}: int2B plus %t{44}: int2B\n  *(k{0}: int*2B) = store %t{45}: int2B\n  d{0}: int*2B = alloca int2B\n  %t{47}: int2B = load k{0}: int*2B\n  %t{48}: int2B = %t{47}: int2B mul %20: char1B\n  %t{49}: int2B = call label-offset max :: (%666: int2B, %t{48}: int2B)\n  *(d{0}: int*2B) = store %t{49}: int2B\n  asm \"xchg dx, dx\"\n  ret\n  end-def\n\n# --- Block Data ---\n  c{0}: const char**2B = const { Hello world! }\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000  \u003c────╮              55                            push bp\n0x000001       │              89 e5                         mov bp, sp\n0x000003       │              83 ec 02                      sub sp, 0x2\n0x000006       │              c7 46 fe 00 00                mov word [bp-2], 0x0\n0x00000b  \u003c──╮ │              8b 5e 04                      mov bx, word [bp+4]\n0x00000e     │ │              03 5e fe                      add bx, word [bp-2]\n0x000011     │ │              8a 07                         mov al, byte [bx]\n0x000013     │ │              3c 00                         cmp al, 0x0\n0x000015  ─╮ │ │              75 09                         jnz 0x20\n0x000017   │ │ │              8b 46 fe                      mov ax, word [bp-2]\n0x00001a   │ │ │              89 ec                         mov sp, bp\n0x00001c   │ │ │              5d                            pop bp\n0x00001d   │ │ │              c2 02 00                      ret 0x2\n0x000020  \u003c╯ │ │              8b 46 fe                      mov ax, word [bp-2]\n0x000023     │ │              05 01 00                      add ax, 0x1\n0x000026     │ │              89 46 fe                      mov word [bp-2], ax\n0x000029  ───╯ │              eb e0                         jmp 0xb\n0x00002b       │              b8 ff ff                      mov ax, -0x1\n0x00002e       │              89 ec                         mov sp, bp\n0x000030       │              5d                            pop bp\n0x000031       │              c2 02 00                      ret 0x2\n0x000034  \u003c────┼─╮            55                            push bp\n0x000035       │ │            89 e5                         mov bp, sp\n0x000037       │ │            83 ec 02                      sub sp, 0x2\n0x00003a       │ │            8b 46 06                      mov ax, word [bp+6]\n0x00003d       │ │            39 46 04                      cmp word [bp+4], ax\n0x000040  ─╮   │ │            7e 05                         jng 0x47\n0x000042   │   │ │            8b 46 04                      mov ax, word [bp+4]\n0x000045  ─┼─╮ │ │            eb 03                         jmp 0x4a\n0x000047  \u003c╯ │ │ │            8b 46 06                      mov ax, word [bp+6]\n0x00004a  \u003c──╯ │ │            89 ec                         mov sp, bp\n0x00004c       │ │            5d                            pop bp\n0x00004d       │ │            c2 04 00                      ret 0x4\n0x000050       │ │            55                            push bp\n0x000051       │ │            89 e5                         mov bp, sp\n0x000053       │ │            83 ec 16                      sub sp, 0x16\n0x000056       │ │            c7 46 f0 05 00                mov word [bp-16], 0x5\n0x00005b       │ │            c7 46 f4 04 00                mov word [bp-12], 0x4\n0x000060       │ │            c7 46 f8 41 42                mov word [bp-8], 0x4241\n0x000065       │ │            c7 46 fa 43 00                mov word [bp-6], 0x43\n0x00006a       │ │            8d 5e ee                      lea bx, word [bp-18]\n0x00006d       │ │            a1 cc 00                      mov ax, ds:@@_c_0_\n0x000070       │ │            89 46 f2                      mov word [bp-14], ax\n0x000073       │ │            89 d9                         mov cx, bx\n0x000075       │ │            83 c3 02                      add bx, 0x2\n0x000078       │ │            8b 17                         mov dx, word [bx]\n0x00007a       │ │            83 c2 01                      add dx, 0x1\n0x00007d       │ │            89 56 f0                      mov word [bp-16], dx\n0x000080       │ │            89 c8                         mov ax, cx\n0x000082       │ │            83 c1 06                      add cx, 0x6\n0x000085       │ │            89 cf                         mov di, cx\n0x000087       │ │            8b 1d                         mov bx, word [di]\n0x000089       │ │            83 c3 03                      add bx, 0x3\n0x00008c       │ │            89 5e f4                      mov word [bp-12], bx\n0x00008f       │ │            89 c1                         mov cx, ax\n0x000091       │ │            05 06 00                      add ax, 0x6\n0x000094       │ │            89 c6                         mov si, ax\n0x000096       │ │            8b 14                         mov dx, word [si]\n0x000098       │ │            89 c8                         mov ax, cx\n0x00009a       │ │            83 c1 02                      add cx, 0x2\n0x00009d       │ │            89 cf                         mov di, cx\n0x00009f       │ │            8b 1d                         mov bx, word [di]\n0x0000a1       │ │            0f af d3                      imul dx, bx\n0x0000a4       │ │            05 04 00                      add ax, 0x4\n0x0000a7       │ │            89 c6                         mov si, ax\n0x0000a9       │ │            8b 0c                         mov cx, word [si]\n0x0000ab       │ │            52                            push dx\n0x0000ac       │ │            51                            push cx\n0x0000ad  ─────╯ │            e8 50 ff                      call 0x0\n0x0000b0         │            5a                            pop dx\n0x0000b1         │            01 c2                         add dx, ax\n0x0000b3         │            89 56 ec                      mov word [bp-20], dx\n0x0000b6         │            8b 5e ec                      mov bx, word [bp-20]\n0x0000b9         │            6b db 14                      imul bx, bx, 0x14\n0x0000bc         │            53                            push bx\n0x0000bd         │            68 9a 02                      push 0x29a\n0x0000c0  ───────╯            e8 71 ff                      call 0x34\n0x0000c3                      89 46 ea                      mov word [bp-22], ax\n0x0000c6                      87 d2                         xchg dx, dx\n0x0000c8                      89 ec                         mov sp, bp\n0x0000ca                      5d                            pop bp\n0x0000cb                      c3                            ret\n0x0000cc                      ce 00                         dw @@_c_0_@str$0_0\n0x0000ce                      48 65 6c 6c 6f 20 77 6f       db \"hello world!\", 0x0\n          72 6c 64 21 00 00\n```\n\n\u003c/details\u003e\n\n### Dynamic alloca\n\n```c\n  #include \u003calloca.h\u003e\n\n  int main() {\n    int k = 10;\n    char* buffer = alloca(k);\n    return 0;\n  }\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block main ---\ndef main(): [ret: int2B]\n  k{0}: int*2B = alloca int2B\n  *(k{0}: int*2B) = store %10: int2B\n  buffer{0}: char**2B = alloca char*2B\n  %t{1}: int2B = load k{0}: int*2B\n  %t{2}: char*2B = call label-offset __builtin_alloca :: (%t{1}: int2B)\n  *(buffer{0}: char**2B) = store %t{2}: char*2B\n  ret %0: char1B\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000                      55                            push bp\n0x000001                      89 e5                         mov bp, sp\n0x000003                      83 ec 04                      sub sp, 0x4\n0x000006                      c7 46 fe 0a 00                mov word [bp-2], 0xa\n0x00000b                      2b 66 fe                      sub sp, word [bp-2]\n0x00000e                      89 e0                         mov ax, sp\n0x000010                      89 46 fc                      mov word [bp-4], ax\n0x000013                      b8 00 00                      mov ax, 0x0\n0x000016                      89 ec                         mov sp, bp\n0x000018                      5d                            pop bp\n0x000019                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Simple function calls with peephole optimization\n\n```c\n  #define int16_t int\n\n  int16_t sum(int x) {\n    return x * 2 / 4;\n  }\n\n  int16_t main() {\n    return sum(3);\n  }\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block sum ---\ndef sum(x{0}: int*2B): [ret: int2B]\n  %t{0}: int2B = load x{0}: int*2B\n  %t{2}: int2B = %t{0}: int2B div %2: char1B\n  ret %t{2}: int2B\n  end-def\n\n\n# --- Block main ---\ndef main(): [ret: int2B]\n  %t{4}: int2B = call label-offset sum :: (%3: char1B)\n  ret %t{4}: int2B\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000  \u003c╮                  55                            push bp\n0x000001   │                  89 e5                         mov bp, sp\n0x000003   │                  8b 46 04                      mov ax, word [bp+4]\n0x000006   │                  d1 e8                         shr ax, 0x1\n0x000008   │                  89 ec                         mov sp, bp\n0x00000a   │                  5d                            pop bp\n0x00000b   │                  c2 02 00                      ret 0x2\n0x00000e   │                  55                            push bp\n0x00000f   │                  89 e5                         mov bp, sp\n0x000011   │                  6a 03                         push 0x3\n0x000013  ─╯                  e8 ea ff                      call 0x0\n0x000016                      89 ec                         mov sp, bp\n0x000018                      5d                            pop bp\n0x000019                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Function pointers\n\n```c\n  int sum(int x, int y) {\n    return x + y * 2;\n  }\n\n  int addPtr(int (*functionPtr)(int, int)) {\n    return (*functionPtr)(2, 3);\n  }\n\n  int main() {\n    int sum = addPtr(sum);\n  }\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block sum ---\ndef sum(x{0}: int*2B, y{0}: int*2B): [ret: int2B]\n  %t{0}: int2B = load x{0}: int*2B\n  %t{1}: int2B = load y{0}: int*2B\n  %t{2}: int2B = %t{1}: int2B mul %2: char1B\n  %t{3}: int2B = %t{0}: int2B plus %t{2}: int2B\n  ret %t{3}: int2B\n  end-def\n\n\n# --- Block addPtr ---\ndef addPtr(functionPtr{0}: int(int, int)**2B): [ret: int2B]\n  %t{4}: int(int, int)*2B = load functionPtr{0}: int(int, int)**2B\n  %t{5}: int2B = call %t{4}: int(int, int)*2B :: (%2: char1B, %3: char1B)\n  ret %t{5}: int2B\n  end-def\n\n\n# --- Block main ---\ndef main(): [ret: int2B]\n  sum{0}: int*2B = alloca int2B\n  %t{7}: int sum(int, int)*2B = label-offset sum\n  %t{8}: int2B = call label-offset addPtr :: (%t{7}: int sum(int, int)*2B)\n  *(sum{0}: int*2B) = store %t{8}: int2B\n  ret\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000                      55                            push bp\n0x000001                      89 e5                         mov bp, sp\n0x000003                      8b 46 06                      mov ax, word [bp+6]\n0x000006                      d1 e0                         shl ax, 0x1\n0x000008                      8b 5e 04                      mov bx, word [bp+4]\n0x00000b                      01 c3                         add bx, ax\n0x00000d                      89 d8                         mov ax, bx\n0x00000f                      89 ec                         mov sp, bp\n0x000011                      5d                            pop bp\n0x000012                      c2 04 00                      ret 0x4\n0x000015  \u003c╮                  55                            push bp\n0x000016   │                  89 e5                         mov bp, sp\n0x000018   │                  8b 5e 04                      mov bx, word [bp+4]\n0x00001b   │                  6a 03                         push 0x3\n0x00001d   │                  6a 02                         push 0x2\n0x00001f   │                  ff d3                         call bx\n0x000021   │                  89 ec                         mov sp, bp\n0x000023   │                  5d                            pop bp\n0x000024   │                  c2 02 00                      ret 0x2\n0x000027   │                  55                            push bp\n0x000028   │                  89 e5                         mov bp, sp\n0x00002a   │                  83 ec 02                      sub sp, 0x2\n0x00002d   │                  6a 00                         push 0x0\n0x00002f  ─╯                  e8 e3 ff                      call 0x15\n0x000032                      89 46 fe                      mov word [bp-2], ax\n0x000035                      89 ec                         mov sp, bp\n0x000037                      5d                            pop bp\n0x000038                      c3                            ret\n```\n\n\u003c/details\u003e\n\n### Bubble sort\n\n```c\nvoid bubble_sort(int a[], int n) {\n  int i = 0, j = 0, tmp;\n  for (i = 0; i \u003c n; i++) {   // loop n times - 1 per element\n    for (j = 0; j \u003c n - i - 1; j++) { // last i elements are sorted already\n      if (a[j] \u003e a[j + 1]) {  // swop if order is broken\n        tmp = a[j];\n        a[j] = a[j + 1];\n        a[j + 1] = tmp;\n      }\n    }\n  }\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block bubble_sort ---\ndef bubble_sort(a{0}: int[]*2B, n{0}: int*2B):\n  i{0}: int*2B = alloca int2B\n  *(i{0}: int*2B) = store %0: int2B\n  j{0}: int*2B = alloca int2B\n  *(j{0}: int*2B) = store %0: int2B\n  tmp{0}: int*2B = alloca int2B\n  L1:\n  %t{0}: int2B = load i{0}: int*2B\n  %t{1}: int2B = load n{0}: int*2B\n  %t{2}: i1:zf = icmp %t{0}: int2B less_than %t{1}: int2B\n  br %t{2}: i1:zf, true: L2, false: L3\n  L2:\n  %t{5}: int2B = load j{0}: int*2B\n  %t{6}: int2B = load n{0}: int*2B\n  %t{7}: int2B = load i{0}: int*2B\n  %t{8}: int2B = %t{6}: int2B minus %t{7}: int2B\n  %t{9}: int2B = %t{8}: int2B minus %1: char1B\n  %t{10}: i1:zf = icmp %t{5}: int2B less_than %t{9}: int2B\n  br %t{10}: i1:zf, true: L5, false: L6\n  L5:\n  %t{13}: int[]*2B = lea a{0}: int[]*2B\n  %t{14}: int2B = load j{0}: int*2B\n  %t{15}: int[]*2B = %t{14}: int2B mul %2: int2B\n  %t{16}: int[]*2B = %t{13}: int[]*2B plus %t{15}: int[]*2B\n  %t{17}: int2B = load %t{16}: int[]*2B\n  %t{20}: int2B = %t{14}: int2B plus %1: char1B\n  %t{21}: int[]*2B = %t{20}: int2B mul %2: int2B\n  %t{22}: int[]*2B = %t{13}: int[]*2B plus %t{21}: int[]*2B\n  %t{23}: int2B = load %t{22}: int[]*2B\n  %t{24}: i1:zf = icmp %t{17}: int2B greater_than %t{23}: int2B\n  br %t{24}: i1:zf, false: L7\n  L8:\n  %t{25}: int[]*2B = lea a{0}: int[]*2B\n  %t{26}: int2B = load j{0}: int*2B\n  %t{27}: int[]*2B = %t{26}: int2B mul %2: int2B\n  %t{28}: int[]*2B = %t{25}: int[]*2B plus %t{27}: int[]*2B\n  %t{29}: int2B = load %t{28}: int[]*2B\n  *(tmp{0}: int*2B) = store %t{29}: int2B\n  %t{32}: int[]*2B = %t{26}: int2B mul %2: int2B\n  %t{33}: int[]*2B = %t{25}: int[]*2B plus %t{32}: int[]*2B\n  %t{36}: int2B = %t{26}: int2B plus %1: char1B\n  %t{37}: int[]*2B = %t{36}: int2B mul %2: int2B\n  %t{38}: int[]*2B = %t{25}: int[]*2B plus %t{37}: int[]*2B\n  %t{39}: int2B = load %t{38}: int[]*2B\n  *(%t{33}: int[]*2B) = store %t{39}: int2B\n  %t{42}: int2B = %t{26}: int2B plus %1: char1B\n  %t{43}: int[]*2B = %t{42}: int2B mul %2: int2B\n  %t{44}: int[]*2B = %t{25}: int[]*2B plus %t{43}: int[]*2B\n  %t{45}: int2B = load tmp{0}: int*2B\n  *(%t{44}: int[]*2B) = store %t{45}: int2B\n  L7:\n  %t{11}: int2B = load j{0}: int*2B\n  %t{12}: int2B = %t{11}: int2B plus %1: int2B\n  *(j{0}: int*2B) = store %t{12}: int2B\n  jmp L2\n  L6:\n  %t{3}: int2B = load i{0}: int*2B\n  %t{4}: int2B = %t{3}: int2B plus %1: int2B\n  *(i{0}: int*2B) = store %t{4}: int2B\n  jmp L1\n  L3:\n  ret\n  end-def\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000                      55                            push bp\n0x000001                      89 e5                         mov bp, sp\n0x000003                      83 ec 0a                      sub sp, 0xa\n0x000006                      c7 46 fe 00 00                mov word [bp-2], 0x0\n0x00000b                      c7 46 fc 00 00                mov word [bp-4], 0x0\n0x000010  \u003c────────╮          8b 46 06                      mov ax, word [bp+6]\n0x000013           │          39 46 fe                      cmp word [bp-2], ax\n0x000016  ─╮       │          7c 04                         jl 0x1c\n0x000018  ─┼─╮     │          0f 8d 89 00                   jge 0xa5\n0x00001c  \u003c╯\u003c┼───╮ │          8b 46 06                      mov ax, word [bp+6]\n0x00001f     │   │ │          2b 46 fe                      sub ax, word [bp-2]\n0x000022     │   │ │          2d 01 00                      sub ax, 0x1\n0x000025     │   │ │          39 46 fc                      cmp word [bp-4], ax\n0x000028  ─╮ │   │ │          7c 02                         jl 0x2c\n0x00002a  ─┼─┼─╮ │ │          7d 6d                         jge 0x99\n0x00002c  \u003c╯ │ │ │ │          8d 5e 04                      lea bx, word [bp+4]\n0x00002f     │ │ │ │          8b 46 fc                      mov ax, word [bp-4]\n0x000032     │ │ │ │          89 c1                         mov cx, ax\n0x000034     │ │ │ │          d1 e0                         shl ax, 0x1\n0x000036     │ │ │ │          89 da                         mov dx, bx\n0x000038     │ │ │ │          01 c3                         add bx, ax\n0x00003a     │ │ │ │          8b 07                         mov ax, word [bx]\n0x00003c     │ │ │ │          83 c1 01                      add cx, 0x1\n0x00003f     │ │ │ │          d1 e1                         shl cx, 0x1\n0x000041     │ │ │ │          01 ca                         add dx, cx\n0x000043     │ │ │ │          89 d7                         mov di, dx\n0x000045     │ │ │ │          8b 1d                         mov bx, word [di]\n0x000047     │ │ │ │          39 d8                         cmp ax, bx\n0x000049  ─╮ │ │ │ │          7e 43                         jng 0x8e\n0x00004b   │ │ │ │ │          8d 5e 04                      lea bx, word [bp+4]\n0x00004e   │ │ │ │ │          8b 46 fc                      mov ax, word [bp-4]\n0x000051   │ │ │ │ │          89 c1                         mov cx, ax\n0x000053   │ │ │ │ │          d1 e0                         shl ax, 0x1\n0x000055   │ │ │ │ │          89 da                         mov dx, bx\n0x000057   │ │ │ │ │          01 c3                         add bx, ax\n0x000059   │ │ │ │ │          8b 07                         mov ax, word [bx]\n0x00005b   │ │ │ │ │          89 46 fa                      mov word [bp-6], ax\n0x00005e   │ │ │ │ │          89 c8                         mov ax, cx\n0x000060   │ │ │ │ │          d1 e1                         shl cx, 0x1\n0x000062   │ │ │ │ │          89 d3                         mov bx, dx\n0x000064   │ │ │ │ │          01 ca                         add dx, cx\n0x000066   │ │ │ │ │          89 c1                         mov cx, ax\n0x000068   │ │ │ │ │          05 01 00                      add ax, 0x1\n0x00006b   │ │ │ │ │          d1 e0                         shl ax, 0x1\n0x00006d   │ │ │ │ │          89 46 f8                      mov word [bp-8], ax\n0x000070   │ │ │ │ │          89 d8                         mov ax, bx\n0x000072   │ │ │ │ │          01 c3                         add bx, ax\n0x000074   │ │ │ │ │          89 46 f6                      mov word [bp-10], ax\n0x000077   │ │ │ │ │          8b 07                         mov ax, word [bx]\n0x000079   │ │ │ │ │          89 d7                         mov di, dx\n0x00007b   │ │ │ │ │          89 05                         mov word [di], ax\n0x00007d   │ │ │ │ │          83 c1 01                      add cx, 0x1\n0x000080   │ │ │ │ │          d1 e1                         shl cx, 0x1\n0x000082   │ │ │ │ │          8b 56 f6                      mov dx, word [bp-10]\n0x000085   │ │ │ │ │          01 ca                         add dx, cx\n0x000087   │ │ │ │ │          89 d6                         mov si, dx\n0x000089   │ │ │ │ │          8b 56 fa                      mov dx, word [bp-6]\n0x00008c   │ │ │ │ │          89 14                         mov word [si], dx\n0x00008e  \u003c╯ │ │ │ │          8b 46 fc                      mov ax, word [bp-4]\n0x000091     │ │ │ │          05 01 00                      add ax, 0x1\n0x000094     │ │ │ │          89 46 fc                      mov word [bp-4], ax\n0x000097  ───┼─┼─╯ │          eb 83                         jmp 0x1c\n0x000099  \u003c──┼─╯   │          8b 46 fe                      mov ax, word [bp-2]\n0x00009c     │     │          05 01 00                      add ax, 0x1\n0x00009f     │     │          89 46 fe                      mov word [bp-2], ax\n0x0000a2  ───┼─────╯          e9 6b ff                      jmp 0x10\n0x0000a5  \u003c──╯                89 ec                         mov sp, bp\n0x0000a7                      5d                            pop bp\n0x0000a8                      c2 04 00                      ret 0x4\n```\n\n\u003c/details\u003e\n\n### Printing BIOS charset\n\nPrinting BIOS charset:\n\n```c\n  const char* VRAM_ADDR = 0xB800;\n  const char* KERNEL_INIT_MESSAGES[] = {\n    \"Tiny kernel!\",\n    \"Charset table:\"\n  };\n\n  struct Vec2 {\n    int x, y;\n  };\n\n  struct Vec2 kernel_screen_cursor = {\n    .x = 0,\n    .y = 0,\n  };\n\n  int strlen(const char* str) {\n    for (int i = 0;;++i) {\n      if (*(str + i) == 0) {\n        return i;\n      }\n    }\n\n    return -1;\n  }\n\n  void kernel_screen_clear() {\n    asm(\n      \"mov cx, 0x7d0\\n\"\n      \"mov ax, 0xF00\\n\"\n      \"mov dx, 0xB800\\n\"\n      \"mov es, dx\\n\"\n      \"xor di, di\\n\"\n      \"rep stosw\\n\"\n    );\n  }\n\n  void kernel_print_char_at(int x, int y, char color, char letter) {\n    const int offset = (y * 80 + x) * 2;\n\n    asm(\n      \"mov gs, %[vram]\\n\"\n      \"mov dl, %[color]\\n\"\n      \"mov dh, %[letter]\\n\"\n      \"mov bx, %[offset]\\n\"\n      \"mov byte [gs:bx + 1], dl\\n\"\n      \"mov byte [gs:bx], dh\\n\"\n      ::\n        [vram] \"r\" (VRAM_ADDR),\n        [offset] \"m\" (offset),\n        [letter] \"m\" (letter),\n        [color] \"m\" (color)\n      : \"dx\", \"bx\", \"gs\"\n    );\n  }\n\n  void kernel_screen_print_at(int x, int y, char color, const char* str) {\n    const int len = strlen(str);\n\n    for (int i = 0; i \u003c len; ++i) {\n      kernel_print_char_at(x + i, y, color, str[i]);\n    }\n  }\n\n  void kernel_screen_newline() {\n    kernel_screen_cursor.x = 0;\n    kernel_screen_cursor.y++;\n  }\n\n  void kernel_screen_println(char color, const char* str) {\n    kernel_screen_print_at(\n      kernel_screen_cursor.x,\n      kernel_screen_cursor.y,\n      color,\n      str\n    );\n\n    kernel_screen_newline();\n  }\n\n  void main() {\n    kernel_screen_clear();\n\n    for (int i = 0; i \u003c 0x2; ++i) {\n      kernel_screen_println(0xF, KERNEL_INIT_MESSAGES[i]);\n    }\n\n    kernel_screen_newline();\n\n    for (int x = 0; x \u003c 0xFF; ++x) {\n      kernel_print_char_at(x, kernel_screen_cursor.y, 0xF, 0x1 + x);\n    }\n  }\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eIR Output\u003c/strong\u003e\u003c/summary\u003e\n\n```ruby\n# --- Block strlen ---\ndef strlen(str{0}: const char**2B): [ret: int2B]\n  i{0}: int*2B = alloca int2B\n  *(i{0}: int*2B) = store %0: int2B\n  L1:\n  %t{2}: const char*2B = load str{0}: const char**2B\n  %t{3}: int2B = load i{0}: int*2B\n  %t{4}: const char*2B = %t{2}: const char*2B plus %t{3}: int2B\n  %t{5}: const char1B = load %t{4}: const char*2B\n  %t{6}: i1:zf = icmp %t{5}: const char1B equal %0: char1B\n  br %t{6}: i1:zf, false: L4\n  L5:\n  %t{7}: int2B = load i{0}: int*2B\n  ret %t{7}: int2B\n  L4:\n  %t{0}: int2B = load i{0}: int*2B\n  %t{1}: int2B = %t{0}: int2B plus %1: int2B\n  *(i{0}: int*2B) = store %t{1}: int2B\n  jmp L1\n  L3:\n  ret %-1: char1B\n  end-def\n\n\n# --- Block kernel_screen_clear ---\ndef kernel_screen_clear():\n  asm \"mov cx, 0x7d0\nmov ax, 0xF00\nmov dx, 0xB800\nmov es, dx\nxor di, di\nrep stosw\n\"\n  ret\n  end-def\n\n\n# --- Block kernel_print_char_at ---\ndef kernel_print_char_at(x{0}: int*2B, y{0}: int*2B, color{0}: char*2B, letter{0}: char*2B):\n  offset{0}: const int*2B = alloca const int2B\n  %t{9}: int2B = load y{0}: int*2B\n  %t{10}: int2B = %t{9}: int2B mul %80: char1B\n  %t{11}: int2B = load x{0}: int*2B\n  %t{12}: int2B = %t{10}: int2B plus %t{11}: int2B\n  %t{13}: int2B = %t{12}: int2B mul %2: char1B\n  *(offset{0}: const int*2B) = store %t{13}: int2B\n  %t{14}: const char**2B = label-offset c{0}\n  %t{15}: const char*2B = load %t{14}: const char**2B\n  %t{16}: const int2B = load offset{0}: const int*2B\n  %t{17}: char1B = load letter{0}: char*2B\n  %t{18}: char1B = load color{0}: char*2B\n  asm \"mov gs, %[vram]\nmov dl, %[color]\nmov dh, %[letter]\nmov bx, %[offset]\nmov byte [gs:bx + 1], dl\nmov byte [gs:bx], dh\n\"\n  ret\n  end-def\n\n\n# --- Block kernel_screen_print_at ---\ndef kernel_screen_print_at(x{1}: int*2B, y{1}: int*2B, color{1}: char*2B, str{1}: const char**2B):\n  len{0}: const int*2B = alloca const int2B\n  %t{20}: const char*2B = load str{1}: const char**2B\n  %t{21}: int2B = call label-offset strlen :: (%t{20}: const char*2B)\n  *(len{0}: const int*2B) = store %t{21}: int2B\n  i{0}: int*2B = alloca int2B\n  *(i{0}: int*2B) = store %0: int2B\n  L6:\n  %t{22}: int2B = load i{0}: int*2B\n  %t{23}: const int2B = load len{0}: const int*2B\n  %t{24}: i1:zf = icmp %t{22}: int2B less_than %t{23}: const int2B\n  br %t{24}: i1:zf, true: L7, false: L8\n  L7:\n  %t{28}: int2B = load x{1}: int*2B\n  %t{29}: int2B = load i{0}: int*2B\n  %t{30}: int2B = %t{28}: int2B plus %t{29}: int2B\n  %t{31}: int2B = load y{1}: int*2B\n  %t{32}: char1B = load color{1}: char*2B\n  %t{33}: const char*2B = load str{1}: const char**2B\n  %t{35}: const char*2B = %t{29}: int2B mul %1: int2B\n  %t{36}: const char*2B = %t{33}: const char*2B plus %t{35}: const char*2B\n  %t{37}: const char1B = load %t{36}: const char*2B\n  call label-offset kernel_print_char_at :: (%t{30}: int2B, %t{31}: int2B, %t{32}: char1B, %t{37}: const char1B)\n  %t{26}: int2B = %t{29}: int2B plus %1: int2B\n  *(i{0}: int*2B) = store %t{26}: int2B\n  jmp L6\n  L8:\n  ret\n  end-def\n\n\n# --- Block kernel_screen_newline ---\ndef kernel_screen_newline():\n  %t{38}: struct Vec2*2B = label-offset c{2}\n  *(%t{38}: int*2B) = store %0: char1B\n  %t{40}: int*2B = %t{38}: struct Vec2*2B plus %2: int2B\n  %t{41}: int2B = load %t{40}: int*2B\n  %t{42}: int2B = %t{41}: int2B plus %1: int2B\n  *(%t{40}: int*2B) = store %t{42}: int2B\n  ret\n  end-def\n\n\n# --- Block kernel_screen_println ---\ndef kernel_screen_println(color{1}: char*2B, str{1}: const char**2B):\n  %t{44}: struct Vec2*2B = label-offset c{2}\n  %t{45}: int2B = load %t{44}: int*2B\n  %t{47}: int*2B = %t{44}: struct Vec2*2B plus %2: int2B\n  %t{48}: int2B = load %t{47}: int*2B\n  %t{49}: char1B = load color{1}: char*2B\n  %t{50}: const char*2B = load str{1}: const char**2B\n  call label-offset kernel_screen_print_at :: (%t{45}: int2B, %t{48}: int2B, %t{49}: char1B, %t{50}: const char*2B)\n  call label-offset kernel_screen_newline :: ()\n  ret\n  end-def\n\n\n# --- Block main ---\ndef main():\n  call label-offset kernel_screen_clear :: ()\n  i{0}: int*2B = alloca int2B\n  *(i{0}: int*2B) = store %0: int2B\n  L9:\n  %t{53}: int2B = load i{0}: int*2B\n  %t{54}: i1:zf = icmp %t{53}: int2B less_than %2: char1B\n  br %t{54}: i1:zf, true: L10, false: L11\n  L10:\n  %t{58}: const char*[2]*2B = label-offset c{1}\n  %t{59}: int2B = load i{0}: int*2B\n  %t{60}: const char*[2]*2B = %t{59}: int2B mul %2: int2B\n  %t{61}: const char*[2]*2B = %t{58}: const char*[2]*2B plus %t{60}: const char*[2]*2B\n  %t{62}: const char*2B = load %t{61}: const char*[2]*2B\n  call label-offset kernel_screen_println :: (%15: char1B, %t{62}: const char*2B)\n  %t{56}: int2B = %t{59}: int2B plus %1: int2B\n  *(i{0}: int*2B) = store %t{56}: int2B\n  jmp L9\n  L11:\n  call label-offset kernel_screen_newline :: ()\n  %1_x{0}: int*2B = alloca int2B\n  *(%1_x{0}: int*2B) = store %0: int2B\n  L12:\n  %t{64}: int2B = load %1_x{0}: int*2B\n  %t{65}: i1:zf = icmp %t{64}: int2B less_than %255: char1B\n  br %t{65}: i1:zf, true: L13, false: L14\n  L13:\n  %t{69}: int2B = load %1_x{0}: int*2B\n  %t{70}: struct Vec2*2B = label-offset c{2}\n  %t{71}: int*2B = %t{70}: struct Vec2*2B plus %2: int2B\n  %t{72}: int2B = load %t{71}: int*2B\n  %t{74}: int2B = %t{69}: int2B plus %1: char1B\n  call label-offset kernel_print_char_at :: (%t{69}: int2B, %t{72}: int2B, %15: char1B, %t{74}: int2B)\n  %t{67}: int2B = %t{69}: int2B plus %1: int2B\n  *(%1_x{0}: int*2B) = store %t{67}: int2B\n  jmp L12\n  L14:\n  ret\n  end-def\n\n# --- Block Data ---\n  c{0}: const char**2B = const { 47104 }\n  c{1}: const char*[2]*2B = const { Tiny kernel!, Charset table: }\n  c{2}: struct Vec2*2B = const { 0, 0 }\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eBinary output\u003c/strong\u003e\u003c/summary\u003e\n\n```asm\n0x000000  \u003c────╮              55                            push bp\n0x000001       │              89 e5                         mov bp, sp\n0x000003       │              83 ec 02                      sub sp, 0x2\n0x000006       │              c7 46 fe 00 00                mov word [bp-2], 0x0\n0x00000b  \u003c──╮ │              8b 5e 04                      mov bx, word [bp+4]\n0x00000e     │ │              03 5e fe                      add bx, word [bp-2]\n0x000011     │ │              8a 07                         mov al, byte [bx]\n0x000013     │ │              3c 00                         cmp al, 0x0\n0x000015  ─╮ │ │              75 09                         jnz 0x20\n0x000017   │ │ │              8b 46 fe                      mov ax, word [bp-2]\n0x00001a   │ │ │              89 ec                         mov sp, bp\n0x00001c   │ │ │              5d                            pop bp\n0x00001d   │ │ │              c2 02 00                      ret 0x2\n0x000020  \u003c╯ │ │              8b 46 fe                      mov ax, word [bp-2]\n0x000023     │ │              05 01 00                      add ax, 0x1\n0x000026     │ │              89 46 fe                      mov word [bp-2], ax\n0x000029  ───╯ │              eb e0                         jmp 0xb\n0x00002b       │              b8 ff ff                      mov ax, -0x1\n0x00002e       │              89 ec                         mov sp, bp\n0x000030       │              5d                            pop bp\n0x000031       │              c2 02 00                      ret 0x2\n0x000034  \u003c────┼─────╮        55                            push bp\n0x000035       │     │        89 e5                         mov bp, sp\n0x000037       │     │        b9 d0 07                      mov cx, 0x7d0\n0x00003a       │     │        b8 00 0f                      mov ax, 0xf00\n0x00003d       │     │        ba 00 b8                      mov dx, 0xb800\n0x000040       │     │        8e c2                         mov es, dx\n0x000042       │     │        31 ff                         xor di, di\n0x000044       │     │        f3 ab                         repz stosw\n0x000046       │     │        89 ec                         mov sp, bp\n0x000048       │     │        5d                            pop bp\n0x000049       │     │        c3                            ret\n0x00004a  \u003c────┼─╮\u003c──┼───╮    55                            push bp\n0x00004b       │ │   │   │    89 e5                         mov bp, sp\n0x00004d       │ │   │   │    83 ec 02                      sub sp, 0x2\n0x000050       │ │   │   │    8b 46 06                      mov ax, word [bp+6]\n0x000053       │ │   │   │    6b c0 50                      imul ax, ax, 0x50\n0x000056       │ │   │   │    03 46 04                      add ax, word [bp+4]\n0x000059       │ │   │   │    d1 e0                         shl ax, 0x1\n0x00005b       │ │   │   │    89 46 fe                      mov word [bp-2], ax\n0x00005e       │ │   │   │    8b 1e 7e 01                   mov bx, word [@@_c_0_]\n0x000062       │ │   │   │    8e eb                         mov gs, bx\n0x000064       │ │   │   │    8a 56 08                      mov dl, byte [bp+8]\n0x000067       │ │   │   │    8a 76 0a                      mov dh, byte [bp+10]\n0x00006a       │ │   │   │    8b 5e fe                      mov bx, word [bp-2]\n0x00006d       │ │   │   │    65 88 57 01                   mov byte [gs:bx+1], dl\n0x000071       │ │   │   │    65 88 37                      mov byte [gs:bx], dh\n0x000074       │ │   │   │    89 ec                         mov sp, bp\n0x000076       │ │   │   │    5d                            pop bp\n0x000077       │ │   │   │    c2 08 00                      ret 0x8\n0x00007a  \u003c────┼─┼─╮ │   │    55                            push bp\n0x00007b       │ │ │ │   │    89 e5                         mov bp, sp\n0x00007d       │ │ │ │   │    83 ec 04                      sub sp, 0x4\n0x000080       │ │ │ │   │    8b 5e 0a                      mov bx, word [bp+10]\n0x000083       │ │ │ │   │    53                            push bx\n0x000084  ─────╯ │ │ │   │    e8 79 ff                      call 0x0\n0x000087         │ │ │   │    89 46 fe                      mov word [bp-2], ax\n0x00008a         │ │ │   │    c7 46 fc 00 00                mov word [bp-4], 0x0\n0x00008f  \u003c────╮ │ │ │   │    8b 46 fe                      mov ax, word [bp-2]\n0x000092       │ │ │ │   │    39 46 fc                      cmp word [bp-4], ax\n0x000095  ─╮   │ │ │ │   │    7c 02                         jl 0x99\n0x000097  ─┼─╮ │ │ │ │   │    7d 2c                         jge 0xc5\n0x000099  \u003c╯ │ │ │ │ │   │    8b 46 04                      mov ax, word [bp+4]\n0x00009c     │ │ │ │ │   │    03 46 fc                      add ax, word [bp-4]\n0x00009f     │ │ │ │ │   │    8b 5e 0a                      mov bx, word [bp+10]\n0x0000a2     │ │ │ │ │   │    03 5e fc                      add bx, word [bp-4]\n0x0000a5     │ │ │ │ │   │    8a 0f                         mov cl, byte [bx]\n0x0000a7     │ │ │ │ │   │    0f b6 d1                      movzx dx, cl\n0x0000aa     │ │ │ │ │   │    52                            push dx\n0x0000ab     │ │ │ │ │   │    8b 4e 08                      mov cx, word [bp+8]\n0x0000ae     │ │ │ │ │   │    81 e1 ff 00                   and cx, 0xff\n0x0000b2     │ │ │ │ │   │    51                            push cx\n0x0000b3     │ │ │ │ │   │    ff 76 06                      push word [bp+6]\n0x0000b6     │ │ │ │ │   │    50                            push ax\n0x0000b7  ───┼─┼─╯ │ │   │    e8 90 ff                      call 0x4a\n0x0000ba     │ │   │ │   │    8b 46 fc                      mov ax, word [bp-4]\n0x0000bd     │ │   │ │   │    05 01 00                      add ax, 0x1\n0x0000c0     │ │   │ │   │    89 46 fc                      mov word [bp-4], ax\n0x0000c3  ───┼─╯   │ │   │    eb ca                         jmp 0x8f\n0x0000c5  \u003c──╯     │ │   │    89 ec                         mov sp, bp\n0x0000c7           │ │   │    5d                            pop bp\n0x0000c8           │ │   │    c2 08 00                      ret 0x8\n0x0000cb  \u003c╮\u003c──────┼─┼─╮ │    55                            push bp\n0x0000cc   │       │ │ │ │    89 e5                         mov bp, sp\n0x0000ce   │       │ │ │ │    c7 06 a2 01 00 00             mov word [@@_c_2_], 0x0\n0x0000d4   │       │ │ │ │    b8 a2 01                      mov ax, 0x1a2\n0x0000d7   │       │ │ │ │    05 02 00                      add ax, 0x2\n0x0000da   │       │ │ │ │    89 c7                         mov di, ax\n0x0000dc   │       │ │ │ │    8b 1d                         mov bx, word [di]\n0x0000de   │       │ │ │ │    83 c3 01                      add bx, 0x1\n0x0000e1   │       │ │ │ │    89 1d                         mov word [di], bx\n0x0000e3   │       │ │ │ │    89 ec                         mov sp, bp\n0x0000e5   │       │ │ │ │    5d                            pop bp\n0x0000e6   │       │ │ │ │    c3                            ret\n0x0000e7  \u003c┼───╮   │ │ │ │    55                            push bp\n0x0000e8   │   │   │ │ │ │    89 e5                         mov bp, sp\n0x0000ea   │   │   │ │ │ │    a1 a2 01                      mov ax, ds:@@_c_2_\n0x0000ed   │   │   │ │ │ │    bb a2 01                      mov bx, 0x1a2\n0x0000f0   │   │   │ │ │ │    83 c3 02                      add bx, 0x2\n0x0000f3   │   │   │ │ │ │    8b 0f                         mov cx, word [bx]\n0x0000f5   │   │   │ │ │ │    8b 7e 06                      mov di, word [bp+6]\n0x0000f8   │   │   │ │ │ │    57                            push di\n0x0000f9   │   │   │ │ │ │    8b 56 04                      mov dx, word [bp+4]\n0x0000fc   │   │   │ │ │ │    81 e2 ff 00                   and dx, 0xff\n0x000100   │   │   │ │ │ │    52                            push dx\n0x000101   │   │   │ │ │ │    51                            push cx\n0x000102   │   │   │ │ │ │    50                            push ax\n0x000103  ─┼───┼───╯ │ │ │    e8 74 ff                      call 0x7a\n0x000106  ─╯   │     │ │ │    e8 c2 ff                      call 0xcb\n0x000109       │     │ │ │    89 ec                         mov sp, bp\n0x00010b       │     │ │ │    5d                            pop bp\n0x00010c       │     │ │ │    c2 04 00                      ret 0x4\n0x00010f       │     │ │ │    55                            push bp\n0x000110       │     │ │ │    89 e5                         mov bp, sp\n0x000112       │     │ │ │    83 ec 04                      sub sp, 0x4\n0x000115  ─────┼─────╯ │ │    e8 1c ff                      call 0x34\n0x000118       │       │ │    c7 46 fe 00 00                mov word [bp-2], 0x0\n0x00011d  \u003c────┼─╮     │ │    83 7e fe 02                   cmp word [bp-2], 0x2\n0x000121  ─╮   │ │     │ │    7c 02                         jl 0x125\n0x000123  ─┼─╮ │ │     │ │    7d 20                         jge 0x145\n0x000125  \u003c╯ │ │ │     │ │    8b 46 fe                      mov ax, word [bp-2]\n0x000128     │ │ │     │ │    89 c3                         mov bx, ax\n0x00012a     │ │ │     │ │    d1 e0                         shl ax, 0x1\n0x00012c     │ │ │     │ │    b9 80 01                      mov cx, 0x180\n0x00012f     │ │ │     │ │    01 c1                         add cx, ax\n0x000131     │ │ │     │ │    89 cf                         mov di, cx\n0x000133     │ │ │     │ │    8b 15                         mov dx, word [di]\n0x000135     │ │ │     │ │    53                            push bx\n0x000136     │ │ │     │ │    52                            push dx\n0x000137     │ │ │     │ │    6a 0f                         push 0xf\n0x000139  ───┼─╯ │     │ │    e8 ab ff                      call 0xe7\n0x00013c     │   │     │ │    5b                            pop bx\n0x00013d     │   │     │ │    83 c3 01                      add bx, 0x1\n0x000140     │   │     │ │    89 5e fe                      mov word [bp-2], bx\n0x000143  ───┼───╯     │ │    eb d8                         jmp 0x11d\n0x000145  \u003c──╯─────────╯ │    e8 83 ff                      call 0xcb\n0x000148                 │    c7 46 fc 00 00                mov word [bp-4], 0x0\n0x00014d  \u003c────╮         │    81 7e fc ff 00                cmp word [bp-4], 0xff\n0x000152  ─╮   │         │    7c 02                         jl 0x156\n0x000154  ─┼─╮ │         │    7d 24                         jge 0x17a\n0x000156  \u003c╯ │ │         │    b8 a2 01                      mov ax, 0x1a2\n0x000159     │ │         │    05 02 00                      add ax, 0x2\n0x00015c     │ │         │    89 c7                         mov di, ax\n0x00015e     │ │         │    8b 1d                         mov bx, word [di]\n0x000160     │ │         │    8b 46 fc                      mov ax, word [bp-4]\n0x000163     │ │         │    89 c1                         mov cx, ax\n0x000165     │ │         │    05 01 00                      add ax, 0x1\n0x000168     │ │         │    51                            push cx\n0x000169     │ │         │    50                            push ax\n0x00016a     │ │         │    6a 0f                         push 0xf\n0x00016c     │ │         │    53                            push bx\n0x00016d     │ │         │    51                            push cx\n0x00016e  ───┼─┼─────────╯    e8 d9 fe                      call 0x4a\n0x000171     │ │              59                            pop cx\n0x000172     │ │              83 c1 01                      add cx, 0x1\n0x000175     │ │              89 4e fc                      mov word [bp-4], cx\n0x000178  ───┼─╯              eb d3                         jmp 0x14d\n0x00017a  \u003c──╯                89 ec                         mov sp, bp\n0x00017c                      5d                            pop bp\n0x00017d                      c3                            ret\n0x00017e                      00 b8                         dw 47104\n0x000180                      84 01                         dw @@_c_1_@str$0_0\n0x000182                      92 01                         dw @@_c_1_@str$0_1\n0x000184                      54 69 6e 79 20 6b 65 72       db \"tiny kernel!\", 0x0\n          6e 65 6c 21 00 00\n0x000192                      43 68 61 72 73 65 74 20       db \"charset table:\", 0x0\n          74 61 62 6c 65 3a 00 00\n0x0001a2                      00 00 00 00                   dw 0, 0\n```\n\n\u003c/details\u003e\n\n## ASM syntax\n\nIt's pretty similar to NASM syntax (including preprocessor), examples: \u003cbr\u003e\n[https://github.com/Mati365/i8086.js/tree/master/packages/x86-assembler/tests/asm](https://github.com/Mati365/ts-c-compiler/tree/master/packages/x86-toolkit/x86-assembler/tests/asm)\n\n## Architecture\n\n### Multipass steps\n\n- [x] Frontend **([source](https://github.com/Mati365/ts-c-compiler/blob/master/packages/compiler-pico-c/src/frontend/cIRcompiler.ts))**\n\n  - [x] Lexer **([source](https://github.com/Mati365/ts-c-compiler/blob/master/packages/compiler-pico-c/src/frontend/parser/lexer/clexer.ts#L37))**\n  - [x] AST creator **([source](https://github.com/Mati365/ts-c-compiler/blob/master/packages/compiler-pico-c/src/frontend/parser/grammar/grammar.ts))**\n  - [x] Type checking **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/compiler-pico-c/src/frontend/analyze))**\n  - [x] IR generation **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/compiler-pico-c/src/frontend/ir))**\n\n- [x] Backend **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/compiler-pico-c/src/backend))**\n  - [x] X86 arch backend **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/compiler-pico-c/src/arch/x86))**\n    - [x] X86 Register linear scan allocation **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/compiler-pico-c/src/arch/x86/backend/reg-allocator))**\n    - [x] X86 ASM generators **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/compiler-pico-c/src/arch/x86/backend/compilers))**\n\n### X86 Arch support\n\n- [x] 16bit real mode X86 arch support\n\n  - [x] X86 16bit Multipass Assembler compatible with NASM syntax **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/x86-toolkit/x86-assembler))**\n\n    - [x] Preprocessor **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/x86-toolkit/x86-assembler/src/preprocessor))** compatible with NASM that supports:\n      - [x] Conditions and definitions: `%if`, `%ifn`, `%ifdef`, `%ifndef`, `%else`, `%elif`, `%elifndef`, `%elifdef`, `%elifn`, `%define`, `%undef`\n      - [x] Macros: `%macro`, `%define`, `%imacro`\n      - [x] Predefined variables: `__TIMES__`\n      - [x] Inline expressions calls: `%[__TIMES__]`\n\n  - [x] X86 CPU 16bit Intel 8086 virtual machine **([source](https://github.com/Mati365/ts-c-compiler/tree/master/packages/x86-toolkit/x86-cpu))**\n    - [x] VGA graphical mode support **([source](https://github.com/Mati365/ts-c-compiler/blob/master/packages/x86-toolkit/x86-cpu/src/devices/Video/Renderers/VGAGraphicsModeCanvasRenderer.ts))**\n    - [x] VGA text mode support **([source](https://github.com/Mati365/ts-c-compiler/blob/master/packages/x86-toolkit/x86-cpu/src/devices/Video/Renderers/VGATextModeCanvasRenderer.ts))**\n\n## Current progress\n\n- [ ] C compiler\n  - [x] Frontend\n    - [x] Syntax parser\n    - [x] Typechecker\n    - [x] IR code generator\n  - [x] Backend\n    - [x] IR optimizer\n    - [x] X86-16 Code generator\n      - [x] Register allocator\n        - [x] Basic allocation using ownership checking\n        - [x] Spilling regs and detection lifetime of IR vars\n      - [x] Compile math integer instruction\n        - [x] Compile `*`, `+`, `-`, `/`\n        - [x] Compile `\u003c\u003c`, `\u003e\u003e`\n        - [x] Compile xor / and / or / not\n      - [x] Compile if stmts\n      - [x] Compile loops `while {}`, `do { } while`, `for (...) {}`\n      - [x] Compile typedefs\n      - [x] Compile pointers\n        - [x] Basic pointer access `*k = 5`\n        - [x] Array access `k[4]`\n      - [x] Compile function calls\n      - [x] Compile `asm` tag\n        - [x] Basic `asm` tag without args\n        - [x] `asm` tag with arguments\n      - [ ] Unions\n      - [ ] Preprocessor\n      - [ ] Stdlib\n- [x] ASM Compiler\n  - [x] NASM syntax instruction compiler matcher with expression eval `mov ax, byte [ds:label+bx+12+(1/3)]`\n  - [x] Instruction prefix support `rep movsw`\n  - [x] Compiler bits/org config `[bits 16]`, `[org 0x7C00]`\n  - [x] Labels support `jmp_label:`\n  - [x] Data define support `db`, `dw`, `dd`, `dq`, `dt`\n  - [x] `EQU`, `times` support\n  - [x] Floating point numbers support\n  - [x] Preprocessor\n    - [x] Basic lang keywords support: `%if`, `%ifn`, `%ifdef`, `%ifndef`, `%else`, `%elif`, `%elifndef`, `%elifdef`, `%elifn`, `%define`, `%undef`\n    - [x] Macros support: `%macro`, `%define`, `%imacro`\n    - [x] Predefined macros like `__TIMES__`\n    - [x] Inline expressions calls `%[__TIMES__]`\n  - [x] Output logger\n    - [x] Basic logger binary blob serializer helpers\n    - [x] Diassembler binary view\n    - [x] Branch arrows (for `jmp`, `call`, `jz` etc.)\n- [ ] CPU Emulator\n  - [x] Magic breakpoint support `xchg bx, bx`\n  - [x] Interrupts handlers support\n  - [x] Basic Intel ~80186 instructions set\n  - [x] ALU instructions support\n  - [x] FPU Support\n    - [x] Assembler\n    - [x] Emulator\n  - [ ] Basic PIT/PIC support\n    - [x] PIT\n    - [ ] PIC\n    - [ ] IDE\n    - [ ] PS2\n  - [ ] Graphics mode\n    - [x] Basic canvas graphics driver\n    - [x] Text Mode\n    - [x] Graphics VGA\n    - [x] VGA IO ports bindings\n  - [ ] BIOS\n    - [x] Basic bios interrupt handlers\n- [ ] App frontend\n  - [ ] Basic front CSS UI\n  - [ ] Debugger\n\n## Screens\n\n![C Compiler Hello World](/doc/screen-13.png)\n![C Compiler Advanced Expressions](/doc/screen-12.png)\n![C Compiler Assembly](/doc/screen-11.png)\n![C Compiler IR](/doc/screen-10.png)\n![C Compiler IR](/doc/screen-9.png)\n![Pillman](/doc/screen-6.png)\n![Space invaders](/doc/screen-7.png)\n![Prototype](/doc/screen.gif)\n![Prototype](/doc/screen-2.png)\n![Tetris](/doc/screen-5.png)\n![ASM Preprocessor](/doc/screen-4.png)\n![ASM Compiler](/doc/screen-3.png)\n![C Compiler](/doc/screen-8.png)\n\n## Docs\n\n\u003chttps://cs.lmu.edu/~ray/notes/ir/\u003e\n\n\u003chttps://www.youtube.com/watch?v=yTXCPGAD3SQ\u003e\n\n\u003chttps://books.google.pl/books?id=Lq4yDwAAQBAJ\u0026pg=PA120\u0026lpg=PA120\u0026dq=chain4+mode\u0026source=bl\u0026ots=Eun_wNFE7b\u0026sig=ACfU3U37tSXE7qOZn0AKGeFwaaNLS4nrKg\u0026hl=pl\u0026sa=X\u0026ved=2ahUKEwjlupT5-u_pAhVNxhoKHVfRA7YQ6AEwAnoECAoQAQ#v=onepage\u0026q=chain4%20mode\u0026f=false\u003e\n\n\u003chttps://bellard.org/otcc/otccn.c\u003e\n\n\u003chttps://bellard.org/otcc/\u003e\n\n\u003chttps://gist.github.com/nikAizuddin/0e307cac142792dcdeba\u003e\n\n\u003chttp://www.plantation-productions.com/Webster/www.artofasm.com/Windows/HTML/RealArithmetica3.html\u003e\n\n\u003chttps://gist.github.com/mikesmullin/6259449\u003e\n\n\u003chttp://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt\u003e\n\n\u003chttp://ece425web.groups.et.byu.net/stable/labs/8086Assembly.html\u003e\n\n\u003chttp://dsearls.org/courses/C391OrgSys/IntelAL/8086_instruction_set.html\u003e\n\n\u003chttps://pdos.csail.mit.edu/6.828/2008/readings/i386/s17_02.htm\u003e\n\n\u003chttps://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol1/o_7281d5ea06a5b67a-194.html\u003e\n\n\u003chttps://johnloomis.org/ece314/notes/fpu/fpu.pdf\u003e\n\n\u003chttps://www.felixcloutier.com/x86/index.html\u003e\n\n\u003chttps://c9x.me/x86/html/file_module_x86_id_87.html\u003e\n\n\u003chttp://www.osdever.net/FreeVGA/vga/graphreg.htm#06\u003e\n\n\u003chttp://www.osdever.net/FreeVGA/vga/vgamem.htm\u003e\n\n\u003chttp://www.osdever.net/FreeVGA/home.htm\u003e\n\n## License\n\nThe MIT License (MIT)\nCopyright (c) 2023/2024 Mateusz Bagiński\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmati365%2Fts-c-compiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmati365%2Fts-c-compiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmati365%2Fts-c-compiler/lists"}