{"id":19813847,"url":"https://github.com/azer0s/persephone","last_synced_at":"2026-03-04T12:31:28.986Z","repository":{"id":136692892,"uuid":"167507901","full_name":"Azer0s/Persephone","owner":"Azer0s","description":"A simple instruction set","archived":false,"fork":false,"pushed_at":"2020-01-04T20:18:45.000Z","size":95,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-28T19:11:18.172Z","etag":null,"topics":["instruction-set","language-specification","virtual-machine"],"latest_commit_sha":null,"homepage":"","language":null,"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/Azer0s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-01-25T07:54:11.000Z","updated_at":"2022-04-05T15:17:31.000Z","dependencies_parsed_at":"2023-05-15T18:00:20.317Z","dependency_job_id":null,"html_url":"https://github.com/Azer0s/Persephone","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Azer0s/Persephone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FPersephone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FPersephone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FPersephone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FPersephone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Azer0s","download_url":"https://codeload.github.com/Azer0s/Persephone/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FPersephone/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30079737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T12:28:08.313Z","status":"ssl_error","status_checked_at":"2026-03-04T12:27:28.210Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["instruction-set","language-specification","virtual-machine"],"created_at":"2024-11-12T09:37:28.762Z","updated_at":"2026-03-04T12:31:28.958Z","avatar_url":"https://github.com/Azer0s.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# 💃🏻🍃 Persephone\n\n## Variable declaration\n\n`v_\u003cdatatype\u003e variable_name` \n\nASCII and Unicode strings can be loaded as 8 bit uints and vice versa. Dynamic variables (declared with `v_dyn`) can be used to store any data.\n\n### Commands:\n\n|        Datatype        |   Command   |\n| :--------------------: | :---------: |\n|    Dynamic variable    |   `v_dyn`   |\n|      8bit integer      |  `v_int8`   |\n|     16bit integer      |  `v_int16`  |\n|     32bit integer      |  `v_int32`  |\n|     32bit integer      |   `v_int`   |\n|     64bit integer      |  `v_int64`  |\n| 8bit unsigned integer  |  `v_uint8`  |\n| 16bit unsigned integer | `v_uint16`  |\n| 32bit unsigned integer | `v_uint32`  |\n| 32bit unsigned integer |  `v_uint`   |\n| 64bit unsigned integer | `v_uint64`  |\n|  32bit floating point  | `v_float32` |\n|  32bit floating point  |  `v_float`  |\n|  64bit floating point  | `v_float64` |\n|  64bit floating point  | `v_double`  |\n|      ASCII string      | `v_stringa` |\n|     Unicode string     | `v_stringu` |\n|          Bit           |   `v_bit`   |\n|        Pointer         |   `v_ptr`   |\n\nWhen storing data, loading constants or variables, implicit conversion is possible.\n\n```\nu8 -\u003e ASCII string\nASCII string -\u003e u8\n\nu8 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\nu16 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\nu32 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\nu64 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\n\nptr (u32) -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\n\ni8 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\ni16 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\ni32 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\ni64 -\u003e all unsigned \u0026 signed int sizes \u0026 ptr\n```\n\n## Variable destruction\n\n`delete variable_name`\n\n## Constant declaration\n\n`dc\u003cdatatype\u003e value`\n\n### Commands:\n\n|        Datatype        | Command |\n| :--------------------: | :-----: |\n|      8bit integer      | `dci8`  |\n|     16bit integer      | `dci16` |\n|     32bit integer      | `dci32` |\n|     32bit integer      |  `dci`  |\n|     64bit integer      | `dci64` |\n| 8bit unsigned integer  | `dcu8`  |\n| 16bit unsigned integer | `dcu16` |\n| 32bit unsigned integer | `dcu32` |\n| 32bit unsigned integer |  `dcu`  |\n| 64bit unsigned integer | `dcu64` |\n|  32bit floating point  | `dcf32` |\n|  32bit floating point  |  `dcf`  |\n|  64bit floating point  | `dcf64` |\n|  64bit floating point  |  `dcd`  |\n|      ASCII string      | `dcsa`  |\n|     Unicode string     | `dcsu`  |\n|          Bit           |  `dcb`  |\n\n## Load values from variable\n\n`ld\u003cdatatype\u003ev variable_name`\n\nTo load a variable of unknown datatype, one can use `lddynv`.\n\n### Commands:\n\n|        Datatype        | Command  |\n| :--------------------: | :------: |\n|    Dynamic variable    | `lddynv` |\n|      8bit integer      | `ldi8v`  |\n|     16bit integer      | `ldi16v` |\n|     32bit integer      | `ldi32v` |\n|     32bit integer      |  `ldiv`  |\n|     64bit integer      | `ldi64v` |\n| 8bit unsigned integer  | `ldu8v`  |\n| 16bit unsigned integer | `ldu16v` |\n| 32bit unsigned integer | `ldu32v` |\n| 32bit unsigned integer |  `lduv`  |\n| 64bit unsigned integer | `ldu64v` |\n|  32bit floating point  | `ldf32v` |\n|  32bit floating point  |  `ldfv`  |\n|  64bit floating point  | `ldf64v` |\n|  64bit floating point  |  `lddv`  |\n|      ASCII string      | `ldsav`  |\n|     Unicode string     | `ldsuv`  |\n|          Bit           |  `ldbv`  |\n|          Ptr           | `ldptrv` |\n\n## Load pointer\n\nOne can load the pointer of any function, label or variable. In Persephone, labels, functions and variables are stored in one address space. This means that if you have 4 labels, the pointer (without memory offset) to the first variable is going to be 0x4.\n\n```\n+-----------------+-----------------+-----------------+-----------------+-------------- ~ ~ --------------+\n|  Label 1 (0x0)  |  Label 2 (0x1)  |  Label 3 (0x2)  |  Label 4 (0x3)  |  Var 1 (0x4)  ~ ~  Var n (0xn)  |\n+-----------------+-----------------+-----------------+-----------------+-------------- ~ ~ --------------+\n```\n\n| Datatype | Command |\n| :------: | :-----: |\n|  Label   | `ldptr` |\n| Variable | `ldptr` |\n\n## Load values from constant\n\n`ld\u003cdatatype\u003ec variable_name`\n\n### Commands:\n\n|        Datatype        | Command  |\n| :--------------------: | :------: |\n|      8bit integer      | `ldi8c`  |\n|     16bit integer      | `ldi16c` |\n|     32bit integer      | `ldi32c` |\n|     32bit integer      |  `ldic`  |\n|     64bit integer      | `ldi64c` |\n| 8bit unsigned integer  | `ldu8c`  |\n| 16bit unsigned integer | `ldu16c` |\n| 32bit unsigned integer | `ldu32c` |\n| 32bit unsigned integer |  `lduc`  |\n| 64bit unsigned integer | `ldu64c` |\n|  32bit floating point  | `ldf32c` |\n|  32bit floating point  |  `ldfc`  |\n|  64bit floating point  | `ldf64c` |\n|  64bit floating point  |  `lddc`  |\n|      ASCII string      | `ldsac`  |\n|     Unicode string     | `ldsuc`  |\n|          Bit           |  `ldbc`  |\n\n## Pop value from stack\n\n`pop` removes the top most value from the stack\n\n## Return from label\n\n`ret` returns from a function and jumps to the address of where the function was called +1.\n\n## Noop\n\n`nop` does nothing.\n\n## Constant pointer base\n\n`cbase` sets the offset for the pointer to the constant map for a specific code region.\n\n```coffeescript\na:\n\n#        \u003c---+\ndcsa \"Foo\" # |\ndcsa \"Bar\" # | Constant offset is 0, `ldsac 0` would put \"Foo\" on the stack\ndcsa \"Baz\" # |\n#        \u003c---+\n   \ncbase\n\n#        \u003c---+\ndcsa \"abc\" # |\ndcsa \"def\" # | Constant offset is 3, `ldsac 0` would put \"a\" on the stack\ndcsa \"ghi\" # |\n#        \u003c---+\n\njmp a # when jumping, the constant offset gets set according to the region\n```\n\n## Len\n\nFor strings, `len` puts the number of characters of the string on the stack. For all other values, their bit size is put on the stack. `len` puts an 32 bit unsigned int on the stack.\n\n## Type\n\n`type` puts the datatype of a variable as u8 on the stack.\n\n|     Datatype     | Code |\n| :--------------: | :--: |\n|      `uint`      | 0x0  |\n|      `int`       | 0x1  |\n|     `float`      | 0x2  |\n|  `ASCII string`  | 0x3  |\n| `Unicode string` | 0x4  |\n|      `Bit`       | 0x5  |\n|      `Ptr`       | 0x6  |\n\n## Compiler directives\n\n### Include\n\n`%include nameOfFile.psph`\n\nThe name of the file must be relative to the file you are including.\n\n### Region\n`%region nameOfRegion`\n\u003cbr\u003e\n`%endregion`\n\nRegions help with formatting your code.\n\n## Operators\n\n### Arithmetic operators\n\nThe lower stack value is the left hand side, the upper is the right hand side of any operation. After an operation, both sides of arguments are popped from the stack and the result is pushed onto it.\n\n#### Commands:\n\n|            Operation             | Command |\n| :------------------------------: | :-----: |\n|         Add two integers         |  `add`  |\n|      Subtract two integers       |  `sub`  |\n|      Multiply two integers       |  `mul`  |\n|       Divide two integers        |  `div`  |\n| Modulo operation on two integers |  `mod`  |\n|         Greater or equal         |  `ge`   |\n|          Less or equal           |  `le`   |\n|           Greater than           |  `gt`   |\n|            Less than             |  `lt`   |\n|           And two ints           | `andi`  |\n|           Or two ints            |  `ori`  |\n|           Xor two ints           | `xori`  |\n|          Flip int bits           | `noti`  |\n|            Left shift            |  `shl`  |\n|           Right shift            |  `shr`  |\n|         Increment by one         |  `inc`  |\n|         Decrement by one         |  `dec`  |\n|          Add two floats          | `addf`  |\n|       Subtract two floats        | `subf`  |\n|       Multiply two floats        | `mulf`  |\n|        Divide two floats         | `divf`  |\n|     Greater or equal (float)     |  `gef`  |\n|      Less or equal (float)       |  `lef`  |\n|       Greater than (float)       |  `gtf`  |\n|        Less than (float)         |  `ltf`  |\n\nThe size of the result value is determined by the size of the operands.\nThe result value will have the smallest size possible.\n\nE.g.: Left value is i8, right value is i16 =\u003e result value will be i16\n\nThe result value will be unsigned only of both operands are unsigned.\n\n### Logical operators\n\n#### Commands:\n\n|     Operation     | Command |\n| :---------------: | :-----: |\n| Equality operator |  `eq`   |\n|   And two bits    |  `and`  |\n|    Or two bits    |  `or`   |\n|   Xor two bits    |  `xor`  |\n|    Flip a bit     |  `not`  |\n\n### String operations\n\n#### Commands:\n\n|                   Operation                    |      Command       |\n| :--------------------------------------------: | :----------------: |\n|            Concatenate two strings             |       `conc`       |\n|       Get a character (stack: position)        | `getc \u003cnameOfVar\u003e` |\n| Set a character (lower: position, upper: char) | `setc \u003cnameOfVar\u003e` |\n\n## Jump to a label\n\n`jmp \u003clabelname\u003e`\n\n## Conditional jump\n\n### Jump if top of stack is 1/true\n\n`jmpt \u003clabelname\u003e`\n\n### Jump if top of stack is 0/false\n\n`jmpf \u003clabelname\u003e`\n\n## call vs jmp\n\n`call` puts an address into the return stack while `jmp` does not. If you want to return from a label, use `call`. If you just want to jump to a label, use `jmp`.\n\n## Bytecode\n\nAt the beginning of a binary file, you have to declare labels. The first 16 bits of the file declares how long the label section is (size is the number of labels).\n\nA label consists of two 64 bit ints. The first one is the label name (or a hex representation/placeholder for it). The second int is the position of the byte the label jumps to.\n\n### Examples\n\n```\n0x1 0xFA63 0x12\n```\n\nThis means that there is only one label. The single label has the name 0xFA63 and points to the 18th byte of the program (after the label section).\n\n### Commands\n\nA command is always an unsigned 16 bit integer. Commands with parameters are followed by an unsigned 8 bit integer that determines the type of the following parameter.\n\n### Parameters\n\n|       Type       | Opcode |\n| :--------------: | :----: |\n|      `uint`      |  0x0   |\n|      `int`       |  0x1   |\n|     `float`      |  0x2   |\n|  `ASCII string`  |  0x3   |\n| `Unicode string` |  0x4   |\n|      `Bit`       |  0x5   |\n|      `Ptr`       |  0x6   |\n|    Labelname     |  0xE   |\n|     Variable     |  0xF   |\n\n`int` and `uint` is followed by the size of the integer. This can either be 0x8 (u/int8), 0x10 (u/int16), 0x20 (u/int32) or 0x40 (u/int64). The actual value comes after the size. Leading zeroes are required if the value doesn't fill all bits.\n\n`float` is also followed by a size. This can be 0x21 (float32) or 0x41 (float64). The actual value comes after the size. Leading zeroes are required if the value doesn't fill all bits.\n\n`ASCII string` and `Unicode string` are followed by the size of the string (total bytes as unsigned 64 bit integer). The actual value comes after the size. Persephone should infer the type of the string (if the length of the byte array is the same length as the string, it's an ASCII string).\n\n`Bit` is followed by either a 0x0 or a 0x1.\n\n`Ptr` is followed by a 64 bit unsigned integer variable name.\n\nCommands that require a varname, are followed by 0xF and a 64 bit unsigned integer value which stands for the variable name.\n\n#### Example: Int\n\n42 is 0x2A in hex and 00101010 in binary. If we want to put 42 into a 16 bit integer, we need to frontpad it. That means that it would look like so: 0000000000101010 or 0x002A in hex.\n\n```\n0x1 0x10 0x002A\n```\n\nBy default, Persephone should infer the int size from the value.\n\n|                    Range                    |  Bits  |\n| :-----------------------------------------: | :----: |\n|                 -128 to 127                 |  int8  |\n|                  0 to 255                   | uint8  |\n|               -32768 to 32767               | int16  |\n|                 0 to 65535                  | uint16 |\n|          -2147483648 to 2147483647          | int32  |\n|               0 to 4294967295               | uint32 |\n| -9223372036854775808 to 9223372036854775807 | int64  |\n|          0 to 18446744073709551615          | uint64 |\n\n### Syscalls\n\nLoad parameter onto stack, call `syscall` with opcode or ptr as parameter.\n\n|  Command  | Opcode |\n| :-------: | :----: |\n|   Print   |  0x01  |\n|  Println  |  0x10  |\n| Read char |  0x02  |\n| Read line |  0x20  |\n\n\n### Command opcodes \n\n|   Command   | Opcode |\n| :---------: | :----: |\n|   `type`    | 0xEEEE |\n|    `nop`    | 0x1000 |\n|   `store`   | 0x0000 |\n|   `v_dyn`   | 0x0101 |\n|  `v_int8`   | 0x0108 |\n|  `v_int16`  | 0x0110 |\n|  `v_int32`  | 0x0120 |\n|   `v_int`   | 0x0120 |\n|  `v_int64`  | 0x0140 |\n|  `v_uint8`  | 0x1108 |\n| `v_uint16`  | 0x1110 |\n| `v_uint32`  | 0x1120 |\n|  `v_uint`   | 0x1120 |\n| `v_uint64`  | 0x1140 |\n| `v_float32` | 0x0121 |\n|  `v_float`  | 0x0121 |\n| `v_float64` | 0x0141 |\n| `v_double`  | 0x0141 |\n| `v_stringa` | 0x0131 |\n| `v_stringu` | 0x0132 |\n|   `v_ptr`   | 0x0150 |\n|   `v_bit`   | 0x0100 |\n|  `delete`   | 0x0099 |\n|   `dci8`    | 0x0218 |\n|   `dci16`   | 0x0210 |\n|   `dci32`   | 0x0220 |\n|    `dci`    | 0x0220 |\n|   `dci64`   | 0x0240 |\n|   `dcu8`    | 0x1218 |\n|   `dcu16`   | 0x1210 |\n|   `dcu32`   | 0x1220 |\n|    `dcu`    | 0x1220 |\n|   `dcu64`   | 0x1240 |\n|   `dcf32`   | 0x0221 |\n|    `dcf`    | 0x0221 |\n|   `dcf64`   | 0x0241 |\n|    `dcd`    | 0x0241 |\n|   `dcsa`    | 0x0231 |\n|   `dcsu`    | 0x0232 |\n|    `dcb`    | 0x0200 |\n|  `lddynv`   | 0x0301 |\n|   `ldi8v`   | 0x0318 |\n|  `ldi16v`   | 0x0310 |\n|  `ldi32v`   | 0x0320 |\n|   `ldiv`    | 0x0320 |\n|  `ldi64v`   | 0x0340 |\n|   `ldu8v`   | 0x1318 |\n|  `ldu16v`   | 0x1310 |\n|  `ldu32v`   | 0x1320 |\n|   `lduv`    | 0x1320 |\n|  `ldu64v`   | 0x1340 |\n|  `ldf32v`   | 0x0321 |\n|   `ldfv`    | 0x0321 |\n|  `ldf64v`   | 0x0341 |\n|   `lddv`    | 0x0341 |\n|   `ldsav`   | 0x0331 |\n|   `ldsuv`   | 0x0332 |\n|  `ldptrv`   | 0x0350 |\n|   `ldbv`    | 0x0300 |\n|   `ldi8c`   | 0x0418 |\n|  `ldi16c`   | 0x0410 |\n|  `ldi32c`   | 0x0420 |\n|   `ldic`    | 0x0420 |\n|  `ldi64c`   | 0x0440 |\n|   `ldu8c`   | 0x1418 |\n|  `ldu16c`   | 0x1410 |\n|  `ldu32c`   | 0x1420 |\n|   `lduc`    | 0x1420 |\n|  `ldu64c`   | 0x1440 |\n|  `ldf32c`   | 0x0421 |\n|   `ldfc`    | 0x0421 |\n|  `ldf64c`   | 0x0441 |\n|   `lddc`    | 0x0441 |\n|   `ldsac`   | 0x0431 |\n|   `ldsuc`   | 0x0432 |\n|   `ldbc`    | 0x0400 |\n|   `cbase`   | 0xFFFF |\n|    `pop`    | 0x0001 |\n|    `ret`    | 0x0002 |\n|    `eq`     | 0x0030 |\n|    `add`    | 0x0003 |\n|    `sub`    | 0x0004 |\n|    `mul`    | 0x0005 |\n|    `div`    | 0x0006 |\n|    `mod`    | 0x0007 |\n|    `ge`     | 0x0008 |\n|    `le`     | 0x0009 |\n|    `gt`     | 0x000A |\n|    `lt`     | 0x000B |\n|   `andi`    | 0x000C |\n|    `ori`    | 0x000D |\n|   `xori`    | 0x000E |\n|   `noti`    | 0x000F |\n|    `shl`    | 0x0010 |\n|    `shr`    | 0x0011 |\n|    `inc`    | 0x0012 |\n|    `dec`    | 0x0013 |\n|   `addf`    | 0x0014 |\n|   `subf`    | 0x0015 |\n|   `mulf`    | 0x0016 |\n|   `divf`    | 0x0017 |\n|    `gef`    | 0x0018 |\n|    `lef`    | 0x0019 |\n|    `gtf`    | 0x001A |\n|    `ltf`    | 0x001B |\n|    `and`    | 0x001C |\n|    `or`     | 0x001D |\n|    `xor`    | 0x001E |\n|    `not`    | 0x001F |\n|   `conc`    | 0x0020 |\n|    `len`    | 0x0021 |\n|   `getc`    | 0x0022 |\n|   `setc`    | 0x0023 |\n|  `syscall`  | 0x0024 |\n|  `extern`   | 0x0025 |\n\n### jmp/call\n\nThe `jmp` and `call` commands are followed by the hex value 0xE (labelname type) and a 64 bit unsigned int (the label name), a pointer value or an int value.\n\n|   Command   |   Opcode   |\n| :---------: | :---------: |\n| `call`| 0xF000 |\n|  `jmp`   |0xF001|\n|  `jmpt`  |0xF002|\n|  `jmpf`  |0xF003|\n\n## Persephone code sample\n\n### fibonacci\n\n```coffeescript\n# declare extern variable (optional, if you want to modify the program response)\nextern RETURN_CODE\n# Persephone exposes many extern variables like the pc or other runtime information\n\ndci32 0 # declare int32 constant\ndci32 1 # declare int32 constant\ndci32 10000 # declare int32 constant\ndci8 0 # declare int8 constant\n\nv_int32 var_01 # declare int32 variable\nv_int32 var_02 # declare int32 variable\n\nldi32c 0 # load 0th constant onto stack\nstore var_01 # initialize var_01 with 0\n\nldi32c 1 # load constant of index 1 onto stack\nstore var_02 # initialize var_02 with 1\n\nloop:\nldi32v var_01 # load int32 variable onto stack\nldi32c 2 # load constant of index 2 onto stack\nle\njmpt fib # jump to fib if var_01 is smaller or equal to 10000\njmp exit\n\nfib:\n\nldi32v var_01 # load var_01 onto stack\nldi32v var_02 # load var_02 onto stack\nadd # add and put result onto stack\nstore var_01 # store top stack value into var_01\n\nldi32v var_01\nldi32v var_02\nadd\nstore var_02\n\nldi32v var_01\nsyscall 0x10 # print var_01\n\nldi32v var_02\nsyscall 0x10 # print var_02\n\njmp loop\n\nexit: # exit program\nldi8c 4\nstore RETURN_CODE\n```\n\n### Boolean\n\n```coffeescript\ndcb false\ndcb true\n\nldbc 0\nldbc 1\nxor\nsyscall 0x10\n\nldbc 1\nldbc 1\nand\npop\n```\n\n### Shift\n\n```coffeescript\ndci32 4\ndci32 16\n\nv_int32 var_01\n\nldi32c 1\nstore var_01\n\nldi32c 0\nldi32v var_01\nshl # left shift var_01 (16) by 4\nstore var_01 # assign shift result to var_01\n\nldi32v var_01\nsyscall 0x10 # print var_01\n```\n\n### Pointers\n\nA pointer can either contain the address of a jump label, the address of a function or the address of a variable. Functions are called with `call` while labels are called with `jmp`.\n\n### Pointer to function label\n\n```coffeescript\ndcsa \"Hello world\"\n\nprint:\n    syscall 0x10\n    ret\n\nv_ptr print_ptr\nldptr print # loads the function ptr\nstore print_ptr\n\nldsac 0\ncall [print_ptr] # calls the function at the address of print_ptr\n```\n\n### Pointer to label\n\n```coffeescript\ndcsa \"Hello\"\n\nloop:\nldsac 0\nsyscall 0x10\n\nv_ptr loop_ptr\nldptr loop\nstore loop_ptr\n\njmp [loop_ptr]\n```\n\n### Pointer to variable\n\n```coffeescript\ndci32 42\n\nv_int32 var0\nldi32c 0\nstore var0\n\nv_ptr var0_ptr\nldptr var0\nstore var0_ptr\n\nldi32v [var0_ptr]\nsyscall 0x10\n```\n\n### Fixed address pointer\n\n```coffeescript\ndci8 0x10\n\nv_ptr print\nldi8c 0\nstore print\n\nsyscall [print]\n```\n\n## Functions\n\n```coffeescript\nv_int32 status\nv_stringa text\n\ncall return_status_and_text\n\nstore status\nstore text\n\n# status and text now have values returned by function_that_returns_status_and_text\n```\n\n```coffeescript\nreturn_status_and_text:\n    ...\n    ldi32v return_status\n    ldsav return_text\n    \n    ret\n```\n\n## Creating arrays\n\n```coffeescript\ndci32 2\n\nv_int32 var0\nv_int32 var1\nv_int32 var2\nv_int32 var3\nv_int32 var4\n\n...\n\nv_ptr arr_ptr\nldptr var0\nstore arr_ptr # arr_ptr is 0x0\n\nldptrv arr_ptr\nldi32c 0\nadd\nstore arr_ptr # arr_ptr is 0x2\n\nldi32v [arr_ptr] # load var2 onto stack\nsyscall 0x10\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazer0s%2Fpersephone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazer0s%2Fpersephone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazer0s%2Fpersephone/lists"}