Implement the RNG for word selection

This commit is contained in:
Juhani Krekelä 2022-02-24 21:14:37 +02:00
parent b7e010e5ac
commit b000857bb4
2 changed files with 305 additions and 4 deletions

281
dosdl.asm
View File

@ -5,11 +5,36 @@ org 0x100
section .code
select_target:
; TODO: Implement target word selection
; https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
mov si, 1397
seed equ 20220224
; Seed the rng
mov ax, seed & 0xffff
mov dx, seed >> 16
mov bp, rng_seed
call store32
select_target:
; Call rng to get a number
call rng
mov bp, rng_output
call store32
; Multiply rng output by number of targer words
xor si, si
xor dx, dx
xor ax, ax
mov cx, targets_len
.multiply_loop:
add ax, [rng_output + 0]
adc dx, [rng_output + 2]
adc si, 0
loop .multiply_loop
mov ax, si
call hexprint16
call newline
load_target:
shl si, 1
shl si, 1
add si, targets
@ -18,6 +43,11 @@ select_target:
call unpack_target
; Figure out whether this is a removed word
; If so, reroll target word
cmp byte [target], '{'
je select_target
read_guess:
; Number of thus far guessed letters stored in bx
xor bx, bx
@ -428,6 +458,237 @@ unpack_target:
ret
; out:
; dx:ax = result
rng:
; https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
; rng_t = rng_seed += rng_seed + 0x6d2b79f5
mov bp, rng_seed
call load32
add ax, 0x79f5
adc dx, 0x6d2b
call store32
mov bp, rng_t
call store32
; xorl32 = rng_t
mov bp, xorl32
call store32
; xorr32 = rng_t >> 15
mov cx, 15
call rshift32
mov bp, xorr32
call store32
; mull32 = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 15)
call xor32
mov bp, mull32
call store32
; mulr32 = rng_t | 1
mov bp, rng_t
call load32
or ax, 1
mov bp, mulr32
call store32
; rng_t = mull32 * mulr32 = (rng_t ^ (rng_t >> 15)) * (rng_t | 1)
call mul32
mov bp, rng_t
call store32
; xorl32 = rng_t
mov bp, xorl32
call store32
; xorr32 = rng_t >> 7
mov cx, 7
call rshift32
mov bp, xorr32
call store32
; mull32 = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 7)
call xor32
mov bp, mull32
call store32
; mulr32 = rng_t | 61
mov bp, rng_t
call load32
or ax, 61
mov bp, mulr32
call store32
; addl32 = rng_t
mov bp, rng_t
call load32
mov bp, addl32
call store32
; addr32 = mull32 * mulr32 = (rng_t ^ (rng_t >> 7)) * (rng_t | 61)
call mul32
mov bp, addr32
call store32
; xorl32 = rng_t
mov bp, rng_t
call load32
mov bp, xorl32
call store32
; xorr32 = addl32 + addr32 = rng_t + (rng_t ^ (rng_t >> 7)) * (rng_t | 61)
call add32
mov bp, xorr32
call store32
; rng_t = xorl32 ^ xorr32 = rng_t ^ (rng_t + (rng_t ^ (rng_t >> 7)) * (rng_t | 61))
call xor32
mov bp, rng_t
call store32
; xorl32 = rng_t
mov bp, xorl32
call store32
; xorr32 = rng_t >> 14
mov cx, 14
call rshift32
mov bp, xorr32
call store32
; result = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 14)
call xor32
ret
; in:
; bp = address of uint32
; out:
; dx = high 16 bits
; ax = low 16 bits
load32:
mov ax, [bp + 0]
mov dx, [bp + 2]
ret
; in:
; bp = address of uint32
; dx = high 16 bits
; ax = low 16 bits
store32:
mov [bp + 0], ax
mov [bp + 2], dx
ret
; in:
; dx:ax = uint32 to be shifted
; cx = shift amount (must not be 0)
; out:
; dx:ax = result
rshift32:
push cx
.loop:
shr dx, 1
rcr ax, 1
loop .loop
pop cx
ret
; in:
; [xorl32], [xorr32] = operands
; out:
; dx:ax = result
xor32:
mov ax, [xorl32 + 0]
xor ax, [xorr32 + 0]
mov dx, [xorl32 + 2]
xor dx, [xorr32 + 2]
ret
; in:
; [mull32], [mulr32] = operands
; out:
; dx:ax = result
mul32:
push bx
push cx
; c = 1<<16
; l = l₁<<16 + l₀
; r = r₁<<16 + r₀
; l·r = (l₁<<16 + l₀)·(r₁<<16 + r₀)
; = l₁<<16·r₁<<16 + l₁<<16·r₀ + l₀·r₁<<16 + l₀·r₀
; = l₁·r₁<<32 + l₁·r₀<<16 + l₀·r₁<<16 + l₀·r₀ ||1<<32 = 0 (mod 1<<32)
; = l₁·r₀<<16 + l₀·r₁<<16 + l₀·r₀
; l₀·r₀
mov ax, [mull32 + 0]
mul word [mulr32 + 0]
mov bx, ax
mov cx, dx
; l₀·r₁<<16
mov ax, [mull32 + 0]
mul word [mulr32 + 2]
add cx, ax
; l₁·r₀<<16
mov ax, [mull32 + 2]
mul word [mulr32 + 0]
add cx, ax
mov dx, cx
mov ax, bx
pop cx
pop bx
ret
; in:
; [addl32], [addr32] = operands
; out:
; dx:ax = result
add32:
mov ax, [addl32 + 0]
mov dx, [addl32 + 2]
add ax, [addr32 + 0]
adc dx, [addr32 + 2]
ret
hexprint32:
xchg ax, dx
call hexprint16
xchg ax, dx
hexprint16:
xchg ah, al
call hexprint8
xchg ah, al
hexprint8:
%rep 4
rol al, 1
%endrep
call hexprint4
%rep 4
rol al, 1
%endrep
hexprint4:
push ax
and al, 0xf
cmp al, 10
jb .digit09
add al, 'a' - 10 - '0'
.digit09:
add al, '0'
mov ah, 0xe
int 0x10
pop ax
ret
section .data
target times 5 db 0
guess times 5 db 0
@ -439,6 +700,18 @@ guesses db 0
dictionary_entry times 5 db 0
rng_seed dd 0
rng_t dd 0
rng_output dd 0
xorl32 dd 0
xorr32 dd 0
mull32 dd 0
mulr32 dd 0
addl32 dd 0
addr32 dd 0
section .rodata
not_found_str db ' - word not found$'

28
word_selection.py Normal file
View File

@ -0,0 +1,28 @@
import json
import sys
# https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
def rshift(n, a): return (n & 0xffff_ffff) >> a
def mulberry32(rng_state):
def worker():
nonlocal rng_state
rng_state += 0x6d2b79f5;
t = rng_state
t = (t ^ rshift(t, 15)) * (t | 1) & 0xffff_ffff
t ^= t + (t ^ rshift(t, 7)) * (t | 61) & 0xffff_ffff
return (t ^ (t >> 14))
return worker
with open('targets.json', 'r') as f:
targets = json.load(f)
targets = targets[:targets.index('murky') + 1]
targets = [i for i in targets if len(i) == 5]
rng = mulberry32(int(sys.argv[1]))
while True:
num = rng()
index = num * len(targets) >> 32
print(f'{num:08x}', index, targets[index])
if targets[index] != '*****': break