From 77594f45f4d97efc60763a315d91286f77cb6662 Mon Sep 17 00:00:00 2001 From: IgorCielniak Date: Sun, 11 Jan 2026 19:26:39 +0100 Subject: [PATCH] rewritten 'sh' inside nob.sl from asm to l2 code, renamed strcpy to memcpy and put it in mem.sl --- nob.sl | 241 +++++++++++++++++++++++++------------------------- nob_test.sl | 2 +- stdlib/mem.sl | 27 ++++++ strconcat.sl | 46 +--------- 4 files changed, 151 insertions(+), 165 deletions(-) diff --git a/nob.sl b/nob.sl index 562fe5e..d678f45 100644 --- a/nob.sl +++ b/nob.sl @@ -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 ) -# Runs `/bin/sh -c ` and returns a waitpid-style exit code -# (WIFEXITED ? status>>8 : 128+signal). Returns neg errno on fork/exec failure. -:asm sh { - ; stack: cmd_len (TOS), cmd_addr (NOS) - push r15 ; preserve callee-saved - push r14 - push r13 - push rbx +# sh ( cmd_addr cmd_len -- exit_code | neg_errno ) +word sh + swap + >r # save cmd_addr + >r # save cmd_len - mov rbx, [r12] ; len - mov r13, [r12 + 8] ; addr (preserve across syscalls) - add r12, 16 ; pop args + r@ 1 + + dup >r # stash len+1 for munmap + alloc + dup 0 < if + rdrop + rdrop + rdrop + else + dup >r # remember buffer pointer + drop - mov r14, rbx ; len - inc r14 ; size = len + 1 + 3 rpick # src addr + 0 rpick # dst addr + swap + 2 rpick # len + memcpy - ; mmap buffer for C-string command - mov rax, 9 ; mmap - xor rdi, rdi ; NULL addr - mov rsi, r14 ; size - mov rdx, 3 ; PROT_READ | PROT_WRITE - mov r10, 34 ; MAP_PRIVATE | MAP_ANON - mov r8, -1 ; fd = -1 - xor r9, r9 ; offset = 0 - syscall - cmp rax, -4095 - jae .mmap_fail - mov r15, rax ; cmd buffer + 0 rpick + 2 rpick + + + 0 + c! - ; copy cmd into buffer and add NUL - mov rcx, rbx ; len - mov rdi, r15 ; dst - mov rsi, r13 ; src - rep movsb - mov byte [r15 + rbx], 0 + "/bin/sh" drop + 0 + mem + + ! + "-c" drop + 8 + mem + + ! + 0 rpick + 16 + mem + + ! + 0 + 24 + mem + + ! + 0 + 32 + mem + + ! - ; fork - mov rax, 57 ; fork - syscall - cmp rax, 0 - jl .fork_fail - cmp rax, 0 - 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 - mov rdi, 127 - mov rax, 60 ; exit - syscall - -.parent: - ; rax holds child pid - mov rbx, rax ; child pid - sub rsp, 8 - lea rsi, [rsp] ; status* - xor rdx, rdx ; options = 0 - xor r10, r10 ; rusage = NULL - mov rdi, rbx ; pid - mov rax, 61 ; wait4 - syscall - mov eax, [rsp] - add rsp, 8 - - ; decode exit status: if signaled -> 128+signal, else (status >> 8) & 0xff - mov ebx, eax - and ebx, 0x7f - cmp ebx, 0 - jne .got_signal - shr eax, 8 - and eax, 0xff - jmp .status_ready -.got_signal: - mov eax, ebx - add eax, 128 -.status_ready: - mov edi, eax ; save for return after unmap - - ; munmap command buffer - mov rax, 11 ; munmap - mov rdi, r15 ; addr - mov rsi, r14 ; size - syscall - - mov eax, edi - sub r12, 8 - mov [r12], rax - pop rbx - pop r13 - 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 -} -; + syscall.fork + syscall + dup 0 < if + >r + 1 rpick + 2 rpick + free + r> + rdrop + rdrop + rdrop + rdrop + else + dup 0 == if + drop + "/bin/sh" drop + mem + dup + 32 + + syscall.execve + syscall + drop + 127 + syscall.exit + syscall + else + mem + 40 + + dup >r + 0 + 0 + syscall.wait4 + syscall + dup 0 < if + >r + rdrop + 1 rpick + 2 rpick + free + r> + rdrop + rdrop + rdrop + rdrop + else + drop + 0 rpick + @ + rdrop + dup + 128 % + dup 0 != if + swap drop + 128 + + else + drop + 256 / + end + >r + 1 rpick + 2 rpick + free + r> + rdrop + rdrop + rdrop + rdrop + end + end + end + end +end diff --git a/nob_test.sl b/nob_test.sl index ec735ac..92d037c 100644 --- a/nob_test.sl +++ b/nob_test.sl @@ -1,5 +1,5 @@ import nob.sl word main - "echo gg" sh + "ls" sh end \ No newline at end of file diff --git a/stdlib/mem.sl b/stdlib/mem.sl index 7bc895f..a26d28e 100644 --- a/stdlib/mem.sl +++ b/stdlib/mem.sl @@ -12,4 +12,31 @@ end word free munmap drop +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 \ No newline at end of file diff --git a/strconcat.sl b/strconcat.sl index 5e5bb25..b52dc34 100644 --- a/strconcat.sl +++ b/strconcat.sl @@ -1,4 +1,5 @@ import stdlib/stdlib.sl +import stdlib/mem.sl import stdlib/io.sl word strconcat @@ -9,11 +10,11 @@ word strconcat alloc r> r> dup >r - strcpy + memcpy swap r> dup -rot + r> r> - strcpy + memcpy swap 3 pick - @@ -27,47 +28,6 @@ word strconcat rdrop rdrop rdrop 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 "hello world hello world hello " "world hello world hello world" strconcat