Skip to content

Instantly share code, notes, and snippets.

@dkaraush
Created December 2, 2025 03:13
Show Gist options
  • Select an option

  • Save dkaraush/ca0daa96b11902a81fb4e1fcda5cfaf0 to your computer and use it in GitHub Desktop.

Select an option

Save dkaraush/ca0daa96b11902a81fb4e1fcda5cfaf0 to your computer and use it in GitHub Desktop.
(module
(import "sys" "open" (func $open (param i32 i32 i32 i32) (result i32)))
(import "sys" "close" (func $close (param i32)))
(import "sys" "read" (func $read (param i32 i32 i32) (result i32)))
(import "sys" "write" (func $write (param i32 i32 i32) (result i32)))
(memory (export "memory") 1)
(data (i32.const 0) "input.txt")
(global $fd (mut i32) (i32.const 0)) ;; 4 bytes
(global $char_ptr i32 (i32.const 16)) ;; 1 byte
(global $num_ptr i32 (i32.const 17)) ;; 4 bytes
(global $num_str_ptr i32 (i32.const 24)) ;; 24 bytes
(func $read_char (result i32)
global.get $fd
global.get $char_ptr
i32.const 1
call $read
i32.const 0
i32.le_s
(if (result i32)
(then
i32.const 0
)
(else
global.get $char_ptr
i32.load
)
)
)
(func $print_char (param $char i32)
global.get $char_ptr
local.get $char
i32.store8
i32.const 1 ;; stdout
global.get $char_ptr
i32.const 1 ;; len
call $write
drop
)
(func $read_number (result i32)
(local $acc i32)
(block $break
(loop $loop
call $read_char
i32.const 48 ;; '0'
i32.lt_s
(if (then br $break))
global.get $char_ptr
i32.load
i32.const 57 ;; '9'
i32.gt_s
(if (then br $break))
;; acc *= 10
local.get $acc
i32.const 10
i32.mul
;; acc += (c - '0')
global.get $char_ptr
i32.load
i32.const 48
i32.sub
i32.add
local.set $acc
br $loop
)
)
local.get $acc
)
(func $print_number (param $num i32)
(local $end i32)
(local $start i32)
local.get $num
i32.eqz
(if (then
i32.const 48 ;; '0'
call $print_char
return
))
local.get $num
i32.const 0
i32.lt_s
(if (then
i32.const 45 ;; '-'
call $print_char
i32.const 0
local.get $num
i32.sub
local.set $num
))
global.get $num_str_ptr
i32.const 24
i32.add
local.tee $end
local.set $start
(block $break
(loop $loop
local.get $num
i32.eqz
br_if $break
local.get $start
i32.const -1
i32.add
local.tee $start
local.get $num
i32.const 10
i32.rem_u
i32.const 48
i32.add
i32.store8
local.get $num
i32.const 10
i32.div_u
local.set $num
br $loop
)
)
i32.const 1 ;; stdout
local.get $start ;; ptr
local.get $end ;; len = end - start
local.get $start
i32.sub
call $write
drop
)
(func (export "_start")
(local $char i32)
(local $dial i32)
(local $rotations i32)
(local $password1 i32)
(local $password2 i32)
i32.const 0
i32.const 9
i32.const 2
i32.const 0
call $open
global.set $fd
i32.const 50
local.set $dial
i32.const 0
local.tee $password1
local.set $password2
(block $break (loop $loop
call $read_char
local.tee $char
call $print_char
local.get $char
i32.eqz
(if (then
br $break
))
(block $break_char
local.get $char
i32.const 82
i32.eq
(if
(then
call $read_number
local.tee $rotations
call $print_number
(loop $loopR
local.get $dial
i32.const 99
i32.eq
(if (then
local.get $password2
i32.const 1
i32.add
local.set $password2
i32.const 82 ;; 'R'
call $print_char
i32.const 0
local.set $dial
) (else
local.get $dial
i32.const 1
i32.add
local.set $dial
))
local.get $rotations
i32.const 1
i32.sub
local.tee $rotations
i32.eqz
(if (then br $break_char))
br $loopR
)
)
(else
call $read_number
local.tee $rotations
call $print_number
(loop $loopL
local.get $dial
i32.const 1
i32.sub
local.tee $dial
i32.eqz
(if (then
local.get $password2
i32.const 1
i32.add
local.set $password2
i32.const 76 ;; 'L'
call $print_char
))
local.get $dial
i32.const 0
i32.lt_s
(if (then
local.get $dial
i32.const 100
i32.add
local.set $dial
))
local.get $rotations
i32.const 1
i32.sub
local.tee $rotations
i32.eqz
(if (then br $break_char))
br $loopL
)
)
)
)
local.get $dial
i32.eqz
(if (then
local.get $password1
i32.const 1
i32.add
local.set $password1
))
i32.const 32 ;; ' '
call $print_char
local.get $dial
call $print_number
i32.const 10 ;; '\n'
call $print_char
br $loop
) )
global.get $fd
call $close
local.get $password1
call $print_number
i32.const 32 ;; ' '
call $print_char
local.get $password2
call $print_number
)
)
#!/usr/bin/env node
import * as fs from 'fs'
import { resolve } from 'path'
if (!process.argv[2]) {
console.error(`Usage: node loader.js module.wasm`)
process.exit(1)
}
const wasmBytes = fs.readFileSync(resolve(process.argv[2]))
let memory
const module = await WebAssembly.compile(wasmBytes)
const instance = await WebAssembly.instantiate(module, { sys: {
open: (pathPtr, pathLen, flags, mode) =>
fs.openSync(
Buffer.from(memory.buffer, pathPtr, pathLen).toString('utf-8'),
flags,
mode >>> 0
),
close: (fd) =>
fs.closeSync(fd),
read: (fd, bufPtr, bufLen) =>
fs.readSync(fd, Buffer.from(memory.buffer, bufPtr, bufLen)),
write: (fd, bufPtr, bufLen) =>
fs.writeSync(fd, Buffer.from(memory.buffer, bufPtr, bufLen))
} })
memory = instance.exports.memory;
if (!memory) {
console.error(`WASM: module must export memory as "memory"`);
process.exit(1);
}
if (instance.exports._start) {
instance.exports._start();
} else if (instance.exports.main) {
instance.exports.main();
} else {
console.error(`WASM: No _start or main export found`);
process.exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment