rewritten 'sh' inside nob.sl from asm to l2 code, renamed strcpy to memcpy and put it in mem.sl

This commit is contained in:
IgorCielniak
2026-01-11 19:26:39 +01:00
parent 8139aa66d9
commit 77594f45f4
4 changed files with 151 additions and 165 deletions

237
nob.sl
View File

@@ -1,127 +1,126 @@
# Minimal nob-style helper: run a shell command via /bin/sh -c import stdlib/stdlib.sl
import stdlib/linux.sl
import stdlib/mem.sl
# : sh ( cmd_addr cmd_len -- exit_code ) # sh ( cmd_addr cmd_len -- exit_code | neg_errno )
# Runs `/bin/sh -c <cmd>` and returns a waitpid-style exit code word sh
# (WIFEXITED ? status>>8 : 128+signal). Returns neg errno on fork/exec failure. swap
:asm sh { >r # save cmd_addr
; stack: cmd_len (TOS), cmd_addr (NOS) >r # save cmd_len
push r15 ; preserve callee-saved
push r14
push r13
push rbx
mov rbx, [r12] ; len r@ 1 +
mov r13, [r12 + 8] ; addr (preserve across syscalls) dup >r # stash len+1 for munmap
add r12, 16 ; pop args alloc
dup 0 < if
rdrop
rdrop
rdrop
else
dup >r # remember buffer pointer
drop
mov r14, rbx ; len 3 rpick # src addr
inc r14 ; size = len + 1 0 rpick # dst addr
swap
2 rpick # len
memcpy
; mmap buffer for C-string command 0 rpick
mov rax, 9 ; mmap 2 rpick
xor rdi, rdi ; NULL addr +
mov rsi, r14 ; size 0
mov rdx, 3 ; PROT_READ | PROT_WRITE c!
mov r10, 34 ; MAP_PRIVATE | MAP_ANON
mov r8, -1 ; fd = -1 "/bin/sh" drop
xor r9, r9 ; offset = 0 0
mem +
!
"-c" drop
8
mem +
!
0 rpick
16
mem +
!
0
24
mem +
!
0
32
mem +
!
syscall.fork
syscall syscall
cmp rax, -4095 dup 0 < if
jae .mmap_fail >r
mov r15, rax ; cmd buffer 1 rpick
2 rpick
; copy cmd into buffer and add NUL free
mov rcx, rbx ; len r>
mov rdi, r15 ; dst rdrop
mov rsi, r13 ; src rdrop
rep movsb rdrop
mov byte [r15 + rbx], 0 rdrop
else
; fork dup 0 == if
mov rax, 57 ; fork drop
"/bin/sh" drop
mem
dup
32 +
syscall.execve
syscall syscall
cmp rax, 0 drop
jl .fork_fail 127
cmp rax, 0 syscall.exit
jne .parent
.child:
; child: argv = "/bin/sh" "-c" cmd NULL
sub rsp, 56
lea rbx, [rel .sh_path]
mov [rsp], rbx ; argv[0]
lea rbx, [rel .dash_c]
mov [rsp + 8], rbx ; argv[1]
mov [rsp + 16], r15 ; argv[2]
mov qword [rsp + 24], 0 ; argv[3] = NULL
lea rsi, [rsp] ; argv
mov qword [rsp + 32], 0 ; envp[0] = NULL
lea rdx, [rsp + 32] ; envp
lea rdi, [rel .sh_path] ; filename
mov rax, 59 ; execve
syscall syscall
mov rdi, 127 else
mov rax, 60 ; exit mem
40 +
dup >r
0
0
syscall.wait4
syscall syscall
dup 0 < if
.parent: >r
; rax holds child pid rdrop
mov rbx, rax ; child pid 1 rpick
sub rsp, 8 2 rpick
lea rsi, [rsp] ; status* free
xor rdx, rdx ; options = 0 r>
xor r10, r10 ; rusage = NULL rdrop
mov rdi, rbx ; pid rdrop
mov rax, 61 ; wait4 rdrop
syscall rdrop
mov eax, [rsp] else
add rsp, 8 drop
0 rpick
; decode exit status: if signaled -> 128+signal, else (status >> 8) & 0xff @
mov ebx, eax rdrop
and ebx, 0x7f dup
cmp ebx, 0 128 %
jne .got_signal dup 0 != if
shr eax, 8 swap drop
and eax, 0xff 128 +
jmp .status_ready else
.got_signal: drop
mov eax, ebx 256 /
add eax, 128 end
.status_ready: >r
mov edi, eax ; save for return after unmap 1 rpick
2 rpick
; munmap command buffer free
mov rax, 11 ; munmap r>
mov rdi, r15 ; addr rdrop
mov rsi, r14 ; size rdrop
syscall rdrop
rdrop
mov eax, edi end
sub r12, 8 end
mov [r12], rax end
pop rbx end
pop r13 end
pop r14
pop r15
ret
.fork_fail:
mov rax, rax ; rax holds neg errno
jmp .cleanup_return
.mmap_fail:
mov rax, -12 ; -ENOMEM
.cleanup_return:
sub r12, 8
mov [r12], rax
pop rbx
pop r13
pop r14
pop r15
ret
.sh_path: db "/bin/sh", 0
.dash_c: db "-c", 0
}
;

View File

@@ -1,5 +1,5 @@
import nob.sl import nob.sl
word main word main
"echo gg" sh "ls" sh
end end

View File

@@ -13,3 +13,30 @@ end
word free word free
munmap drop munmap drop
end end
word memcpy #(dst_addr src_addr len -- dst_addr len)
dup
>r
swap
dup c@
3 pick swap
c!
drop
swap
for
1 + dup
c@
swap
-rot
swap
1 +
dup
rot
c!
drop
swap
end
swap
nip
r> dup -rot - swap
end

View File

@@ -1,4 +1,5 @@
import stdlib/stdlib.sl import stdlib/stdlib.sl
import stdlib/mem.sl
import stdlib/io.sl import stdlib/io.sl
word strconcat word strconcat
@@ -9,11 +10,11 @@ word strconcat
alloc alloc
r> r> r> r>
dup >r dup >r
strcpy memcpy
swap swap
r> dup -rot + r> dup -rot +
r> r> r> r>
strcpy memcpy
swap swap
3 pick 3 pick
- -
@@ -27,47 +28,6 @@ word strconcat
rdrop rdrop rdrop rdrop rdrop rdrop
end end
word alloc
0 # addr hint (NULL)
swap # size
3 # prot (PROT_READ | PROT_WRITE)
34 # flags (MAP_PRIVATE | MAP_ANON)
-1 # fd
0 # offset
mmap
end
word free
munmap drop
end
word strcpy #(dst_addr src_addr len -- dst_addr len)
dup
>r
swap
dup c@
3 pick swap
c!
drop
swap
for
1 + dup
c@
swap
-rot
swap
1 +
dup
rot
c!
drop
swap
end
swap
nip
r> dup -rot - swap
end
word main word main
"hello world hello world hello " "world hello world hello world" "hello world hello world hello " "world hello world hello world"
strconcat strconcat