File: nil-linux-amd64.asm
   1 ; The MIT License (MIT)
   2 ;
   3 ; Copyright (c) 2026 pacman64
   4 ;
   5 ; Permission is hereby granted, free of charge, to any person obtaining a copy
   6 ; of this software and associated documentation files (the "Software"), to deal
   7 ; in the Software without restriction, including without limitation the rights
   8 ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   9 ; copies of the Software, and to permit persons to whom the Software is
  10 ; furnished to do so, subject to the following conditions:
  11 ;
  12 ; The above copyright notice and this permission notice shall be included in
  13 ; all copies or substantial portions of the Software.
  14 ;
  15 ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 ; SOFTWARE.
  22 
  23 
  24 ; To compile this app for linux/amd64, use the commands
  25 ;
  26 ; nasm -f elf64 -o nil-linux-amd64.o nil-linux-amd64.asm
  27 ; ld -n -s nil-linux-amd64.o -o nil
  28 ; rm nil-linux-amd64.o
  29 
  30 
  31 ; nil [options...]
  32 ;
  33 ; Emit nothing, while also discarding all bytes from the standard input, if
  34 ; data are being piped into it.
  35 ;
  36 ; Options, also with optional leading single or double dash
  37 ;
  38 ;    h, help    show this help message
  39 
  40 
  41 stdin equ 0
  42 statbuf_size equ 32
  43 chunk_max_size equ 32 * 1024
  44 
  45 stdout equ 1
  46 sys_read equ 0
  47 sys_write equ 1
  48 sys_fstat equ 5
  49 sys_exit equ 60
  50 
  51 lf equ 10 ; line feed
  52 
  53 section .rodata
  54 
  55 info:
  56     db 'nil [options...]', lf
  57     db lf
  58     db 'Emit nothing, while also discarding all bytes from the standard '
  59     db 'input, if', lf
  60     db 'data are being piped into it.', lf
  61     db lf
  62     db 'Options, also with optional leading single or double dash', lf
  63     db lf
  64     db '    h, help    show this help message', lf
  65 info_length equ $ - info
  66 
  67 section .text
  68 
  69 global _start
  70 
  71 _start:
  72 
  73 ; rcx = argc
  74 pop rcx
  75 
  76 cmp rcx, 1
  77 je no_args
  78 
  79 ; skip argv[0]
  80 pop rbx
  81 ; get argv[1]
  82 pop rbx
  83 
  84 ; check/skip (optional) leading dash
  85     mov al, [rbx + 0]
  86     cmp al, '-'
  87     jne no_dashes
  88     inc rbx
  89 ; check/skip (optional) second leading dash
  90     mov al, [rbx + 0]
  91     cmp al, '-'
  92     jne single_dash
  93     inc rbx
  94 single_dash:
  95 no_dashes:
  96 ; check letter 'h'
  97     mov al, [rbx + 0]
  98     cmp al, 'h'
  99     jne no_args
 100 ; check null byte: `h` is a valid help-option
 101     mov al, [rbx + 1]
 102     cmp al, 0
 103     je help
 104 ; check letter 'e'
 105     mov al, [rbx + 1]
 106     cmp al, 'e'
 107     jne no_args
 108 ; check letter 'l'
 109     mov al, [rbx + 2]
 110     cmp al, 'l'
 111     jne no_args
 112 ; check letter 'p'
 113     mov al, [rbx + 3]
 114     cmp al, 'p'
 115     jne no_args
 116 ; check null byte: `help` is also a valid help-option
 117     mov al, [rbx + 4]
 118     cmp al, 0
 119     je help
 120 
 121 no_args:
 122 
 123 sub rsp, statbuf_size
 124 
 125 ; fstat(stdin, stat = rsp)
 126     mov rax, sys_fstat
 127     mov rdi, stdin
 128     mov rsi, rsp
 129     syscall
 130 
 131 cmp rax, 0
 132 jne fail
 133 
 134 mov al, [rsp+8]
 135 cmp al, 3
 136 jne piped
 137 
 138 add rsp, statbuf_size
 139 
 140 quit:
 141     ; exit(0)
 142     mov rax, sys_exit
 143     mov rdi, 0
 144     syscall
 145 
 146 fail:
 147     ; exit(1)
 148     mov rax, sys_exit
 149     mov rdi, 1
 150     syscall
 151 
 152 piped:
 153 
 154 add rsp, statbuf_size
 155 sub rsp, chunk_max_size
 156 mov rbx, rsp
 157 
 158 discard_stdin:
 159     push rbx
 160 
 161     ; read(stdin, buf = rbx, size = chunk_max_size)
 162         mov rax, sys_read
 163         mov rdi, stdin
 164         mov rsi, rbx
 165         mov rdx, chunk_max_size
 166         syscall
 167 
 168     pop rbx
 169 
 170     cmp rax, -1
 171     je fail
 172     cmp rax, 0
 173     je quit
 174 
 175     jmp discard_stdin
 176 
 177 help:
 178     ; write(stdout, info, info_length)
 179     mov rax, sys_write
 180     mov rdi, stdout
 181     mov rsi, info
 182     mov rdx, info_length
 183     syscall
 184 
 185     jmp quit