東大版Palo Alto Tiny BASICをamd64環境に移植してみるため、出力ルーチンが出来たので、引き続き入力ルーチンも書いてみました。WSL2のUbuntuを使っていますが、端末をRAWモードに設定する必要があります。プログラムを動かす前にsttyで設定を変えておくことにして、プログラム内部ではロジックを組みません。
オリジナルの入力ルーチンは次のようになっています。
GET: IN IFLG
NOP
ANI IMSK
RZ
IN ITTY
ANI 7FH
CPI 0FH
JNZ TTYI2
LDA OMASK
CMA
STA OMASK
JMP GET
TTYI2: CPI 03H
JZ START
RET
Geminiに教えてもらいながら、入力ルーチンを書いてみました。動作確認には、既にできている出力ルーチンを使いました。
# as get.s -o get.o
# ld get.o -o get
# stty raw -echo ; ./get ; stty sane
.intel_syntax noprefix
.global _start
.equ CTRL_C, 0x03
.equ CTRL_O, 0x0F
.equ CR, 0x0D
.equ LF, 0x0A
.equ SYS_READ, 0
.equ SYS_WRITE, 1
.equ SYS_IOCTL, 16
.equ STDIN, 0
.equ STDOUT, 1
.equ TC_MAGIC, 'T'
.equ FIONREAD_CMD, 27
.equ FIONREAD, (TC_MAGIC << 8) | FIONREAD_CMD
.equ OMASK_TOGGLE, 0x01
_start: call get
call put
jmp _start
done:
# プログラム終了 (sys_exit = 60)
mov rax, 60 # システムコール番号 (sys_exit)
xor rdi, rdi # 第1引数: 終了ステータスコード (0)
syscall # Linuxカーネル呼び出し
put: cmp byte ptr [rip+omask],0
jne ttyo0
ret
ttyo0: cmp al,CR
jne ttyo1
call ttyo1
push rax
mov al,LF
call ttyo1
pop rax
ret
ttyo1: push rax
mov rax,SYS_WRITE
mov rdi,STDOUT
lea rsi,[rsp]
mov rdx,1
syscall
pop rax
ret
get: push rbp
mov rbp,rsp
sub rsp,16
mov rax,SYS_IOCTL
mov rdi,STDIN
mov rsi,FIONREAD
lea rdx,[rbp-4]
syscall
test eax,eax
js ttyi8
cmp dword ptr [rbp-4],0
jz ttyi8
ttyi1: mov rax,SYS_READ
mov rdi,STDIN
lea rsi,[rbp-5]
mov rdx,1
syscall
cmp rax,1
jl ttyi8
movzx eax,byte ptr [rbp-5]
cmp al,CTRL_O
jne ttyi2
xor byte ptr [rip+omask],OMASK_TOGGLE
mov rsp,rbp
pop rbp
jmp get
ttyi2: cmp al,CTRL_C
je done
jmp ttyi9
ttyi8: xor eax,eax
ttyi9: mov rsp,rbp
pop rbp
ret
.data
omask: .byte 1 # 出力フラグ(0: 出力抑制 / 0以外: 出力許可)
0 件のコメント:
コメントを投稿