128 lines
3.5 KiB
Text
128 lines
3.5 KiB
Text
(module
|
|
(import "wasi_unstable" "fd_read"
|
|
(func $fd_read (param i32 i32 i32 i32) (result i32)))
|
|
(import "wasi_unstable" "fd_write"
|
|
(func $fd_write (param i32 i32 i32 i32) (result i32)))
|
|
(import "wasi_unstable" "random_get"
|
|
(func $random_get (param i32 i32) (result i32)))
|
|
|
|
(memory 1) (export "memory" (memory 0))
|
|
;; memory usage:
|
|
;; 0-7: temp IO Vector used with WASI functions
|
|
;; 8-24: temp buffer used for reading numbers
|
|
;; 100-: string data
|
|
|
|
;; string constants
|
|
(data (i32.const 100) "Guess a number between 1 and 10.\n")
|
|
(data (i32.const 200) "Well guessed!\n")
|
|
|
|
;; function to print a null-terminated string at the given address
|
|
;; (assumes use of an IOVector at address 0)
|
|
(func $print_cstr (param $strAddr i32)
|
|
(local $charPos i32)
|
|
|
|
;; store the data address into our IO vector (address 0)
|
|
i32.const 0 local.get $strAddr i32.store
|
|
|
|
;; find the null terminator at the end of the string
|
|
local.get $strAddr local.set $charPos
|
|
block $loop_break
|
|
loop $LOOP
|
|
;; get the character at charPos
|
|
local.get $charPos i32.load
|
|
;; if it is equal to zero, break out of the loop
|
|
i32.eqz if br $loop_break end
|
|
;; otherwise, increment and loop
|
|
local.get $charPos i32.const 1 i32.add local.set $charPos
|
|
br $LOOP
|
|
end
|
|
end
|
|
|
|
;; from that, compute the length of the string for our IOVector
|
|
i32.const 4 ;; (address of string length in the IOVector)
|
|
local.get $charPos local.get $strAddr i32.sub
|
|
i32.store
|
|
|
|
;; now call $fd_write to actually write to stdout
|
|
i32.const 1 ;; 1 for stdout
|
|
i32.const 0 i32.const 1 ;; 1 IOVector at address 0
|
|
i32.const 0 ;; where to stuff the number of bytes written
|
|
call $fd_write
|
|
drop ;; (drop the result value)
|
|
)
|
|
|
|
;; function to read a number
|
|
;; (assumes use of an IOVector at address 0,
|
|
;; and 16-character buffer at address 8)
|
|
(func $input_i32 (result i32)
|
|
(local $ptr i32)
|
|
(local $n i32)
|
|
(local $result i32)
|
|
|
|
;; prepare our IOVector to point to the buffer
|
|
i32.const 0 i32.const 8 i32.store ;; (address of buffer)
|
|
i32.const 4 i32.const 16 i32.store ;; (size of buffer)
|
|
|
|
i32.const 0 ;; 0 for stdin
|
|
i32.const 0 i32.const 1 ;; 1 IOVector at address 0
|
|
i32.const 4 ;; where to stuff the number of bytes read
|
|
call $fd_read drop
|
|
|
|
;; Convert that to a number!
|
|
;; loop over characters in the string until we hit something < '0'.
|
|
i32.const 8 local.set $ptr
|
|
block $LOOP_BREAK
|
|
loop $LOOP
|
|
;; get value of current digit
|
|
;; (we assume all positive integers for this task)
|
|
local.get $ptr i32.load8_u
|
|
i32.const 48 i32.sub ;; (subtract 48, ASCII value of '0')
|
|
local.tee $n
|
|
|
|
;; bail out if < 0
|
|
i32.const 0 i32.lt_s br_if $LOOP_BREAK
|
|
|
|
;; multiply current number by 10, and add new number
|
|
local.get $result i32.const 10 i32.mul
|
|
local.get $n i32.add
|
|
local.set $result
|
|
|
|
;; increment and loop
|
|
local.get $ptr i32.const 1 i32.add local.set $ptr
|
|
br $LOOP
|
|
end
|
|
end
|
|
|
|
local.get $result
|
|
)
|
|
|
|
;; function to get a random i32
|
|
;; (assumes use of temporary space at address 0)
|
|
(func $random_i32 (result i32)
|
|
i32.const 0 i32.const 4 call $random_get drop
|
|
i32.const 0 i32.load
|
|
)
|
|
|
|
(func $main (export "_start")
|
|
(local $trueNumber i32)
|
|
|
|
;; get a random integer, then take that (unsigned) mod 10
|
|
call $random_i32 i32.const 10 i32.rem_u
|
|
local.set $trueNumber
|
|
|
|
loop $LOOP
|
|
;; print prompt
|
|
i32.const 100 call $print_cstr
|
|
|
|
;; input a guess
|
|
call $input_i32
|
|
|
|
;; if correct, print message and we're done
|
|
local.get $trueNumber i32.eq if
|
|
i32.const 200 call $print_cstr
|
|
return
|
|
end
|
|
br $LOOP
|
|
end
|
|
)
|
|
)
|