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: 14/06/2022 ] -cat2.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 cat2.s -l cat2.txt -o cat2 -Z error.txt)) 19 ; cat386.s - cat2.s (14/06/2022, Retro UNIX 386 v1 & v1.1) 20 ; cat386.s - cat1.s (05/03/2022, Retro UNIX 386 v1 & v1.1 & v1.2) 21 ; cat386.s - cat0.s (17/10/2015 - 28/12/2015, Retro UNIX 386 v1, NASM 2.11) 22 ; CAT2.ASM (02/12/2013 - 16/07/2015, Retro UNIX 8086 v1, MASM 6.11) 23 24 ; 17/10/2015 25 26 ; UNIX v1 system calls 27 _rele equ 0 28 _exit equ 1 29 _fork equ 2 30 _read equ 3 31 _write equ 4 32 _open equ 5 33 _close equ 6 34 _wait equ 7 35 _creat equ 8 36 _link equ 9 37 _unlink equ 10 38 _exec equ 11 39 _chdir equ 12 40 _time equ 13 41 _mkdir equ 14 42 _chmod equ 15 43 _chown equ 16 44 _break equ 17 45 _stat equ 18 46 _seek equ 19 47 _tell equ 20 48 _mount equ 21 49 _umount equ 22 50 _setuid equ 23 51 _getuid equ 24 52 _stime equ 25 53 _quit equ 26 54 _intr equ 27 55 _fstat equ 28 56 _emt equ 29 57 _mdate equ 30 58 _stty equ 31 59 _gtty equ 32 60 _ilgins equ 33 61 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 62 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 63 64 %macro sys 1-4 65 ; 03/09/2015 66 ; 13/04/2015 67 ; Retro UNIX 386 v1 system call. 68 %if %0 >= 2 69 mov ebx, %2 70 %if %0 >= 3 71 mov ecx, %3 72 %if %0 = 4 73 mov edx, %4 74 %endif 75 %endif 76 %endif 77 mov eax, %1 78 int 30h 79 %endmacro 80 81 ; Retro UNIX 386 v1 system call format: 82 ; sys systemcall (eax) , , 83 84 [BITS 32] ; We need 32-bit intructions for protected mode 85 86 [ORG 0] 87 88 START_CODE: 89 ;; / cat -- concatenate files 90 91 sys _write, 1, nl, 2 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 00000000 BB01000000 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 00000005 B9[41010000] <1> mov ecx, %3 72 <1> %if %0 = 4 73 0000000A BA02000000 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 0000000F B804000000 <1> mov eax, %1 78 00000014 CD30 <1> int 30h 92 93 00000016 5D pop ebp 94 00000017 5A pop edx 95 ; esi = 0 ; ('sysexec' sets regs to zero) 96 ; 05/03/2022 97 ;mov esi, fin 98 ;mov edi, obuf 99 ;EAX = 2 (written byte count) 100 00000018 30C0 xor al, al ; 0 101 0000001A 4D dec ebp 102 0000001B 745A jz short cat_3 103 ;;mov (sp)+,r5 104 ;;tst (sp)+ 105 ;;mov $obuf,r2 106 ;;cmp r5,$1 107 ;;beq 3f 108 cat_0: 109 0000001D 5B pop ebx 110 0000001E 803B2D cmp byte [ebx], '-' 111 00000021 7410 je short cat_2 112 ;;dec r5 113 ;;ble done 114 ;;mov (sp)+,r0 115 ;;cmpb (r0),$'- 116 ;;bne 2f 117 ;;clr fin 118 ;;br 3f 119 cat_1: 120 ;;2: 121 ; ebx = file name offset 122 00000023 31C9 xor ecx, ecx ; 0 123 sys _open 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 00000025 B805000000 <1> mov eax, %1 78 0000002A CD30 <1> int 30h 124 ;jc short cat_7 125 ; 05/03/2022 ; (+) 126 0000002C 7305 jnc short cat_2 127 0000002E E9FC000000 jmp cat_7 128 cat_2: 129 ; 05/03/2022 130 00000033 89C6 mov esi, eax 131 ;mov [esi], eax ; 05/03/2022 132 ;mov [esi], ax 133 ;;mov r0,0f 134 ;;sys open; 0:..; 0 135 ;;bes loop 136 ;;mov r0,fin 137 138 ; 05/03/2022 ; (+) 139 ; convert user's file number to inode number 140 ; (get 34 byte inode details, inode num + inode) 141 ; (get 66 byte inode details for runix 386 v1.2) 142 sys _fstat, esi, iobuf 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 00000035 89F3 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 00000037 B9[50010000] <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 0000003C B81C000000 <1> mov eax, %1 78 00000041 CD30 <1> int 30h 143 ;jc short cat_7 144 ; 05/03/2022 ; (+) 145 00000043 7305 jnc short cat_f 146 00000045 E9E5000000 jmp cat_7 147 cat_f: 148 ; 05/03/2022 ; (+) 149 ;;movzx edi, word [iobuf] ; inode number 150 ;movzx edi, word [ecx] ; inode number 151 ; edi = 0 ; ('sysexec' sets regs to zero) 152 0000004A 668B39 mov di, [ecx] 153 154 ; 05/03/2022 ; (+) 155 ; check against '/dev/tty' inode number 156 ;sys _stat, consoletty, iobuf 157 ; (get 34 byte inode details, inode num + inode) 158 ; (get 66 byte inode details for runix 386 v1.2) 159 ;mov ecx, iobuf 160 sys _stat, consoletty 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 0000004D BB[44010000] <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 00000052 B812000000 <1> mov eax, %1 78 00000057 CD30 <1> int 30h 161 00000059 7207 jc short cat_x 162 163 ;movzx eax, word [iobuf] 164 0000005B 668B01 mov ax, [ecx] 165 0000005E 39C7 cmp edi, eax ; is it /dev/tty inode ? 166 00000060 7413 je short cat_y ; yes 167 ; no, it is not '/dev/tty' 168 cat_x: 169 ; 05/03/2022 ; (+) 170 ; get inode number of current tty (stdin) 171 ; (get 34 byte inode details, inode num + inode) 172 ; (get 66 byte inode details for runix 386 v1.2) 173 ;sys _fstat, 0, iobuf 174 ;;jc short cat_z 175 ;mov ecx, iobuf 176 sys _fstat, 0 ; get stdin file inode details 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 00000062 BB00000000 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 00000067 B81C000000 <1> mov eax, %1 78 0000006C CD30 <1> int 30h 177 178 ;movzx eax, word [iobuf] 179 0000006E 668B01 mov ax, [ecx] ; inode number 180 00000071 39C7 cmp edi, eax 181 ;jne short cat_z ; (ebx = 0) 182 00000073 7502 jne short cat_3 ; 14/06/2022 183 ;; (/dev/tyy0 .. /dev/tty9) 184 cat_y: 185 ; same with input file inode 186 00000075 29F6 sub esi, esi ; 0 187 ; use console tty input (stdin) 188 cat_3: ;;3: 189 ; 05/03/2022 190 ;or eax, eax ; console tty input (stdin) ? 191 ;jnz short cat_r ; no.. 192 ; 193 ; get keyboard status of console tty 194 00000077 31DB xor ebx, ebx ; 0 195 196 ; 14/06/2022 197 ; check if stdin is a tty (except console tty) 198 00000079 31D2 xor edx, edx ; 0 199 0000007B 6683F813 cmp ax, 19 ; /dev/tty9 200 0000007F 7708 ja short cat_z 201 00000081 3C0A cmp al, 10 ; /dev/tty0 202 00000083 7204 jb short cat_z 203 00000085 2C09 sub al, 9 ; ttynumber + 1 204 00000087 88C6 mov dh, al 205 cat_z: 206 ;xor ecx, ecx ; 0 207 00000089 89D1 mov ecx, edx ; 14/06/2022 208 sys _gtty 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 0000008B B820000000 <1> mov eax, %1 78 00000090 CD30 <1> int 30h 209 ;;sub eax, eax ; clear ax 210 ;mov eax, [esi] ; file descriptor/number 211 00000092 21DB and ebx, ebx ; is there a waiting char ? 212 ;jz short cat_3 ; no, wait for keystroke again 213 00000094 751B jnz short cat_c ; (a char is waiting in buffer) 214 ;mov eax, [esi] 215 ;or eax, eax ; 0 ; console tty input ? 216 00000096 09F6 or esi, esi ; 05/03/2022 217 00000098 7555 jnz short cat_r ; no, continue (to read file) 218 ;jmp short cat_z ; yes, wait for keystroke again 219 ; 14/06/2022 220 0000009A 31C9 xor ecx, ecx ; 0 221 sys _gtty ; get console tty status (ch=0) 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 0000009C B820000000 <1> mov eax, %1 78 000000A1 CD30 <1> int 30h 222 000000A3 21DB and ebx, ebx ; is there a waiting char ? 223 000000A5 74E2 jz short cat_z ; no, wait for keystroke again 224 000000A7 80FB1B cmp bl, 1Bh ; ESC key 225 000000AA 75DD jne short cat_z 226 000000AC E986000000 jmp cat_exit 227 cat_c: 228 ; 05/03/2022 229 ; read from console tty (stdin) 230 sys _read, 0, iobuf, 1 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 000000B1 BB00000000 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 000000B6 B9[50010000] <1> mov ecx, %3 72 <1> %if %0 = 4 73 000000BB BA01000000 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 000000C0 B803000000 <1> mov eax, %1 78 000000C5 CD30 <1> int 30h 231 ; read one char into [iobuf] 232 000000C7 7259 jc short cat_6 ; (ebx = 0) 233 ;and eax, eax 234 ;jz short cat_6 235 000000C9 48 dec eax ; 1 -> 0 236 000000CA 7556 jnz short cat_6 237 ;inc eax 238 ; eax = 1 239 000000CC 8A1D[50010000] mov bl, [iobuf] ; ascii code of the character 240 000000D2 80FB1B cmp bl, 1Bh ; 27 ; ESCape key ? 241 000000D5 7460 je short cat_exit ; yes, exit 242 ; 243 ;mov eax, [esi] ; file descriptor/number 244 ;or eax, eax ; 0 ; console_tty input ? 245 000000D7 09F6 or esi, esi ; 05/03/2022 246 ;jz short cat_w ; yes, write char to screen 247 ; 14/06/2022 248 000000D9 7514 jnz short cat_r 249 000000DB 40 inc eax 250 ; eax = 1 251 000000DC 803D[50010000]0D cmp byte [iobuf], 0Dh ; carriage return ? 252 000000E3 7523 jne short cat_w 253 000000E5 C605[51010000]0A mov byte [iobuf+1], 0Ah ; line feed 254 000000EC 40 inc eax 255 ; eax = 2 256 000000ED EB19 jmp short cat_w 257 cat_r: 258 ; 05/03/2022 259 ;mov eax, [esi] ; file descriptor/number 260 ;;mov ax, [esi] 261 ; 262 ;sys _read, eax, iobuf, 512 ; 16/07/2015 263 ;;sys _read, eax, ibuf, 512 264 ;jc short cat_6 265 ; 05/03/2022 266 ; esi = file descriptor/number 267 sys _read, esi, iobuf, 512 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 000000EF 89F3 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 000000F1 B9[50010000] <1> mov ecx, %3 72 <1> %if %0 = 4 73 000000F6 BA00020000 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 000000FB B803000000 <1> mov eax, %1 78 00000100 CD30 <1> int 30h 268 ; read 512 chars into [iobuf] 269 ;jc short cat_6 270 00000102 7222 jc short cat_k ; 05/03/2022 271 272 ; NOTE: If input file is a tty (keyboard) 273 ; only 1 byte will be read, by ignoring 274 ; byte count (512). 275 ; Retro UNIX 8086 v1 kernel ('rtty') 276 ; has been modified fot that. 277 ; Erdogan Tan (16/07/2015) 278 ; 279 280 00000104 21C0 and eax, eax ; EAX = 1 for tty (keyboard) 281 ;jz short cat_6 282 00000106 741E jz short cat_k ; 05/03/2022 283 284 ; push esi 285 ;mov esi, ibuf 286 ; mov esi, ecx ; offset ibuf 287 ; mov ecx, eax 288 ;;mov fin,r0 289 ;;sys read; ibuf; 512. 290 ;;bes 3f 291 ;;mov r0,r4 292 ;;beq 3f 293 ;;mov $ibuf,r3 294 ; 16/07/2015 295 ; mov edx, eax 296 ; ;add edx, obuf 297 ;cat_4: 298 ; ;;4: 299 ; lodsb 300 ;call putc 301 cat_w: 302 ; 16/07/2015 303 ; write to console tty (stdout) 304 sys _write, 1, iobuf, eax 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 00000108 BB01000000 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 0000010D B9[50010000] <1> mov ecx, %3 72 <1> %if %0 = 4 73 00000112 89C2 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 00000114 B804000000 <1> mov eax, %1 78 00000119 CD30 <1> int 30h 305 ;jc short cat_6 306 ; 05/03/2022 307 ;jnc short cat_3 308 ; 14/06/2022 309 0000011B 7205 jc short cat_m 310 0000011D E955FFFFFF jmp cat_3 311 cat_m: 312 ; loop cat_4 313 ; pop esi 314 cat_5: 315 ;mov eax, [esi] ; 05/03/2022 316 ;;mov ax, [esi] 317 ;jmp short cat_3 318 ;;movb (r3)+,r0 319 ;;jsr pc,putc 320 ;;dec r4 321 ;;bne 4b 322 ;;br 3b 323 ;; 05/03/2022 324 ;; ebx = file descriptor/input 325 ;;and ebx, ebx ; console input ? 326 ;;jnz short cat_3 ; no, file input 327 ;;cmp byte [quit], al ; 0 328 ;;ja short cat_7 ; ebx = 0 329 ;;jmp short cat_z 330 ; 05/03/2022 331 ;jmp short cat_3 332 333 cat_6: ;;3: 334 ; 05/03/2022 335 ; ebx = file descriptor/number 336 ;movzx ebx, word [esi] 337 ; 338 00000122 09F6 or esi, esi 339 00000124 7409 jz short cat_7 340 cat_k: 341 sys _close, esi 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 00000126 89F3 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 00000128 B806000000 <1> mov eax, %1 78 0000012D CD30 <1> int 30h 342 ; 343 ;or ebx, ebx 344 ;jz short cat_7 345 ;sys _close 346 ;;mov fin,r0 347 ;;beq loop 348 ;;sys close 349 ;;br loop 350 cat_7: 351 ;;loop: 352 0000012F 4D dec ebp 353 ;;jz short cat_8 354 ; 28/12/2015 355 ;jg short cat_0 356 ; 05/03/2022 357 00000130 7E05 jng short cat_exit 358 00000132 E9E6FEFFFF jmp cat_0 359 cat_exit: 360 sys _exit 65 <1> 66 <1> 67 <1> 68 <1> %if %0 >= 2 69 <1> mov ebx, %2 70 <1> %if %0 >= 3 71 <1> mov ecx, %3 72 <1> %if %0 = 4 73 <1> mov edx, %4 74 <1> %endif 75 <1> %endif 76 <1> %endif 77 00000137 B801000000 <1> mov eax, %1 78 0000013C CD30 <1> int 30h 361 here: 362 0000013E 90 nop 363 0000013F EBFD jmp short here 364 ;; 365 ;cat_8: 366 ; ;;done: 367 ; sub di, obuf 368 ; jz short cat_9 369 ; sys _write, 1, obuf, di 370 ;;sub $obuf,r2 371 ;;beq 1f 372 ;;mov r2,0f 373 ;;mov $1,r0 374 ;;sys write; obuf; 0:.. 375 ;cat_9: 376 ; ;;1: 377 ; sys _exit 378 ;;sys exit 379 ;; 380 ;putc: 381 ; ;;putc: 382 ; stosb 383 ; cmp di, dx ; 16/07/2015 384 ;cmp di, obuf + 512 385 ; jb short cat_10 386 ; push cx 387 ; 16/07/2015 388 ; mov di, obuf 389 ; sub dx, di ; byte (char) count 390 ; 391 ; sys _write, 1, obuf 392 ;sys _write, 1, obuf, 512 393 ;mov di, obuf 394 ;;movb r0,(r2)+ 395 ;;cmp r2,$obuf+512. 396 ;;blo 1f 397 ;;mov $1,r0 398 ;;sys write; obuf; 512. 399 ;;mov $obuf,r2 400 ; pop cx 401 ;cat_10: 402 ;;1: 403 ; retn 404 ;;rts pc 405 406 00000141 0D0A nl: db 0Dh, 0Ah ; , 0 407 ; 05/03/2022 408 00000143 00 quit: db 0 409 consoletty: 410 00000144 2F6465762F74747900 db '/dev/tty', 0 ; (+) 411 412 0000014D 90 align 4 413 414 bss_start: 415 416 ABSOLUTE bss_start 417 418 00000150 iobuf: resb 512 419 ;ibuf: resb 512 420 ;obuf: resb 512 421 ;;fin: resw 1 422 ;fin: resd 1 ; 05/03/2022 423 ;;.bss 424 ;;ibuf: .=.+512. 425 ;;obuf: .=.+512. 426 ;;fin: .=.+2 427 ;;.text 428 ;bss_end: