1 ; **************************************************************************** 2 ; cat386.s (Retro Unix 386 v1) - /bin/cat - concatenate files 3 ; ---------------------------------------------------------------------------- 4 ; 5 ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix) 6 ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013) 7 ; 8 ; Retro UNIX 8086 v1 - '/bin/cat' file 9 ; 10 ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 11 ; (v0.1 - Beginning: 11/07/2012) 12 ; 13 ; [ Last Modification: 05/03/2022 ] -cat1.s- 14 ; 15 ; Derived from UNIX Operating System (v1.0 for PDP-11) 16 ; (Original) Source Code by Ken Thompson (Bell Laboratories, 1971-1972) 17 ; **************************************************************************** 18 ; ((nasm cat1.s -l cat1.txt -o cat1 -Z error.txt)) 19 ; cat386.s - cat1.s (05/03/2022, Retro UNIX 386 v1 & v1.1 & v1.2) 20 ; cat386.s - cat0.s (17/10/2015 - 28/12/2015, Retro UNIX 386 v1, NASM 2.11) 21 ; CAT2.ASM (02/12/2013 - 16/07/2015, Retro UNIX 8086 v1, MASM 6.11) 22 23 ; 17/10/2015 24 25 ; UNIX v1 system calls 26 _rele equ 0 27 _exit equ 1 28 _fork equ 2 29 _read equ 3 30 _write equ 4 31 _open equ 5 32 _close equ 6 33 _wait equ 7 34 _creat equ 8 35 _link equ 9 36 _unlink equ 10 37 _exec equ 11 38 _chdir equ 12 39 _time equ 13 40 _mkdir equ 14 41 _chmod equ 15 42 _chown equ 16 43 _break equ 17 44 _stat equ 18 45 _seek equ 19 46 _tell equ 20 47 _mount equ 21 48 _umount equ 22 49 _setuid equ 23 50 _getuid equ 24 51 _stime equ 25 52 _quit equ 26 53 _intr equ 27 54 _fstat equ 28 55 _emt equ 29 56 _mdate equ 30 57 _stty equ 31 58 _gtty equ 32 59 _ilgins equ 33 60 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 61 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 62 63 %macro sys 1-4 64 ; 03/09/2015 65 ; 13/04/2015 66 ; Retro UNIX 386 v1 system call. 67 %if %0 >= 2 68 mov ebx, %2 69 %if %0 >= 3 70 mov ecx, %3 71 %if %0 = 4 72 mov edx, %4 73 %endif 74 %endif 75 %endif 76 mov eax, %1 77 int 30h 78 %endmacro 79 80 ; Retro UNIX 386 v1 system call format: 81 ; sys systemcall (eax) , , 82 83 [BITS 32] ; We need 32-bit intructions for protected mode 84 85 [ORG 0] 86 87 START_CODE: 88 ;; / cat -- concatenate files 89 90 sys _write, 1, nl, 2 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 00000000 BB01000000 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 00000005 B9[04010000] <1> mov ecx, %3 71 <1> %if %0 = 4 72 0000000A BA02000000 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 0000000F B804000000 <1> mov eax, %1 77 00000014 CD30 <1> int 30h 91 92 00000016 5D pop ebp 93 00000017 5A pop edx 94 ; esi = 0 ; ('sysexec' sets regs to zero) 95 ; 05/03/2022 96 ;mov esi, fin 97 ;mov edi, obuf 98 ;EAX = 2 (written byte count) 99 00000018 30C0 xor al, al ; 0 100 0000001A 4D dec ebp 101 0000001B 745A jz short cat_3 102 ;;mov (sp)+,r5 103 ;;tst (sp)+ 104 ;;mov $obuf,r2 105 ;;cmp r5,$1 106 ;;beq 3f 107 cat_0: 108 0000001D 5B pop ebx 109 0000001E 803B2D cmp byte [ebx], '-' 110 00000021 7410 je short cat_2 111 ;;dec r5 112 ;;ble done 113 ;;mov (sp)+,r0 114 ;;cmpb (r0),$'- 115 ;;bne 2f 116 ;;clr fin 117 ;;br 3f 118 cat_1: 119 ;;2: 120 ; ebx = file name offset 121 00000023 31C9 xor ecx, ecx ; 0 122 sys _open 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 00000025 B805000000 <1> mov eax, %1 77 0000002A CD30 <1> int 30h 123 ;jc short cat_7 124 ; 05/03/2022 ; (+) 125 0000002C 7305 jnc short cat_2 126 0000002E E9BF000000 jmp cat_7 127 cat_2: 128 ; 05/03/2022 129 00000033 89C6 mov esi, eax 130 ;mov [esi], eax ; 05/03/2022 131 ;mov [esi], ax 132 ;;mov r0,0f 133 ;;sys open; 0:..; 0 134 ;;bes loop 135 ;;mov r0,fin 136 137 ; 05/03/2022 ; (+) 138 ; convert user's file number to inode number 139 ; (get 34 byte inode details, inode num + inode) 140 ; (get 66 byte inode details for runix 386 v1.2) 141 sys _fstat, esi, iobuf 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 00000035 89F3 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 00000037 B9[10010000] <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 0000003C B81C000000 <1> mov eax, %1 77 00000041 CD30 <1> int 30h 142 ;jc short cat_7 143 ; 05/03/2022 ; (+) 144 00000043 7305 jnc short cat_f 145 00000045 E9A8000000 jmp cat_7 146 cat_f: 147 ; 05/03/2022 ; (+) 148 ;;movzx edi, word [iobuf] ; inode number 149 ;movzx edi, word [ecx] ; inode number 150 ; edi = 0 ; ('sysexec' sets regs to zero) 151 0000004A 668B39 mov di, [ecx] 152 153 ; 05/03/2022 ; (+) 154 ; check against '/dev/tty' inode number 155 ;sys _stat, consoletty, iobuf 156 ; (get 34 byte inode details, inode num + inode) 157 ; (get 66 byte inode details for runix 386 v1.2) 158 ;mov ecx, iobuf 159 sys _stat, consoletty 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 0000004D BB[07010000] <1> mov ebx, %2 69 <1> %if %0 >= 3 70 <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 00000052 B812000000 <1> mov eax, %1 77 00000057 CD30 <1> int 30h 160 00000059 7207 jc short cat_x 161 162 ;movzx eax, word [iobuf] 163 0000005B 668B01 mov ax, [ecx] 164 0000005E 39C7 cmp edi, eax ; is it /dev/tty inode ? 165 00000060 7413 je short cat_y ; yes 166 ; no, it is not '/dev/tty' 167 cat_x: 168 ; 05/03/2022 ; (+) 169 ; get inode number of current tty (stdin) 170 ; (get 34 byte inode details, inode num + inode) 171 ; (get 66 byte inode details for runix 386 v1.2) 172 ;sys _fstat, 0, iobuf 173 ;;jc short cat_z 174 ;mov ecx, iobuf 175 sys _fstat, 0 ; get stdin file inode details 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 00000062 BB00000000 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 00000067 B81C000000 <1> mov eax, %1 77 0000006C CD30 <1> int 30h 176 177 ;movzx eax, word [iobuf] 178 0000006E 668B01 mov ax, [ecx] ; inode number 179 00000071 39C7 cmp edi, eax 180 00000073 7504 jne short cat_z ; (ebx = 0) 181 ; (/dev/tyy0 .. /dev/tty9) 182 cat_y: 183 ; same with input file inode 184 00000075 29F6 sub esi, esi ; 0 185 ; use console tty input (stdin) 186 cat_3: ;;3: 187 ; 05/03/2022 188 ;or eax, eax ; console tty input (stdin) ? 189 ;jnz short cat_r ; no.. 190 ; 191 ; get keyboard status of console tty 192 00000077 31DB xor ebx, ebx ; 0 193 cat_z: 194 00000079 31C9 xor ecx, ecx ; 0 195 sys _gtty 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 0000007B B820000000 <1> mov eax, %1 77 00000080 CD30 <1> int 30h 196 ;;sub eax, eax ; clear ax 197 ;mov eax, [esi] ; file descriptor/number 198 00000082 21DB and ebx, ebx ; is there a waiting char ? 199 ;jz short cat_3 ; no, wait for keystroke again 200 00000084 7506 jnz short cat_c ; (a char is waiting in buffer) 201 ;mov eax, [esi] 202 ;or eax, eax ; 0 ; console tty input ? 203 00000086 09F6 or esi, esi ; 05/03/2022 204 00000088 752D jnz short cat_r ; no, continue (to read file) 205 0000008A EBED jmp short cat_z ; yes, wait for keystroke again 206 cat_c: 207 ; 05/03/2022 208 ; read from console tty (stdin) 209 sys _read, 0, iobuf, 1 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 0000008C BB00000000 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 00000091 B9[10010000] <1> mov ecx, %3 71 <1> %if %0 = 4 72 00000096 BA01000000 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 0000009B B803000000 <1> mov eax, %1 77 000000A0 CD30 <1> int 30h 210 ; read one char into [iobuf] 211 000000A2 7241 jc short cat_6 ; (ebx = 0) 212 ;and eax, eax 213 ;jz short cat_6 214 000000A4 48 dec eax ; 1 -> 0 215 000000A5 753E jnz short cat_6 216 000000A7 40 inc eax 217 ; eax = 1 218 000000A8 8A1D[10010000] mov bl, [iobuf] ; ascii code of the character 219 000000AE 80FB1B cmp bl, 1Bh ; 27 ; ESCape key ? 220 000000B1 7447 je short cat_exit ; yes, exit 221 ;mov eax, [esi] ; file descriptor/number 222 ;or eax, eax ; 0 ; console_tty input ? 223 000000B3 09F6 or esi, esi ; 05/03/2022 224 000000B5 7419 jz short cat_w ; yes, write char to screen 225 cat_r: 226 ; 05/03/2022 227 ;mov eax, [esi] ; file descriptor/number 228 ;;mov ax, [esi] 229 ; 230 ;sys _read, eax, iobuf, 512 ; 16/07/2015 231 ;;sys _read, eax, ibuf, 512 232 ;jc short cat_6 233 ; 05/03/2022 234 ; esi = file descriptor/number 235 sys _read, esi, iobuf, 512 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 000000B7 89F3 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 000000B9 B9[10010000] <1> mov ecx, %3 71 <1> %if %0 = 4 72 000000BE BA00020000 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 000000C3 B803000000 <1> mov eax, %1 77 000000C8 CD30 <1> int 30h 236 ; read 512 chars into [iobuf] 237 ;jc short cat_6 238 000000CA 721D jc short cat_k ; 05/03/2022 239 240 ; NOTE: If input file is a tty (keyboard) 241 ; only 1 byte will be read, by ignoring 242 ; byte count (512). 243 ; Retro UNIX 8086 v1 kernel ('rtty') 244 ; has been modified fot that. 245 ; Erdogan Tan (16/07/2015) 246 ; 247 248 000000CC 21C0 and eax, eax ; EAX = 1 for tty (keyboard) 249 ;jz short cat_6 250 000000CE 7419 jz short cat_k ; 05/03/2022 251 252 ; push esi 253 ;mov esi, ibuf 254 ; mov esi, ecx ; offset ibuf 255 ; mov ecx, eax 256 ;;mov fin,r0 257 ;;sys read; ibuf; 512. 258 ;;bes 3f 259 ;;mov r0,r4 260 ;;beq 3f 261 ;;mov $ibuf,r3 262 ; 16/07/2015 263 ; mov edx, eax 264 ; ;add edx, obuf 265 ;cat_4: 266 ; ;;4: 267 ; lodsb 268 ;call putc 269 cat_w: 270 ; 16/07/2015 271 ; write to console tty (stdout) 272 sys _write, 1, iobuf, eax 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 000000D0 BB01000000 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 000000D5 B9[10010000] <1> mov ecx, %3 71 <1> %if %0 = 4 72 000000DA 89C2 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 000000DC B804000000 <1> mov eax, %1 77 000000E1 CD30 <1> int 30h 273 ;jc short cat_6 274 ; 05/03/2022 275 000000E3 7392 jnc short cat_3 276 ; 277 ; loop cat_4 278 ; pop esi 279 cat_5: 280 ;mov eax, [esi] ; 05/03/2022 281 ;;mov ax, [esi] 282 ;jmp short cat_3 283 ;;movb (r3)+,r0 284 ;;jsr pc,putc 285 ;;dec r4 286 ;;bne 4b 287 ;;br 3b 288 ;; 05/03/2022 289 ;; ebx = file descriptor/input 290 ;;and ebx, ebx ; console input ? 291 ;;jnz short cat_3 ; no, file input 292 ;;cmp byte [quit], al ; 0 293 ;;ja short cat_7 ; ebx = 0 294 ;;jmp short cat_z 295 ; 05/03/2022 296 ;jmp short cat_3 297 298 cat_6: ;;3: 299 ; 05/03/2022 300 ; ebx = file descriptor/number 301 ;movzx ebx, word [esi] 302 ; 303 000000E5 09F6 or esi, esi 304 000000E7 7409 jz short cat_7 305 cat_k: 306 sys _close, esi 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 000000E9 89F3 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 000000EB B806000000 <1> mov eax, %1 77 000000F0 CD30 <1> int 30h 307 ; 308 ;or ebx, ebx 309 ;jz short cat_7 310 ;sys _close 311 ;;mov fin,r0 312 ;;beq loop 313 ;;sys close 314 ;;br loop 315 cat_7: 316 ;;loop: 317 000000F2 4D dec ebp 318 ;;jz short cat_8 319 ; 28/12/2015 320 ;jg short cat_0 321 ; 05/03/2022 322 000000F3 7E05 jng short cat_exit 323 000000F5 E923FFFFFF jmp cat_0 324 cat_exit: 325 sys _exit 64 <1> 65 <1> 66 <1> 67 <1> %if %0 >= 2 68 <1> mov ebx, %2 69 <1> %if %0 >= 3 70 <1> mov ecx, %3 71 <1> %if %0 = 4 72 <1> mov edx, %4 73 <1> %endif 74 <1> %endif 75 <1> %endif 76 000000FA B801000000 <1> mov eax, %1 77 000000FF CD30 <1> int 30h 326 here: 327 00000101 90 nop 328 00000102 EBFD jmp short here 329 ;; 330 ;cat_8: 331 ; ;;done: 332 ; sub di, obuf 333 ; jz short cat_9 334 ; sys _write, 1, obuf, di 335 ;;sub $obuf,r2 336 ;;beq 1f 337 ;;mov r2,0f 338 ;;mov $1,r0 339 ;;sys write; obuf; 0:.. 340 ;cat_9: 341 ; ;;1: 342 ; sys _exit 343 ;;sys exit 344 ;; 345 ;putc: 346 ; ;;putc: 347 ; stosb 348 ; cmp di, dx ; 16/07/2015 349 ;cmp di, obuf + 512 350 ; jb short cat_10 351 ; push cx 352 ; 16/07/2015 353 ; mov di, obuf 354 ; sub dx, di ; byte (char) count 355 ; 356 ; sys _write, 1, obuf 357 ;sys _write, 1, obuf, 512 358 ;mov di, obuf 359 ;;movb r0,(r2)+ 360 ;;cmp r2,$obuf+512. 361 ;;blo 1f 362 ;;mov $1,r0 363 ;;sys write; obuf; 512. 364 ;;mov $obuf,r2 365 ; pop cx 366 ;cat_10: 367 ;;1: 368 ; retn 369 ;;rts pc 370 371 00000104 0D0A nl: db 0Dh, 0Ah ; , 0 372 ; 05/03/2022 373 00000106 00 quit: db 0 374 consoletty: 375 00000107 2F6465762F74747900 db '/dev/tty', 0 ; (+) 376 377 align 4 378 379 bss_start: 380 381 ABSOLUTE bss_start 382 383 00000110 iobuf: resb 512 384 ;ibuf: resb 512 385 ;obuf: resb 512 386 ;;fin: resw 1 387 ;fin: resd 1 ; 05/03/2022 388 ;;.bss 389 ;;ibuf: .=.+512. 390 ;;obuf: .=.+512. 391 ;;fin: .=.+2 392 ;;.text 393 ;bss_end: