1 ; **************************************************************************** 2 ; sh386.s (sh1.s) - Retro Unix 386 v1 Shell - /bin/sh 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 ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 9 ; (v0.1 - Beginning: 11/07/2012) 10 ; 11 ; [ Last Modification: 03/01/2016 ] 12 ; 13 ; Derived from UNIX Operating System (v1.0 for PDP-11) 14 ; (Original) Source Code by Ken Thompson (Bell Laboratories, 1971-1972) 15 ; **************************************************************************** 16 ; 17 ; 18 ; 19 ; 20 ; 21 ; **************************************************************************** 22 23 ; sh1.s (27/12/2015, Retro UNIX 386 v1.1) 24 ; sh0.s (24/08/2015, Retro UNIX 386 v1, NASM 2.11, 32 bit version of 'sh.asm') 25 ; SHELL02.ASM, 13/11/2013 - 08/04/2014 (sh.asm, Retro UNIX 8086 v1, MASM 6.11) 26 27 ; 27/08/2015 28 ; 24/08/2015 29 ; 08/04/2014 30 ; 13/11/2013 31 32 ; UNIX v1 system calls 33 _rele equ 0 34 _exit equ 1 35 _fork equ 2 36 _read equ 3 37 _write equ 4 38 _open equ 5 39 _close equ 6 40 _wait equ 7 41 _creat equ 8 42 _link equ 9 43 _unlink equ 10 44 _exec equ 11 45 _chdir equ 12 46 _time equ 13 47 _mkdir equ 14 48 _chmod equ 15 49 _chown equ 16 50 _break equ 17 51 _stat equ 18 52 _seek equ 19 53 _tell equ 20 54 _mount equ 21 55 _umount equ 22 56 _setuid equ 23 57 _getuid equ 24 58 _stime equ 25 59 _quit equ 26 60 _intr equ 27 61 _fstat equ 28 62 _emt equ 29 63 _mdate equ 30 64 _stty equ 31 65 _gtty equ 32 66 _ilgins equ 33 67 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 68 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 69 70 %macro sys 1-4 71 ; 03/09/2015 72 ; 13/04/2015 73 ; Retro UNIX 386 v1 system call. 74 %if %0 >= 2 75 mov ebx, %2 76 %if %0 >= 3 77 mov ecx, %3 78 %if %0 = 4 79 mov edx, %4 80 %endif 81 %endif 82 %endif 83 mov eax, %1 84 int 30h 85 %endmacro 86 87 ; Retro UNIX 386 v1 system call format: 88 ; sys systemcall (eax) , , 89 90 [BITS 32] ; We need 32-bit intructions for protected mode 91 92 [ORG 0] 93 94 START_CODE: 95 ;/ sh -- command interpreter 96 97 ;;27/12/2015 98 ;;clear BSS 99 ;mov ecx, ((bss_end - bss_start) + 3) / 4 100 ;sub eax, eax 101 ;mov edi, bss_start 102 ;rep stosd 103 s0: 104 00000000 89E5 mov ebp, esp 105 ; mov sp,r5 106 00000002 892D[720C0000] mov [shellarg], ebp 107 ; mov r5,shellarg / save orig sp in shellarg 108 00000008 8B5D04 mov ebx, [ebp+4] 109 0000000B 803B2D cmp byte [ebx], '-' 110 ; cmpb *2(r5),$'- / was this sh called by init or loginx~ 111 0000000E 752E jne short s1 112 ; bne 2f / no 113 sys _intr, 0 114 <1> 115 <1> 116 <1> 117 <1> %if %0 >= 2 118 00000010 BB00000000 <1> mov ebx, %2 119 <1> %if %0 >= 3 120 <1> mov ecx, %3 121 <1> %if %0 = 4 122 <1> mov edx, %4 123 <1> %endif 124 <1> %endif 125 <1> %endif 126 00000015 B81B000000 <1> mov eax, %1 127 0000001A CD30 <1> int 30h 128 ; sys intr; 0 / yes, turn off interrupts 129 sys _quit, 0 130 <1> 131 <1> 132 <1> 133 <1> %if %0 >= 2 134 0000001C BB00000000 <1> mov ebx, %2 135 <1> %if %0 >= 3 136 <1> mov ecx, %3 137 <1> %if %0 = 4 138 <1> mov edx, %4 139 <1> %endif 140 <1> %endif 141 <1> %endif 142 00000021 B81A000000 <1> mov eax, %1 143 00000026 CD30 <1> int 30h 144 ; sys quit; 0 145 sys _write, 1, msg_unix_sh, msgsh_size 146 <1> 147 <1> 148 <1> 149 <1> %if %0 >= 2 150 00000028 BB01000000 <1> mov ebx, %2 151 <1> %if %0 >= 3 152 0000002D B9[EB050000] <1> mov ecx, %3 153 <1> %if %0 = 4 154 00000032 BA1D000000 <1> mov edx, %4 155 <1> %endif 156 <1> %endif 157 <1> %endif 158 00000037 B804000000 <1> mov eax, %1 159 0000003C CD30 <1> int 30h 160 s1: ;2: 161 sys _getuid 162 <1> 163 <1> 164 <1> 165 <1> %if %0 >= 2 166 <1> mov ebx, %2 167 <1> %if %0 >= 3 168 <1> mov ecx, %3 169 <1> %if %0 = 4 170 <1> mov edx, %4 171 <1> %endif 172 <1> %endif 173 <1> %endif 174 0000003E B818000000 <1> mov eax, %1 175 00000043 CD30 <1> int 30h 176 ; sys getuid / who is user 177 ;and eax, eax 178 00000045 20C0 and al, al 179 ; tst r0 / is it superuser 180 00000047 7507 jnz short s2 181 ; bne 2f / no 182 00000049 C605[79060000]23 mov byte [_at], '#' 183 ; movb $'#,at / yes, set new prompt symbol 184 s2: ;2: 185 00000050 837D0001 cmp dword [ebp], 1 186 ; cmp (r5),$1 / tty input? 187 00000054 7631 jna short newline 188 ; ble newline / yes, call with '-' (or with no command 189 ; / file name) 190 00000056 31DB xor ebx, ebx 191 ; clr r0 / no, set tty 192 sys _close 193 <1> 194 <1> 195 <1> 196 <1> %if %0 >= 2 197 <1> mov ebx, %2 198 <1> %if %0 >= 3 199 <1> mov ecx, %3 200 <1> %if %0 = 4 201 <1> mov edx, %4 202 <1> %endif 203 <1> %endif 204 <1> %endif 205 00000058 B806000000 <1> mov eax, %1 206 0000005D CD30 <1> int 30h 207 ; sys close / close it 208 0000005F 8B5D08 mov ebx, [ebp+8] ; arg 1 209 ; mov 4(r5),0f / get new file name 210 00000062 31C9 xor ecx, ecx ; arg 2 211 sys _open 212 <1> 213 <1> 214 <1> 215 <1> %if %0 >= 2 216 <1> mov ebx, %2 217 <1> %if %0 >= 3 218 <1> mov ecx, %3 219 <1> %if %0 = 4 220 <1> mov edx, %4 221 <1> %endif 222 <1> %endif 223 <1> %endif 224 00000064 B805000000 <1> mov eax, %1 225 00000069 CD30 <1> int 30h 226 ; sys open; 0:..; 0 / open it 227 0000006B 7311 jnc short s3 228 ; bec 1f / branch if no error 229 0000006D BE[15060000] mov esi, msgNotFound 230 00000072 E8ED010000 call error 231 ; jsr r5,error / error in file name 232 ; ; .even 233 sys _exit 234 <1> 235 <1> 236 <1> 237 <1> %if %0 >= 2 238 <1> mov ebx, %2 239 <1> %if %0 >= 3 240 <1> mov ecx, %3 241 <1> %if %0 = 4 242 <1> mov edx, %4 243 <1> %endif 244 <1> %endif 245 <1> %endif 246 00000077 B801000000 <1> mov eax, %1 247 0000007C CD30 <1> int 30h 248 ; sys exit 249 s3: ;1: 250 0000007E C605[79060000]00 mov byte [_at], 0 251 ; clr at / clear prompt character, if reading non-tty 252 ; / input file 253 00000085 EB1F jmp short newcom 254 newline: 255 00000087 803D[79060000]00 cmp byte [_at], 0 256 ; tst at / is there a prompt symbol 257 0000008E 7616 jna short newcom 258 ; beq newcom / no 259 ; mov $1,r0 / yes 260 nl: 261 sys _write, 1, prompt, p_size 262 <1> 263 <1> 264 <1> 265 <1> %if %0 >= 2 266 00000090 BB01000000 <1> mov ebx, %2 267 <1> %if %0 >= 3 268 00000095 B9[77060000] <1> mov ecx, %3 269 <1> %if %0 = 4 270 0000009A BA04000000 <1> mov edx, %4 271 <1> %endif 272 <1> %endif 273 <1> %endif 274 0000009F B804000000 <1> mov eax, %1 275 000000A4 CD30 <1> int 30h 276 ;sys _write, 1, _at, 2 277 ; sys write; at; 2. / print prompt 278 newcom: 279 000000A6 8B25[720C0000] mov esp, [shellarg] 280 ; mov shellarg,sp / 281 000000AC BE[A6060000] mov esi, parbuf 282 ; mov $parbuf,r3 / initialize command list area 283 000000B1 BF[A00A0000] mov edi, parp 284 ; mov $parp,r4 / initialize command list pointers 285 000000B6 31C0 xor eax, eax 286 000000B8 A3[940A0000] mov [infile], eax ; 0 287 ; clr infile / initialize alternate input 288 000000BD A3[980A0000] mov [outfile], eax ; 0 289 ; clr outfile / initialize alternate output 290 000000C2 A2[920A0000] mov [glflag], al ; 0 291 ;mov [glflag], ax ; 0 292 ; clr glflag / initialize global flag 293 ; 27/12/2015 294 000000C7 A2[76060000] mov [FCAT], al ; 0 295 newarg: 296 000000CC E897030000 call blank 297 ; jsr pc,blank / squeeze out leading blanks 298 000000D1 E877030000 call delim 299 000000D6 7467 je short nch4 ; '\n', ';', '&' 300 ; jsr r5,delim / is new character a ; \n or & 301 ; br 2f / yes 302 000000D8 56 push esi 303 ; mov r3,-(sp) / no, push arg pointer onto stack 304 000000D9 3C3C cmp al, '<' 305 ; cmp r0,$'< / new input file? 306 000000DB 7508 jne short na1 307 ; bne 1f / no 308 000000DD 8935[940A0000] mov [infile], esi 309 ; mov (sp),infile / yes, save arg pointer 310 ;jmp short na4 311 000000E3 EB1E jmp short na3 312 ;mov dword [esp], 0 313 ; clr (sp) / clear pointer 314 ;jmp short nch1 315 ; br 3f 316 na1: ;1: 317 000000E5 3C3E cmp al, '>' 318 ; cmp r0,$'> / new output file? 319 000000E7 7530 jne short nch0 320 ;jne short newchar 321 ; bne newchar / no 322 000000E9 8935[980A0000] mov [outfile], esi 323 ; mov (sp),outfile / yes, save arg pointer 324 ; 27/12/2015 325 000000EF E886030000 call getc 326 000000F4 3C3E cmp al, '>' 327 000000F6 7507 jne short na2 328 ; 329 000000F8 A2[76060000] mov [FCAT], al ; '>>' 330 000000FD EB04 jmp short na3 331 na2: 332 000000FF 3C20 cmp al, 20h ; ' ' 333 00000101 7505 jne short na4 334 na3: 335 00000103 E860030000 call blank 336 na4: 337 00000108 C7042400000000 mov dword [esp], 0 338 ; clr (sp) / clear pointer 339 ;jmp short nch1 340 ; br 3f 341 0000010F EB12 jmp short nch7 342 newchar: 343 00000111 3C20 cmp al, 20h 344 ; cmp $' ,r0 / is character a blank 345 00000113 7415 je short nch2 346 ; beq 1f / branch if it is (blank as arg separator) 347 00000115 3C8D cmp al, 8Dh ; 128 + 13 348 00000117 7411 je short nch2 349 ; cmp $'\n+200,r0 / treat \n preceded by ; beq 1f / as blank 350 nch0: 351 00000119 E8A3010000 call putc 352 ; jsr pc,putc / put this character in parbuf list 353 nch1: ;3: 354 0000011E E857030000 call getc 355 ; jsr pc,getc / get next character 356 nch7: 357 00000123 E825030000 call delim 358 00000128 75E7 jne short newchar 359 ;jz short nch2 ; '\n', ';', '&' 360 ; jsr r5,delim / is char a ; \n or &, 361 ; br 1f / yes 362 ;jmp short newchar 363 ; br newchar / no, start new character tests 364 nch2: ;1: 365 0000012A C60600 mov byte [esi], 0 366 0000012D 46 inc esi 367 ; clrb (r3)+ / end name with \0 when read blank, 368 ; or delim 369 0000012E 5B pop ebx 370 0000012F 891F mov [edi], ebx 371 ; mov (sp)+,(r4)+ / move arg ptr to parp location 372 00000131 09DB or ebx, ebx 373 00000133 7403 jz short nch3 374 ;jnz short nch3 375 ; bne 1f / if (sp)=0, in file or out file points 376 ; to arg 377 00000135 83C704 add edi, 4 378 ; tst -(r4) / so ignore dummy (0), in pointer list 379 nch3: ;1: 380 00000138 E810030000 call delim 381 0000013D 758D jne short newarg 382 ;jz short nch4 ; '\n', ';', '&' 383 ; jsr r5,delim / is char a ; \n or &. 384 ; br 2f / yes 385 ;jmp short newarg 386 ; br newarg / no, start newarg processing 387 nch4: ;2: 388 0000013F C70700000000 mov dword [edi], 0 389 ; clr (r4) / \n, &, or ; takes to here 390 ; / (end of arg list) after 'delim' call 391 00000145 50 push eax 392 ; mov r0,-(sp) / save delimiter in stack 393 00000146 E82A000000 call docom 394 ; jsr pc,docom / go to exec command in parbuf 395 0000014B 803C2426 cmp byte [esp], '&' 396 ; cmpb (sp),$'& / get a new command without wait? 397 0000014F 0F8451FFFFFF je newcom 398 ; beq newcom / yes 399 00000155 21D2 and edx, edx 400 ; tst r1 / was chdir just executed or line ended 401 ; / with ampersand? 402 00000157 740D jz short nch6 403 ; beq 2f / yes 404 nch5: ;1: 405 sys _wait 406 <1> 407 <1> 408 <1> 409 <1> %if %0 >= 2 410 <1> mov ebx, %2 411 <1> %if %0 >= 3 412 <1> mov ecx, %3 413 <1> %if %0 = 4 414 <1> mov edx, %4 415 <1> %endif 416 <1> %endif 417 <1> %endif 418 00000159 B807000000 <1> mov eax, %1 419 0000015E CD30 <1> int 30h 420 ; sys wait / no, wait for new process to terminate 421 ; / command executed) 422 00000160 7204 jc short nch6 423 ; bcs 2f / no, children not previously waited for 424 00000162 39D0 cmp eax, edx 425 ; cmp r0,r1 / is this my child 426 00000164 75F3 jne short nch5 427 ; bne 1b 428 nch6: ;2: 429 00000166 803C240D cmp byte [esp], 0Dh 430 ;cmp byte [esp], 0Ah 431 ; cmp (sp),$'\n / was delimiter a new line 432 0000016A 0F8417FFFFFF je newline 433 ; beq newline / yes 434 00000170 E931FFFFFF jmp newcom 435 ; br newcom / no, pick up next command 436 docom: 437 00000175 81EF[A00A0000] sub edi, parp 438 ; sub $parp,r4 / out arg count in r4 439 0000017B 7503 jne short dcom1 440 ; bne 1f / any arguments? 441 dcom0: 442 0000017D 29D2 sub edx, edx ; 0 443 ; clr r1 / no, line ended with ampersand 444 0000017F C3 retn 445 ; rts pc / return from call 446 dcom1: ;1: 447 00000180 89FB mov ebx, edi 448 ; 06/12/2013 449 00000182 BE[7B060000] mov esi, qecho 450 00000187 E827010000 call chcom 451 0000018C 7543 jnz short dcom7 452 ; 28/12/2015 453 0000018E 89DD mov ebp, ebx 454 00000190 BF[A00A0000] mov edi, parp 455 dcom9: ; CRLF 456 sys _write, 1, nextline, 2 457 <1> 458 <1> 459 <1> 460 <1> %if %0 >= 2 461 00000195 BB01000000 <1> mov ebx, %2 462 <1> %if %0 >= 3 463 0000019A B9[12060000] <1> mov ecx, %3 464 <1> %if %0 = 4 465 0000019F BA02000000 <1> mov edx, %4 466 <1> %endif 467 <1> %endif 468 <1> %endif 469 000001A4 B804000000 <1> mov eax, %1 470 000001A9 CD30 <1> int 30h 471 ; 472 000001AB 83ED04 sub ebp, 4 ; remain arg count x 4 473 000001AE 76CD jna short dcom0 474 000001B0 83C704 add edi, 4 475 000001B3 8B37 mov esi, [edi] 476 ;or esi, esi 477 ;jz short dcom0 478 000001B5 89F2 mov edx, esi ; string address 479 dcom10: 480 000001B7 AC lodsb 481 000001B8 08C0 or al, al 482 000001BA 75FB jnz short dcom10 483 000001BC 87D6 xchg edx, esi 484 000001BE 29F2 sub edx, esi ; byte count 485 000001C0 4A dec edx 486 ;jz short dcom0 487 ; write string 488 sys _write, 1, esi ; edx = byte count 489 <1> 490 <1> 491 <1> 492 <1> %if %0 >= 2 493 000001C1 BB01000000 <1> mov ebx, %2 494 <1> %if %0 >= 3 495 000001C6 89F1 <1> mov ecx, %3 496 <1> %if %0 = 4 497 <1> mov edx, %4 498 <1> %endif 499 <1> %endif 500 <1> %endif 501 000001C8 B804000000 <1> mov eax, %1 502 000001CD CD30 <1> int 30h 503 000001CF EBC4 jmp short dcom9 504 dcom7: 505 000001D1 BE[83060000] mov esi, qchdir 506 000001D6 E8D8000000 call chcom 507 000001DB 752D jnz short dcom4 508 ; jsr r5,chcom; qchdir / is command chdir? 509 ; br 2f / command not chdir 510 dcom12: 511 000001DD 80FB08 cmp bl, 8 ; 8 = arg count x 4 (24/08/2015) 512 ;cmp bx, 8 513 ; cmp r4,$4 / prepare to exec chdir, 514 ; 4 = arg count x 2 515 000001E0 740C je short dcom2 516 ; beq 3f 517 dcom8: 518 000001E2 BE[25060000] mov esi, msgArgCount 519 000001E7 E878000000 call error 520 ; jsr r5,error / go to print error 521 ; ; .even 522 ;jmp short dcom3 523 ; br 4f 524 000001EC EB8F jmp short dcom0 525 dcom2: ;3: 526 000001EE 8B1D[A40A0000] mov ebx, [parp+4] 527 ;mov parp+2,0f / move directory name to sys call 528 sys _chdir 529 <1> 530 <1> 531 <1> 532 <1> %if %0 >= 2 533 <1> mov ebx, %2 534 <1> %if %0 >= 3 535 <1> mov ecx, %3 536 <1> %if %0 = 4 537 <1> mov edx, %4 538 <1> %endif 539 <1> %endif 540 <1> %endif 541 000001F4 B80C000000 <1> mov eax, %1 542 000001F9 CD30 <1> int 30h 543 ; sys chdir; 0:0 / exec chdir 544 000001FB 730A jnc short dcom3 545 ; bec 4f / no error exit 546 000001FD BE[2F060000] mov esi, msgBadDir 547 00000202 E85D000000 call error 548 ; jsr r5,error / go to print error 549 ; ; .even 550 ; / this diagnostic 551 dcom3: ;4: 552 00000207 31D2 xor edx, edx ; 0 553 ; clr r1 / set r1 to zero to skip wait 554 00000209 C3 retn 555 ; rts pc / and return 556 dcom4: ;2: 557 ; 06/12/2013 558 0000020A BE[80060000] mov esi, qcd 559 0000020F E89F000000 call chcom 560 00000214 74C7 jz short dcom12 561 dcom11: 562 00000216 BE[89060000] mov esi, glogin 563 0000021B E893000000 call chcom 564 00000220 7522 jnz short dcom5 565 ; jsr r5,chcom; glogin / is command login? 566 ; br 2f / not loqin, go to fork 567 sys _exec, parbuf, parp 568 <1> 569 <1> 570 <1> 571 <1> %if %0 >= 2 572 00000222 BB[A6060000] <1> mov ebx, %2 573 <1> %if %0 >= 3 574 00000227 B9[A00A0000] <1> mov ecx, %3 575 <1> %if %0 = 4 576 <1> mov edx, %4 577 <1> %endif 578 <1> %endif 579 <1> %endif 580 0000022C B80B000000 <1> mov eax, %1 581 00000231 CD30 <1> int 30h 582 ; sys exec; parbuf; parp / exec login 583 sys _exec, binpb, parp 584 <1> 585 <1> 586 <1> 587 <1> %if %0 >= 2 588 00000233 BB[A1060000] <1> mov ebx, %2 589 <1> %if %0 >= 3 590 00000238 B9[A00A0000] <1> mov ecx, %3 591 <1> %if %0 = 4 592 <1> mov edx, %4 593 <1> %endif 594 <1> %endif 595 <1> %endif 596 0000023D B80B000000 <1> mov eax, %1 597 00000242 CD30 <1> int 30h 598 ; sys exec; binpb; parp / or /bin/login 599 dcom5: ;2: / no error return?? 600 00000244 BB[F6020000] mov ebx, newproc 601 ; child process will return to 'newproc' address 602 sys _fork 603 <1> 604 <1> 605 <1> 606 <1> %if %0 >= 2 607 <1> mov ebx, %2 608 <1> %if %0 >= 3 609 <1> mov ecx, %3 610 <1> %if %0 = 4 611 <1> mov edx, %4 612 <1> %endif 613 <1> %endif 614 <1> %endif 615 00000249 B802000000 <1> mov eax, %1 616 0000024E CD30 <1> int 30h 617 ; sys fork / generate sh child process 618 ; for command 619 ; br newproc / exec command with 620 ; new process 621 ; parent process will return here 622 00000250 730F jnc short dcom6 623 ; bec 1f / no error exit, old process 624 00000252 BE[3D060000] mov esi, msgTryAgain 625 00000257 E808000000 call error 626 ; jsr r5,error / go to print error 627 ; ; .even / this diagnostic 628 0000025C E926FEFFFF jmp newline 629 ; jmp newline / and return for next try 630 dcom6: ;1: 631 00000261 89C2 mov edx, eax ; child process ID 632 ; mov r0,r1 / save id of child sh 633 00000263 C3 retn 634 ; rts pc / return to "jsr pc, docom" call 635 ; in parent sh 636 error: 637 sys _write, 1, nextline, 2 638 <1> 639 <1> 640 <1> 641 <1> %if %0 >= 2 642 00000264 BB01000000 <1> mov ebx, %2 643 <1> %if %0 >= 3 644 00000269 B9[12060000] <1> mov ecx, %3 645 <1> %if %0 = 4 646 0000026E BA02000000 <1> mov edx, %4 647 <1> %endif 648 <1> %endif 649 <1> %endif 650 00000273 B804000000 <1> mov eax, %1 651 00000278 CD30 <1> int 30h 652 s4: 653 0000027A AC lodsb 654 0000027B A2[700C0000] mov [och], al 655 ; movb (r5)+,och / pick up diagnostic character 656 00000280 20C0 and al, al 657 00000282 7418 jz short s5 658 ; beq 1f / 0 is end of line 659 sys _write, 1, och, 1 660 <1> 661 <1> 662 <1> 663 <1> %if %0 >= 2 664 00000284 BB01000000 <1> mov ebx, %2 665 <1> %if %0 >= 3 666 00000289 B9[700C0000] <1> mov ecx, %3 667 <1> %if %0 = 4 668 0000028E BA01000000 <1> mov edx, %4 669 <1> %endif 670 <1> %endif 671 <1> %endif 672 00000293 B804000000 <1> mov eax, %1 673 00000298 CD30 <1> int 30h 674 ; mov $1,r0 / set for tty output 675 ; sys write; och; 1 / print it 676 0000029A EBDE jmp short s4 677 ;jmp short error 678 ; br error / continue to get characters 679 s5: ;1: 680 ;inc esi 681 ; inc r5 / inc r5 to point to return 682 ;;and si, 0FFFEh 683 ;shr esi, 1 684 ;shl esi, 1 685 ; bic $1,r5 / make it even 686 sys _seek, 0, 0, 2 687 <1> 688 <1> 689 <1> 690 <1> %if %0 >= 2 691 0000029C BB00000000 <1> mov ebx, %2 692 <1> %if %0 >= 3 693 000002A1 B900000000 <1> mov ecx, %3 694 <1> %if %0 = 4 695 000002A6 BA02000000 <1> mov edx, %4 696 <1> %endif 697 <1> %endif 698 <1> %endif 699 000002AB B813000000 <1> mov eax, %1 700 000002B0 CD30 <1> int 30h 701 ; clr r0 / set for input 702 ; sys seek; 0; 2 / exit from runcom. skip to 703 ; / end of input file 704 000002B2 C3 retn 705 ;; ((/ rts r5)) 706 ;; (not in original unix v1 'sh.s') 707 708 chcom: ; / has no effect if tty input 709 ; mov (r5)+,r1 / glogin gchdir r1, bump r5 710 000002B3 BF[A6060000] mov edi, parbuf 711 ; mov $parbuf,r2 / command address r2 'login' 712 s6: ;1: 713 000002B8 AC lodsb 714 ; movb (r1)+,r0 / is this command 'chdir' 715 000002B9 AE scasb 716 ; cmpb (r2)+,r0 / compare command name byte 717 ; / with 'login' or 'chdir' 718 000002BA 7504 jne short s7 719 ; bne 1f / doesn't compare 720 000002BC 08C0 or al, al 721 ; tst r0 / is this 722 000002BE 75F8 jnz short s6 723 ; bne 1b / end of names 724 ; tst (r5)+ / yes, bump r5 again to execute 725 ; / login or chdir 726 s7: ;1: 727 000002C0 C3 retn 728 ; rts r5 / no, return to exec command 729 730 putc: 731 000002C1 3C27 cmp al, 27h ; ' 732 ; cmp r0,$'' / single quote? 733 000002C3 740A je short pch1 734 ; beq 1f / yes 735 000002C5 3C22 cmp al, 22h ; " 736 ; cmp r0,$'" / double quote 737 000002C7 7406 je short pch1 738 ; beq 1f / yes 739 000002C9 247F and al, 7Fh 740 ; bic $!177,r0 / no, remove 200, if present 741 000002CB 8806 mov [esi], al 742 000002CD 46 inc esi 743 ; movb r0,(r3)+ / store character in parbuf 744 000002CE C3 retn 745 ; rts pc 746 pch1: ;1: 747 000002CF 50 push eax 748 ; mov r0,-(sp) / push quote mark onto stack 749 pch2: ;1: 750 000002D0 E8A5010000 call getc 751 ; jsr pc,getc / get a quoted character 752 000002D5 3C0D cmp al, 0Dh 753 ;cmp al, 0Ah ; \n 754 ; cmp r0,$'\n / is it end or line 755 000002D7 750F jne short pch3 756 ; bne 2f / no 757 000002D9 BE[47060000] mov esi, msgImbalance 758 000002DE E881FFFFFF call error 759 ; jsr r5,error / yes, indicate missing 760 ; quote mark 761 ; <"' imbalance\n\0>; .even 762 000002E3 E99FFDFFFF jmp newline 763 ; jmp newline / ask for new line 764 pch3: ;2: 765 000002E8 380424 cmp [esp], al 766 ; cmp r0,(sp) / is this closing quote mark 767 000002EB 7407 je short pch4 768 ; beq 1f / yes 769 000002ED 247F and al, 7Fh 770 ; bic $!177,r0 / no, strip off 200 771 ; if present 772 000002EF 8806 mov [esi], al 773 000002F1 46 inc esi 774 ; movb r0,(r3)+ / store quoted character 775 ; in parbuf 776 000002F2 EBDC jmp short pch2 777 ; br 1b / continue 778 pch4: ;1: 779 000002F4 58 pop eax 780 ; tst (sp)+ / pop quote mark off stack 781 000002F5 C3 retn 782 ; rts pc / return 783 784 ; / thp`e new process 785 786 newproc: 787 000002F6 8B35[940A0000] mov esi, [infile] 788 000002FC 09F6 or esi, esi 789 000002FE 7432 jz short np2 790 ; mov infile,0f / move pointer to new file name 791 ; beq 1f / branch if no alternate read file given 792 00000300 803E00 cmp byte [esi], 0 793 ; tstb *0f 794 00000303 761C jna short np1 795 ; beq 3f / branch if no file name given 796 sys _close, 0 797 <1> 798 <1> 799 <1> 800 <1> %if %0 >= 2 801 00000305 BB00000000 <1> mov ebx, %2 802 <1> %if %0 >= 3 803 <1> mov ecx, %3 804 <1> %if %0 = 4 805 <1> mov edx, %4 806 <1> %endif 807 <1> %endif 808 <1> %endif 809 0000030A B806000000 <1> mov eax, %1 810 0000030F CD30 <1> int 30h 811 ; clr r0 / set tty input file name 812 ; sys close / close it 813 sys _open, esi, 0 814 <1> 815 <1> 816 <1> 817 <1> %if %0 >= 2 818 00000311 89F3 <1> mov ebx, %2 819 <1> %if %0 >= 3 820 00000313 B900000000 <1> mov ecx, %3 821 <1> %if %0 = 4 822 <1> mov edx, %4 823 <1> %endif 824 <1> %endif 825 <1> %endif 826 00000318 B805000000 <1> mov eax, %1 827 0000031D CD30 <1> int 30h 828 ; sys open; 0:..; 0 / open new input file 829 ; for reading 830 0000031F 7311 jnc short np2 831 ; bcc 1f / branch if input file ok 832 np1: ;3: 833 00000321 BE[54060000] mov esi, msgInputFile 834 00000326 E839FFFFFF call error 835 ; jsr r5,error / file not ok, print error 836 ; ; .even / this diagnostic 837 sys _exit 838 <1> 839 <1> 840 <1> 841 <1> %if %0 >= 2 842 <1> mov ebx, %2 843 <1> %if %0 >= 3 844 <1> mov ecx, %3 845 <1> %if %0 = 4 846 <1> mov edx, %4 847 <1> %endif 848 <1> %endif 849 <1> %endif 850 0000032B B801000000 <1> mov eax, %1 851 00000330 CD30 <1> int 30h 852 ; sys exit / terminate this process 853 ; and make parent sh 854 np2: ;1: 855 00000332 8B35[980A0000] mov esi, [outfile] 856 ; mov outfile,r2 / more pointer to new file name 857 00000338 21F6 and esi, esi 858 0000033A 747E jz short np6 859 ; beq 1f / branch if no alternate write file 860 ; 27/12/2015 861 0000033C 803E00 cmp byte [esi], 0 862 0000033F 7629 jna short np4 863 ; 864 ;cmp byte [esi], '>' 865 ; cmpb (r2),$'> / is > at beqinning of file name? 866 ;jne short np3 867 ; bne 4f / branch if it isn't 868 ;inc esi 869 ; inc r2 / yes, increment pointer 870 ; 27/12/2015 871 00000341 803D[76060000]3E cmp byte [FCAT], '>' ; '>>' 872 00000348 7510 jne short np3 873 ; 874 sys _open, esi, 1 875 <1> 876 <1> 877 <1> 878 <1> %if %0 >= 2 879 0000034A 89F3 <1> mov ebx, %2 880 <1> %if %0 >= 3 881 0000034C B901000000 <1> mov ecx, %3 882 <1> %if %0 = 4 883 <1> mov edx, %4 884 <1> %endif 885 <1> %endif 886 <1> %endif 887 00000351 B805000000 <1> mov eax, %1 888 00000356 CD30 <1> int 30h 889 ; mov r2,0f 890 ; sys open; 0:..; 1 / open file for writing 891 00000358 7321 jnc short np5 892 ; bec 3f / if no error 893 np3: ;4: 894 sys _creat, esi, 15 ; Decimal 15 = Octal 17 895 <1> 896 <1> 897 <1> 898 <1> %if %0 >= 2 899 0000035A 89F3 <1> mov ebx, %2 900 <1> %if %0 >= 3 901 0000035C B90F000000 <1> mov ecx, %3 902 <1> %if %0 = 4 903 <1> mov edx, %4 904 <1> %endif 905 <1> %endif 906 <1> %endif 907 00000361 B808000000 <1> mov eax, %1 908 00000366 CD30 <1> int 30h 909 ; mov r2,0f 910 ; sys creat; 0:..; 17 / create new file 911 ; with this name 912 00000368 7311 jnc short np5 913 ; bec 3f / branch if no error 914 np4: ;2: 915 0000036A BE[5F060000] mov esi, msgOutputFile 916 0000036F E8F0FEFFFF call error 917 ; jsr r5,error 918 ; ; .even 919 sys _exit 920 <1> 921 <1> 922 <1> 923 <1> %if %0 >= 2 924 <1> mov ebx, %2 925 <1> %if %0 >= 3 926 <1> mov ecx, %3 927 <1> %if %0 = 4 928 <1> mov edx, %4 929 <1> %endif 930 <1> %endif 931 <1> %endif 932 00000374 B801000000 <1> mov eax, %1 933 00000379 CD30 <1> int 30h 934 ; sys exit 935 np5: ;3: 936 sys _close, eax 937 <1> 938 <1> 939 <1> 940 <1> %if %0 >= 2 941 0000037B 89C3 <1> mov ebx, %2 942 <1> %if %0 >= 3 943 <1> mov ecx, %3 944 <1> %if %0 = 4 945 <1> mov edx, %4 946 <1> %endif 947 <1> %endif 948 <1> %endif 949 0000037D B806000000 <1> mov eax, %1 950 00000382 CD30 <1> int 30h 951 ; sys close / close the new write file 952 ; mov r2,0f / move new name to open 953 np10: 954 sys _close, 1 955 <1> 956 <1> 957 <1> 958 <1> %if %0 >= 2 959 00000384 BB01000000 <1> mov ebx, %2 960 <1> %if %0 >= 3 961 <1> mov ecx, %3 962 <1> %if %0 = 4 963 <1> mov edx, %4 964 <1> %endif 965 <1> %endif 966 <1> %endif 967 00000389 B806000000 <1> mov eax, %1 968 0000038E CD30 <1> int 30h 969 ; mov $1,r0 / set tty file name 970 ; sys close / close it 971 sys _open, esi, 1 972 <1> 973 <1> 974 <1> 975 <1> %if %0 >= 2 976 00000390 89F3 <1> mov ebx, %2 977 <1> %if %0 >= 3 978 00000392 B901000000 <1> mov ecx, %3 979 <1> %if %0 = 4 980 <1> mov edx, %4 981 <1> %endif 982 <1> %endif 983 <1> %endif 984 00000397 B805000000 <1> mov eax, %1 985 0000039C CD30 <1> int 30h 986 ; sys open; 0:..; 1 / open new output file, 987 ; /it now has file descriptor 1 988 ; 27/12/2015 989 0000039E 803D[76060000]3E cmp byte [FCAT], '>' ; '>>' 990 000003A5 7513 jne short np6 991 ; 992 sys _seek, eax, 0, 2 993 <1> 994 <1> 995 <1> 996 <1> %if %0 >= 2 997 000003A7 89C3 <1> mov ebx, %2 998 <1> %if %0 >= 3 999 000003A9 B900000000 <1> mov ecx, %3 1000 <1> %if %0 = 4 1001 000003AE BA02000000 <1> mov edx, %4 1002 <1> %endif 1003 <1> %endif 1004 <1> %endif 1005 000003B3 B813000000 <1> mov eax, %1 1006 000003B8 CD30 <1> int 30h 1007 ; sys seek; 0; 2 / set pointer to 1008 ; current end of file 1009 np6: ;1: 1010 000003BA 803D[920A0000]00 cmp byte [glflag], 0 1011 ; tst glflag / was *, ? or [ encountered? 1012 000003C1 776F ja short np9 1013 ; bne 1f / yes 1014 sys _exec, parbuf, parp 1015 <1> 1016 <1> 1017 <1> 1018 <1> %if %0 >= 2 1019 000003C3 BB[A6060000] <1> mov ebx, %2 1020 <1> %if %0 >= 3 1021 000003C8 B9[A00A0000] <1> mov ecx, %3 1022 <1> %if %0 = 4 1023 <1> mov edx, %4 1024 <1> %endif 1025 <1> %endif 1026 <1> %endif 1027 000003CD B80B000000 <1> mov eax, %1 1028 000003D2 CD30 <1> int 30h 1029 ; sys exec; parbuf; parp / no, execute 1030 ; this command 1031 sys _exec, binpb, parp 1032 <1> 1033 <1> 1034 <1> 1035 <1> %if %0 >= 2 1036 000003D4 BB[A1060000] <1> mov ebx, %2 1037 <1> %if %0 >= 3 1038 000003D9 B9[A00A0000] <1> mov ecx, %3 1039 <1> %if %0 = 4 1040 <1> mov edx, %4 1041 <1> %endif 1042 <1> %endif 1043 <1> %endif 1044 000003DE B80B000000 <1> mov eax, %1 1045 000003E3 CD30 <1> int 30h 1046 ; sys exec; binpb; parp / or /bin/this command 1047 np7: ;2: 1048 sys _stat, binpb, inbuf 1049 <1> 1050 <1> 1051 <1> 1052 <1> %if %0 >= 2 1053 000003E5 BB[A1060000] <1> mov ebx, %2 1054 <1> %if %0 >= 3 1055 000003EA B9[680B0000] <1> mov ecx, %3 1056 <1> %if %0 = 4 1057 <1> mov edx, %4 1058 <1> %endif 1059 <1> %endif 1060 <1> %endif 1061 000003EF B812000000 <1> mov eax, %1 1062 000003F4 CD30 <1> int 30h 1063 ; sys stat; binpb; inbuf / if can't execute 1064 ; / does it exist? 1065 000003F6 7223 jc short np8 1066 ; bes 2f / branch if it doesn't 1067 000003F8 BE[9C0A0000] mov esi, parp-4 1068 000003FD C706[8F060000] mov dword [esi], shell 1069 ; mov $shell,parp-2 / does exist, 1070 ; not executable 1071 00000403 B8[A1060000] mov eax, binpb 1072 00000408 A3[A00A0000] mov [parp], eax 1073 ; mov $binpb,parp / so it must be 1074 sys _exec, shell, esi 1075 <1> 1076 <1> 1077 <1> 1078 <1> %if %0 >= 2 1079 0000040D BB[8F060000] <1> mov ebx, %2 1080 <1> %if %0 >= 3 1081 00000412 89F1 <1> mov ecx, %3 1082 <1> %if %0 = 4 1083 <1> mov edx, %4 1084 <1> %endif 1085 <1> %endif 1086 <1> %endif 1087 00000414 B80B000000 <1> mov eax, %1 1088 00000419 CD30 <1> int 30h 1089 ; sys exec; shell; parp-2 / a command file, 1090 ; / get it with sh /bin/x (if x name of file) 1091 np8: ;2: 1092 0000041B BE[6B060000] mov esi, msgNoCmd 1093 00000420 E83FFEFFFF call error 1094 ; jsr r5,error / a return for exec 1095 ; is the diagnostic 1096 ; ; .even 1097 00000425 8B25[720C0000] mov esp, [shellarg] 1098 sys _exit 1099 <1> 1100 <1> 1101 <1> 1102 <1> %if %0 >= 2 1103 <1> mov ebx, %2 1104 <1> %if %0 >= 3 1105 <1> mov ecx, %3 1106 <1> %if %0 = 4 1107 <1> mov edx, %4 1108 <1> %endif 1109 <1> %endif 1110 <1> %endif 1111 0000042B B801000000 <1> mov eax, %1 1112 00000430 CD30 <1> int 30h 1113 ; sys exit 1114 np9: ;1: 1115 00000432 BE[9C0A0000] mov esi, parp-4 1116 00000437 C706[97060000] mov dword [esi], glob 1117 ; mov $glob,parp-2 / prepare to process *,? 1118 sys _exec, glob, esi 1119 <1> 1120 <1> 1121 <1> 1122 <1> %if %0 >= 2 1123 0000043D BB[97060000] <1> mov ebx, %2 1124 <1> %if %0 >= 3 1125 00000442 89F1 <1> mov ecx, %3 1126 <1> %if %0 = 4 1127 <1> mov edx, %4 1128 <1> %endif 1129 <1> %endif 1130 <1> %endif 1131 00000444 B80B000000 <1> mov eax, %1 1132 00000449 CD30 <1> int 30h 1133 ; sys exec; glob; parp-2 1134 ; / execute modified command 1135 0000044B EBCE jmp short np8 1136 ; br 2b 1137 1138 delim: 1139 0000044D 3C0D cmp al, 0Dh ; carriage return 1140 0000044F 7416 je short dlim2 1141 ;cmp al, 0Ah 1142 ; cmp r0,$'\n / is character a newline 1143 ;je short dlim2 1144 ; beq 1f 1145 00000451 3C26 cmp al, '&' 1146 ;cmp r0,$'& / is it & 1147 00000453 7412 je short dlim2 1148 ; beq 1f / yes 1149 00000455 3C3B cmp al, ';' 1150 ; cmp r0,$'; / is it ; 1151 00000457 740E je short dlim2 1152 ; beq 1f / yes 1153 00000459 3C3F cmp al, '?' 1154 ; cmp r0,$'? / is it ? 1155 0000045B 7404 je short dlim1 1156 ; beq 3f 1157 0000045D 3C5B cmp al, '[' 1158 ; cmp r0,$'[ / is it beginning of character string 1159 ; / (for glob) 1160 0000045F 7506 jne short dlim2 1161 ; bne 2f 1162 dlim1: ;3: 1163 00000461 FE05[920A0000] inc byte [glflag] 1164 ; inc glflag / ? or * or [ set flag 1165 ;2: 1166 ;tst (r5)+ / bump to process all except \n,;,& 1167 dlim2: ;1: 1168 ; zf = 1 if the char is '\n' or ';' or '&' 1169 00000467 C3 retn 1170 ; rts r5 1171 blank: 1172 00000468 E80D000000 call getc 1173 ; jsr pc,getc / get next character 1174 0000046D 3C20 cmp al, 20h 1175 ; cmp $' ,r0 / leading blanks 1176 0000046F 74F7 je short blank 1177 ; beq blank / yes, 'squeeze out' 1178 00000471 3C8D cmp al, 8Dh ; 80h + 0Dh 1179 ;cmp al, 8Ah ; 80h + 0Ah 1180 00000473 74F3 je short blank 1181 ; cmp r0,$200+'\n / new-line preceded by ; is translated 1182 ; beq blank / into blank 1183 ; 28/12/2015 1184 00000475 3C0A cmp al, 0Ah 1185 00000477 74EF je short blank 1186 ; 1187 00000479 C3 retn 1188 ; rts pc 1189 getc: 1190 0000047A 833D[8E0A0000]00 cmp dword [param], 0 1191 ; tst param / are we substituting for $n 1192 00000481 773D ja short gch3 1193 ; bne 2f/ yes 1194 gch0: 1195 00000483 8B1D[680C0000] mov ebx, [inbufp] 1196 ; mov inbufp,r1 / no, move normal input pointer to r1 1197 s8: 1198 00000489 3B1D[6C0C0000] cmp ebx, [einbuf] 1199 ; cmp r1,einbuf / end of input line? 1200 0000048F 7207 jb short gch1 1201 ; bne 1f / no 1202 00000491 E877000000 call getbuf 1203 ; jsr pc,getbuf / yes, put next console line 1204 ; in buffer 1205 00000496 EBEB jmp short gch0 1206 ; br getc 1207 gch1: ;1: 1208 00000498 8A03 mov al, [ebx] 1209 0000049A 43 inc ebx 1210 ; movb (r1)+,r0 / move byte from input buffer to r0 1211 0000049B 891D[680C0000] mov [inbufp], ebx 1212 ; mov r1,inbufp / increment routine 1213 000004A1 0A05[760C0000] or al, [escap] 1214 ;or ax, escap 1215 ; bis escap,r0 / if last character was \ this adds 1216 ; / 200 to current character 1217 ;mov byte [escap], 0 1218 ;mov word [escap], 0 1219 ; clr escap / clear, so escap normally zero 1220 000004A7 3C5C cmp al, '\' 1221 ; cmp r0,$'\\ / note that \\ is equal \ in as 1222 000004A9 740C je short gch2 1223 ; beq 1f 1224 000004AB C605[760C0000]00 mov byte [escap], 0 1225 000004B2 3C24 cmp al, '$' 1226 ; cmp r0,$'$ / is it $ 1227 000004B4 7429 je short gch5 1228 ; beq 3f / yes 1229 000004B6 C3 retn 1230 ; rts pc / no 1231 gch2: ;1: 1232 000004B7 C605[760C0000]80 mov byte [escap], 80h 1233 ;mov word [escap], 128 1234 ; mov $200,escap / mark presence of \ in command line 1235 000004BE EBC9 jmp short s8 1236 ;jmp short gch0 1237 ; br getc / get next character 1238 gch3: ;2: 1239 000004C0 8B1D[8E0A0000] mov ebx, [param] 1240 000004C6 8A03 mov al, [ebx] 1241 ; movb *param,r0 / pick up substitution character 1242 ; / put in r0 1243 000004C8 08C0 or al, al 1244 000004CA 7407 jz short gch4 1245 ; beq 1f / if end of substitution arg, branch 1246 000004CC FF05[8E0A0000] inc dword [param] 1247 ; inc param / if not end, set for next character 1248 000004D2 C3 retn 1249 ; rts pc / return as though character in ro is normal 1250 ; / input 1251 gch4: ;1: 1252 000004D3 C705[8E0A0000]0000- mov dword [param], 0 1253 000004DB 0000 1254 ; clr param / unset substitution pointer 1255 000004DD EBA4 jmp short gch0 1256 ; br getc / get next char in normal input 1257 gch5: ;3: 1258 000004DF E89FFFFFFF call gch0 1259 ;call getc 1260 ; jsr pc,getc / get digit after $ 1261 000004E4 2C30 sub al, '0' 1262 ; sub $'0,r0 / strip off zone bits 1263 000004E6 3C09 cmp al, 9 1264 ; cmp r0,$9. / compare with digit 9 1265 000004E8 7602 jna short gch6 1266 ; blos 1f / less than or equal 9 1267 000004EA B009 mov al, 9 1268 ; mov $9.,r0 / if larger than 9, force 9 1269 gch6: ;1: 1270 000004EC 8B1D[720C0000] mov ebx, [shellarg] 1271 ; mov shellarg,r1 / get pointer to stack for 1272 ; / this call of shell 1273 000004F2 0FB6C0 movzx eax, al ; al->eax 1274 000004F5 FEC0 inc al 1275 ;inc eax 1276 ; inc r0 / digit +1 1277 000004F7 3B03 cmp eax, [ebx] 1278 ; cmp r0,(r1) / is it less than # of args 1279 ; in this call 1280 000004F9 7388 jnb short gch0 1281 ; bge getc / no, ignore it. so this $n is not replaced 1282 000004FB C0E002 shl al, 2 ; multiply by 4 (24/08/2015) 1283 ;shl al, 1 1284 ;;shl ax, 1 1285 ; asl r0 / yes, multiply by 2 (to skip words) 1286 000004FE 01C3 add ebx, eax 1287 ; add r1,r0 / form pointer to arg pointer (-2) 1288 00000500 8B4304 mov eax, [ebx+4] 1289 00000503 A3[8E0A0000] mov [param], eax 1290 ; mov 2(r0),param / move arg pointer to param 1291 00000508 E96DFFFFFF jmp getc 1292 ; br getc / go to get substitution arg for $n 1293 getbuf: 1294 0000050D B9[680B0000] mov ecx, inbuf 1295 ; mov $inbuf,r0 / move input buffer address 1296 00000512 890D[680C0000] mov [inbufp], ecx 1297 ; mov r0,inbufp / to input buffer pointer 1298 00000518 890D[6C0C0000] mov [einbuf], ecx 1299 ; mov r0,einbuf / and initialize pointer to end of 1300 ; / character string 1301 0000051E 49 dec ecx 1302 ; dec r0 / decrement pointer so can utilize normal 1303 ; / 100p starting at 1f 1304 ; mov r0,0f / initialize address for reading 1st char 1305 0000051F BA01000000 mov edx, 1 1306 gbuf0: ;1: 1307 00000524 41 inc ecx 1308 ; inc 0f / this routine filles inbuf with line from 1309 ; / console - if there is cnc 1310 00000525 51 push ecx 1311 ; edx = 1 1312 sys _read, 0, och 1313 <1> 1314 <1> 1315 <1> 1316 <1> %if %0 >= 2 1317 00000526 BB00000000 <1> mov ebx, %2 1318 <1> %if %0 >= 3 1319 0000052B B9[700C0000] <1> mov ecx, %3 1320 <1> %if %0 = 4 1321 <1> mov edx, %4 1322 <1> %endif 1323 <1> %endif 1324 <1> %endif 1325 00000530 B803000000 <1> mov eax, %1 1326 00000535 CD30 <1> int 30h 1327 00000537 59 pop ecx 1328 ;xor ebx, ebx ; 0 1329 ;sys _read ; sys _read, ebx, ecx, edx ; ebx = 0, edx = 1 1330 ; sys read; 0:0; 1 / read next char into inbuf 1331 00000538 0F82A6000000 jc xit1 1332 ; bcs xit1 / error exit 1333 0000053E 21C0 and eax, eax 1334 ; tst r0 / a zero input is end of file 1335 00000540 0F849E000000 jz xit1 1336 ; beq xit1 / exit 1337 00000546 FF05[6C0C0000] inc dword [einbuf] ; 08/04/2014 (24/08/2015, 32 bit) 1338 0000054C A0[700C0000] mov al, [och] 1339 00000551 803D[79060000]00 cmp byte [_at], 0 1340 00000558 7608 jna short gbuf1 1341 0000055A 3C08 cmp al, 8 ; backspace 1342 0000055C 746B je short gbuf3 1343 0000055E 3C7F cmp al, 127 ; delete 1344 00000560 7460 je short gbuf6 ; 06/12/2013 1345 gbuf1: 1346 ;mov ebx, ecx 1347 ;inc dword [einbuf] 1348 ; inc einbuf / eventually einbuf points to \n 1349 ; / (+1) of this line 1350 00000562 81F9[680C0000] cmp ecx, inbuf + 256 1351 ; cmp 0b,$inbuf+256. / have we exceeded 1352 ; input buffer size 1353 00000568 737A jnb xit1 1354 ; bhis xit1 / if so, exit assume some sort of binary 1355 ; 08/04/2014 1356 0000056A 3C0D cmp al, 0Dh 1357 0000056C 750A jne short gbuf8 1358 0000056E 8B1D[6C0C0000] mov ebx, [einbuf] 1359 00000574 4B dec ebx 1360 00000575 8803 mov [ebx], al 1361 00000577 C3 retn 1362 gbuf8: 1363 00000578 89CB mov ebx, ecx 1364 0000057A 8803 mov [ebx], al 1365 ;cmp al, 0Ah ; \n 1366 ; cmpb *0b,$'\n / end of line? 1367 ;je short gbuf5 1368 ;jne short gbuf1 1369 ; bne 1b / no, go to get next char 1370 ;cmp al, 0Dh ; ENTER 1371 ;je short gbuf5 1372 0000057C 803D[79060000]00 cmp byte [_at], 0 ; at > 0 --> tty input 1373 00000583 769F jna short gbuf0 1374 00000585 3C1B cmp al, 1Bh ; ESC 1375 00000587 7514 jne short gbuf2 1376 00000589 B8[680B0000] mov eax, inbuf 1377 0000058E A3[680C0000] mov [inbufp], eax 1378 00000593 A3[6C0C0000] mov [einbuf], eax 1379 00000598 E9F3FAFFFF jmp nl ; cancel current command, new line 1380 gbuf2: 1381 ; 28/12/2015 1382 0000059D 803D[79060000]00 cmp byte [_at], 0 1383 000005A4 0F867AFFFFFF jna gbuf0 1384 gbuf7: 1385 000005AA 51 push ecx 1386 ;mov [och], al 1387 ; edx = 1 1388 sys _write, 1, och 1389 <1> 1390 <1> 1391 <1> 1392 <1> %if %0 >= 2 1393 000005AB BB01000000 <1> mov ebx, %2 1394 <1> %if %0 >= 3 1395 000005B0 B9[700C0000] <1> mov ecx, %3 1396 <1> %if %0 = 4 1397 <1> mov edx, %4 1398 <1> %endif 1399 <1> %endif 1400 <1> %endif 1401 000005B5 B804000000 <1> mov eax, %1 1402 000005BA CD30 <1> int 30h 1403 ;sys _write, 1, och, 1 ; echo (write char on tty) 1404 000005BC 59 pop ecx 1405 000005BD E962FFFFFF jmp gbuf0 1406 gbuf6: ; DELETE key -> BACKSPACE key 1407 ; mov al, 8 1408 000005C2 C605[700C0000]08 mov byte [och], 8 ; 06/12/2013 1409 gbuf3: 1410 ; 08/04/2014 1411 000005C9 FF0D[6C0C0000] dec dword [einbuf] ; (24/08/2015, 32 bit code) 1412 ; 12/12/2013 1413 000005CF 49 dec ecx 1414 000005D0 81F9[680B0000] cmp ecx, inbuf 1415 000005D6 7203 jb short gbuf4 1416 000005D8 49 dec ecx 1417 ; 08/04/2014 1418 ;jmp short gbuf2 1419 000005D9 EBCF jmp short gbuf7 1420 gbuf4: 1421 ;mov al, 7 1422 000005DB C605[700C0000]07 mov byte [och], 07h ; beep 1423 ; 08/04/2014 1424 ;jmp short gbuf2 1425 000005E2 EBC6 jmp short gbuf7 1426 ;gbuf5: 1427 ; retn 1428 ; rts pc / yes, return 1429 1430 xit1: 1431 sys _exit 1432 <1> 1433 <1> 1434 <1> 1435 <1> %if %0 >= 2 1436 <1> mov ebx, %2 1437 <1> %if %0 >= 3 1438 <1> mov ecx, %3 1439 <1> %if %0 = 4 1440 <1> mov edx, %4 1441 <1> %endif 1442 <1> %endif 1443 <1> %endif 1444 000005E4 B801000000 <1> mov eax, %1 1445 000005E9 CD30 <1> int 30h 1446 ; sys exit 1447 1448 ;----------------------------------------------------------------- 1449 ; DATA 1450 ;----------------------------------------------------------------- 1451 1452 ; /// Messages 1453 1454 000005EB 0D0A msg_unix_sh: db 0Dh, 0Ah 1455 000005ED 526574726F20556E69- db 'Retro Unix 386 v1.1 - shell' 1456 000005F6 78203338362076312E- 1457 000005FF 31202D207368656C6C 1458 ;db 0Dh, 0Ah 1459 msgsh_size equ $ - msg_unix_sh 1460 ;db 0 1461 00000608 30332F30312F323031- db '03/01/2016' 1462 00000611 36 1463 00000612 0D0A00 nextline: db 0Dh, 0Ah, 0 1464 ;Error messages: 1465 00000615 496E707574206E6F74- msgNotFound: db 'Input not found', 0 1466 0000061E 20666F756E6400 1467 00000625 41726720636F756E74- msgArgCount: db 'Arg count', 0 1468 0000062E 00 1469 0000062F 426164206469726563- msgBadDir: db 'Bad directory', 0 1470 00000638 746F727900 1471 0000063D 54727920616761696E- msgTryAgain: db 'Try again', 0 1472 00000646 00 1473 00000647 222720696D62616C61- msgImbalance: db 22h, 27h, 20h, 'imbalance', 0 1474 00000650 6E636500 1475 00000654 496E7075742066696C- msgInputFile: db 'Input file', 0 1476 0000065D 6500 1477 0000065F 4F7574707574206669- msgOutputFile: db 'Output file', 0 1478 00000668 6C6500 1479 0000066B 4E6F20636F6D6D616E- msgNoCmd: db 'No command', 0 1480 00000674 6400 1481 1482 ; /// Commands, files, parameters 1483 1484 ; 27/12/2015 1485 FCAT: ; '>>' 1486 00000676 00 db 0 1487 1488 ;quest: 1489 ;db '?', 0Dh, 0Ah 1490 ; 1491 1492 prompt: 1493 00000677 0D0A db 0Dh, 0Ah 1494 _at: 1495 00000679 4020 db '@ ' 1496 ;<@ > 1497 p_size equ $ - prompt 1498 1499 0000067B 6563686F00 qecho: db 'echo', 0 1500 ; 1501 00000680 636400 qcd: db 'cd', 0 1502 ; 1503 qchdir: 1504 00000683 636864697200 db 'chdir', 0 1505 ; 1506 glogin: 1507 00000689 6C6F67696E00 db 'login', 0 1508 ; 1509 shell: 1510 0000068F 2F62696E2F736800 db '/bin/sh', 0 1511 ; 1512 glob: 1513 00000697 2F6574632F676C6F62- db '/etc/glob', 0 1514 000006A0 00 1515 ; 1516 binpb: 1517 000006A1 2F62696E2F db '/bin/' 1518 ; 1519 1520 ; /// BSS data 1521 1522 bss_start: 1523 1524 ABSOLUTE bss_start 1525 1526 parbuf: 1527 000006A6 resb 1000 1528 ; .=.+1000. 1529 alignb 2 1530 ;.even 1531 param: 1532 00000A8E resd 1 1533 ;.=.+2 1534 glflag: 1535 00000A92 resb 1 1536 00000A93 resb 1 1537 ;.=.+2 1538 infile: 1539 00000A94 resd 1 1540 ; .=.+2 1541 outfile: 1542 00000A98 resd 1 1543 ;.=.+2 1544 ; parp-4 1545 00000A9C resd 1 1546 ;.=.+2 / room for glob 1547 parp: 1548 00000AA0 resb 200 1549 ;.=.+200. 1550 inbuf: 1551 00000B68 resb 256 1552 ;.=.+256. 1553 ;escap: 1554 ;resw 1 1555 ;.=.+2 1556 inbufp: 1557 00000C68 resd 1 1558 ;.=.+2 1559 einbuf: 1560 00000C6C resd 1 1561 ;.=.+2 1562 och: 1563 00000C70 resb 1 1564 00000C71 resb 1 1565 ;.=.+2 1566 shellarg: 1567 00000C72 resd 1 1568 ;.=.+2 1569 escap: 1570 00000C76 resb 1 1571 ; 1572 00000C77 resb 1 1573 1574 bss_end: