     1                                  ; ****************************************************************************
     2                                  ; cp8086.s (cp0.s) - by Erdogan Tan - 20/04/2022
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; Retro UNIX 8086 v1 - copy -- cp oldfile newfile
     5                                  ;
     6                                  ; [ Last Modification: 10/05/2022 ]
     7                                  ;
     8                                  ; Derived from (original) UNIX v7 (& v7 x86) 'cp.c' source Code
     9                                  ; Ref:
    10                                  ; www.tuhs.org (https://minnie.tuhs.org)
    11                                  ; v7.tar.gz
    12                                  ; ****************************************************************************
    13                                  ; [ v7.tar - usr/src/cmd/cp.c (archive date: 10-1-1979) ]
    14                                  ;
    15                                  ; Assembler: NASM v2.15
    16                                  ; ((nasm cp8086.s -l cp8086.txt -o cp8086.bin -Z error.txt))
    17                                  ;
    18                                  ; cp1.s - 21/04/2022 - Retro UNIX 386 v1.2 (modified unix v7 inode)
    19                                  ; cp0.s - 21/04/2022 - Retro UNIX 386 v1 & v1.1
    20                                  ; cp8086.s - 22/04/2022 - Retro UNIX 8086 v1 (16 bit 'cp0.s') 
    21                                  
    22                                  ; 12/01/2022 (Retro UNIX 386 v1.2)
    23                                  ; 13/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                                  _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
    63                                  ; 12/01/2022 - Retro UNIX 386 v1.2
    64                                  ; Retro UNIX 386 v2 system calls
    65                                  _setgid	equ 37
    66                                  _getgid	equ 38
    67                                  _sysver	equ 39 ; (get) Retro Unix 386 version
    68                                  
    69                                  ;;;
    70                                  ESCKey equ 1Bh
    71                                  EnterKey equ 0Dh
    72                                  
    73                                  ;%macro sys 1-4
    74                                  ;   ; 03/09/2015	
    75                                  ;   ; 13/04/2015
    76                                  ;   ; Retro UNIX 386 v1 system call.		
    77                                  ;   %if %0 >= 2   
    78                                  ;       mov ebx, %2
    79                                  ;       %if %0 >= 3    
    80                                  ;           mov ecx, %3
    81                                  ;           ;%if %0 = 4
    82                                  ;           %if	%0 >= 4 ; 11/03/2022
    83                                  ;		mov edx, %4   
    84                                  ;           %endif
    85                                  ;       %endif
    86                                  ;   %endif
    87                                  ;   mov eax, %1
    88                                  ;   int 30h	   
    89                                  ;%endmacro
    90                                  
    91                                  %macro sys 1-4
    92                                      ; Retro UNIX 8086 v1 system call.
    93                                      %if %0 >= 2   
    94                                          mov bx, %2
    95                                          %if %0 >= 3
    96                                              mov cx, %3
    97                                              %if %0 >= 4
    98                                                 mov dx, %4
    99                                              %endif
   100                                          %endif
   101                                      %endif
   102                                      mov ax, %1
   103                                      int 20h
   104                                  %endmacro
   105                                  
   106                                  ;; Retro UNIX 386 v1 system call format:
   107                                  ;; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
   108                                  
   109                                  ;; 11/03/2022
   110                                  ;; Note: Above 'sys' macro has limitation about register positions;
   111                                  ;;	ebx, ecx, edx registers must not be used after their
   112                                  ;;	positions in sys macro.
   113                                  ;; for example:
   114                                  ;;	'sys _write, 1, msg, ecx' is defective, because
   115                                  ;;	 ecx will be used/assigned before edx in 'sys' macro.
   116                                  ;; correct order may be:
   117                                  ;;	'sys _write, 1, msg, eax ; (eax = byte count)
   118                                  
   119                                  ; Retro UNIX 8086 v1 system call format:
   120                                  ; sys systemcall (ax) <arg1 (bx)>, <arg2 (cx)>, <arg3 (dx)>
   121                                  
   122                                  struc stat
   123                                  	; Note: This is for Retro UNIX v1 'sysstat' output !!!
   124                                  	; (34 bytes)
   125 00000000 ????                    	.inode:  resw 1	
   126 00000002 ????                    	.mode:	 resw 1
   127 00000004 ??                      	.nlinks: resb 1
   128 00000005 ??                      	.uid:	 resb 1
   129 00000006 ????                    	.size:	 resw 1
   130 00000008 <res 10h>               	.dskptr: resw 8
   131 00000018 ????????                	.ctime:	 resd 1
   132 0000001C ????????                	.mtime:	 resd 1
   133 00000020 ????                    	.rsvd:   resw 1
   134                                  	.strucsize:
   135                                  endstruc   
   136                                  
   137                                  ;struc stat
   138                                  ;	; Note: This is for Retro UNIX v1.2 'sysstat' output !!!
   139                                  ;	; (66 bytes)
   140                                  ;	.inode:  resw 1	
   141                                  ;	.mode:	 resw 1
   142                                  ;	.nlinks: resw 1 
   143                                  ;	.uid:	 resw 1
   144                                  ;	.gid:	 resb 1
   145                                  ;	.size_h: resb 1
   146                                  ;	.size:	 resd 1
   147                                  ;	.dskptr: resd 10
   148                                  ;	.atime:	 resd 1
   149                                  ;	.mtime:	 resd 1
   150                                  ;	.ctime:  resd 1
   151                                  ;	.strucsize:
   152                                  ;endstruc   
   153                                  
   154                                  ;S_IFMT   equ 0F000h ; /* type of file */
   155                                  ;S_IFDIR  equ 04000h ; /* directory */
   156                                  ;S_IFCHR  equ 02000h ; /* character special */
   157                                  ;S_IFBLK  equ 06000h ; /* block special */
   158                                  ;S_IFREG  equ 08000h ; /* regular */
   159                                  ;S_ISUID  equ 00800h ; /* set user id on execution */
   160                                  ;S_ISGID  equ 00400h ; /* set group id on execution */
   161                                  ;S_IREAD  equ 00100h ; /* read permission, owner */
   162                                  ;S_IWRITE equ 00080h ; /* write permission, owner */
   163                                  ;S_IEXEC  equ 00040h ; /* execute/search permission, owner */
   164                                  
   165                                  ; 23/04/2022
   166                                  ; 21/04/2022 - UNIX v1 inode
   167                                  ; byte 1
   168                                  S_ALLOC  equ 080h ; Allocated flag
   169                                  S_IFDIR  equ 040h ; Directory flag
   170                                  S_IFMDF  equ 020h ; File modified flag (always on)
   171                                  S_IFLRG  equ 010h ; Large File flag
   172                                  ; byte 0
   173                                  S_ISUID  equ 020h ; Set User ID On Execution flag
   174                                  S_IEXEC  equ 010h ; Executable File flag
   175                                  S_IREAD  equ 008h ; Owner's Read Permission flag
   176                                  S_IWRITE equ 004h ; Owner's Write Permission flag
   177                                  
   178                                  BSIZE equ 512
   179                                  
   180                                  ;-----------------------------------------------------------------
   181                                  ;  text - code
   182                                  ;-----------------------------------------------------------------
   183                                  
   184                                  ;[BITS 32] ; 32-bit intructions (for 80386 protected mode)
   185                                  
   186                                  [BITS 16] ; 16-bit (x86 real mode) intructions
   187                                  
   188                                  [ORG 0] 
   189                                  
   190                                  START_CODE:
   191                                  	; 10/05/2022
   192                                  	; 09/05/2022
   193                                  	; 22/04/2022 - 16 bit version (Retro UNIX 8086 v1) 
   194                                  	;
   195                                  	; 20/04/2022
   196                                  	; main(argc, argv)
   197                                  
   198                                  	;mov	esi, esp		
   199                                  	;mov	edi, esi
   200                                  	;lodsd		; number of arguments
   201                                  	;;mov	edi, esi			
   202                                  	;;mov	[argc], eax
   203                                  	;mov	[argc], al
   204                                  
   205                                  	; 22/04/2022
   206 00000000 89E6                    	mov	si, sp
   207 00000002 89F7                    	mov	di, si
   208 00000004 AD                      	lodsw
   209                                  	;mov	[argc], ax
   210 00000005 A2[9E01]                	mov	[argc], al
   211                                  
   212                                  	;if (argc < 3) 
   213                                  	;   goto usage;
   214                                  
   215                                  	;;cmp	eax, 3
   216                                  	;cmp	ax, 3
   217 00000008 3C03                    	cmp	al, 3
   218 0000000A 732D                    	jnb	short cp_0  ; if (argc > 3) {
   219 0000000C FEC8                    	dec	al	; 21/04/2022
   220 0000000E 7506                    	jnz	short cp_usage
   221                                  
   222                                  	;sys	_msg, program_msg, 255, 0Fh
   223                                  	; 22/04/2022
   224 00000010 B8[9F01]                	mov	ax, program_msg ; asciiz message address
   225 00000013 E80B00                  	call	print_msg
   226                                  
   227                                  cp_usage:
   228                                     ; fprintf(stderr, "Usage: cp: f1 f2; or cp f1 ... fn d2\n");
   229                                  	;sys	_msg, usage_msg, 255, 07h
   230 00000016 B8[D701]                	mov	ax, usage_msg
   231 00000019 E80500                  	call	print_msg
   232                                  cp_exit:
   233                                  	sys	_exit	; sys exit
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94                              <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 0000001C B80100              <1>  mov ax, %1
   103 0000001F CD20                <1>  int 20h
   234                                  ;hlt:
   235                                  ;	nop
   236                                  ;	nop
   237                                  ;	jmp	short hlt
   238                                  
   239                                  print_msg:
   240                                  	; 22/04/2022
   241                                  	; Modified registers: ax, bx, cx, dx
   242                                  strlen:
   243                                  	; ax = asciiz string address
   244 00000021 89C3                    	mov	bx, ax
   245 00000023 4B                      	dec	bx
   246                                  nextchr:
   247 00000024 43                      	inc	bx
   248 00000025 803F00                  	cmp	byte [bx], 0
   249 00000028 77FA                    	ja	short nextchr
   250                                  	;cmp	[bx], 0Dh
   251                                  	;ja	short nextchr
   252 0000002A 29C3                    	sub	bx, ax
   253                                  	; bx = asciiz string length
   254                                  	;retn
   255                                  print_str:
   256 0000002C 89DA                    	mov	dx, bx
   257                                  	sys	_write, 1, ax
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 0000002E BB0100              <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 00000031 89C1                <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000033 B80400              <1>  mov ax, %1
   103 00000036 CD20                <1>  int 20h
   258                                  
   259 00000038 C3                      	retn
   260                                  
   261                                  cp_0:
   262                                  	;mov	edx, eax ; [argc]
   263                                  	;; 21/04/2022
   264                                  	;;;dec	edx  ; argc-1
   265                                  	;;dec	dl
   266                                  	;shl	dl, 2 ; * 4 
   267                                  	;add	edi, edx
   268                                  
   269                                  	; 22/04/2022
   270 00000039 89C2                    	mov	dx, ax
   271 0000003B D0E2                    	shl	dl, 1 ; * 2 ; 16 bit argument pointers
   272 0000003D 01D7                    	add	di, dx
   273                                  
   274                                  	; 21/04/2022
   275 0000003F 3C03                    	cmp	al,3
   276 00000041 7613                    	jna	short cp_1
   277                                  
   278                                  	;sys	_stat, [edi], stbuf2
   279                                  	sys	_stat, [di], stbuf2  ; 22/04/2022
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000043 8B1D                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 00000045 B9[8202]            <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000048 B81200              <1>  mov ax, %1
   103 0000004B CD20                <1>  int 20h
   280 0000004D 72C7                    	jc	short cp_usage
   281                                  
   282                                  	;; check retro unix v2 inode flags
   283                                  	;;	(a bit different than unix v7 inode flags)
   284                                  	;; if it is a directory..
   285                                  	;;	regular file flag and dir flag must be 1
   286                                  	;mov	al, [stbuf2+stat.mode+1]
   287                                  	;and	al, S_IFDIR|S_IFREG
   288                                  	;cmp	al, S_IFDIR|S_IFREG ; directory ?
   289                                  	;jne	short cp_usage ; no
   290                                  	
   291                                  	;; check if it is a device file
   292                                  	;;test	al, S_IFREG ; regular file ?
   293                                  	;;jz	short cp_usage ; no
   294                                  	;;and	al, S_IFDIR ; directory ?
   295                                  	;;jz	short cp_usage ; no
   296                                  
   297                                  	; 21/04/2022
   298                                  	; check (unix v1 inode) directory flag
   299 0000004F F606[8502]40            	test	byte [stbuf2+stat.mode+1], S_IFDIR ; directory ?
   300 00000054 74C0                    	jz	short cp_usage ; no
   301                                   
   302                                  cp_1:	
   303                                  	; esi = esp+4 = argv[0] ; executable file name (cp)
   304                                  	;lodsd	; 21/04/2022
   305 00000056 AD                      	lodsw ; 22/04/2022 - Retro UNIX 8086 v1
   306                                  cp_loop: ; for(i=1; i<argc-1;i++)
   307                                  	;lodsd
   308                                  	; ((esi = esp+8 = argv[1] ; (old) file 1))
   309                                  
   310                                  	; esi = argv[i] 
   311                                   	; edi = argv[argc-1] ; *
   312                                  	; 22/04/2022 - Retro UNIX 8086 v1 (16 bit Retro UNIX)
   313                                  	; si = argv[i]
   314                                  	; di = argv[argc-1] ; *
   315                                   	
   316 00000057 E81D00                  	call	copy
   317 0000005A 7304                    	jnc	short cp_2
   318                                  
   319 0000005C FE06[7D02]              	inc	byte [errors]
   320                                  cp_2:
   321                                  	;lodsd	; 21/04/2022
   322                                  	;cmp	esi, edi
   323                                  	;jb	short cp_loop
   324                                  
   325                                  	; 22/04/2022 - Retro UNIX 8086 v1
   326 00000060 AD                      	lodsw
   327 00000061 39FE                    	cmp	si, di
   328 00000063 72F2                    	jb	short cp_loop
   329                                  
   330                                  	; bypass 'OK.' message if there was an error
   331 00000065 803E[7D02]00            	cmp	byte [errors], 0
   332 0000006A 77B0                    	ja	short cp_exit
   333                                  cp_ok:
   334                                  	;sys	_msg, ok_msg, 255, 07h
   335                                  	; 22/04/2022
   336 0000006C B8[7502]                	mov	ax, ok_msg
   337 0000006F E8AFFF                  	call	print_msg
   338                                  ;cp_exit:
   339                                  	sys	_exit	; sys exit
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94                              <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000072 B80100              <1>  mov ax, %1
   103 00000075 CD20                <1>  int 20h
   340                                  
   341                                  ;_halt:
   342                                  ;	nop
   343                                  ;	jmp	short _halt
   344                                  
   345                                  copy:	; copy(from, to)
   346                                  	;
   347                                  	; 10/05/2022
   348                                  	; 09/05/2022
   349                                  	; 22/04/2022 - 16 bit version (Retro UNIX 8086 v1) 
   350                                  	; 21/04/2022
   351                                  	; 20/04/2022
   352                                  	; INPUT:
   353                                  	;	esi = pointer to file name to be copied
   354                                  	;  	edi = ptr to new file name or destination dir
   355                                  	; OUTPUT:
   356                                  	;	cf = 0 -> OK
   357                                  	;	cf = 1 -> Error !
   358                                  	;
   359                                  	; Modified registers: eax, ebx, ecx, edx, ebp
   360                                  	;
   361                                  	
   362                                  	; open (old) file for read
   363                                  	;sys	_open, [esi], 0
   364                                  	sys	_open, [si], 0 ; 22/04/2022
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000077 8B1C                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 00000079 B90000              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 0000007C B80500              <1>  mov ax, %1
   103 0000007F CD20                <1>  int 20h
   365 00000081 7313                    	jnc	short cp_3
   366                                  	
   367                                  	; esi = file name (from)
   368                                  
   369                                  	;fprintf(stderr, "cp: cannot open %s\n", from);
   370                                  	;	return(1);
   371                                  
   372                                  	;sys	_msg, cno_err_msg, 255, 07h
   373                                  	; 22/04/2022
   374 00000083 B8[0002]                	mov	ax, cno_err_msg
   375 00000086 E898FF                  	call	print_msg
   376                                  
   377                                  	; file name (from) 
   378                                  	;sys	_msg, [esi], 255, 07h
   379                                  	; 22/04/2022
   380 00000089 8B04                    	mov	ax, [si]
   381                                  write_err_nl:	; 24/04/2022
   382 0000008B E893FF                  	call	print_msg
   383                                  write_nl:
   384                                  	; new/next line
   385                                  	;sys	_msg, nextline, 255, 07h
   386                                  	; 22/04/2022
   387 0000008E B8[FD01]                	mov	ax, nextline
   388 00000091 E88DFF                  	call	print_msg
   389                                  	;
   390 00000094 F9                      	stc	; return with error (cf=1)
   391 00000095 C3                      	retn
   392                                  
   393                                  cp_3:
   394                                  	;mov	[fold], eax ; file (descriptor) number
   395                                  	; 22/04/2022
   396 00000096 A3[7E02]                	mov	[fold], ax ; file (descriptor) number
   397                                  
   398                                  	; (from)
   399                                  	sys	_fstat, [fold], stbuf1
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000099 8B1E[7E02]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 0000009D B9[A402]            <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 000000A0 B81C00              <1>  mov ax, %1
   103 000000A3 CD20                <1>  int 20h
   400                                  
   401                                  	; 10/05/2022 (new -retro unix 8086 v1- kernel)
   402                                  	; save device number
   403                                  	; ((device number = ax return from sysfstat))
   404 000000A5 A3[C602]                	mov	[idev1], ax
   405                                  
   406                                  	; save mode
   407                                  	;mov	ax, [stbuf1.mode]
   408                                  	;mov	[mode], ax
   409                                  	
   410                                  	; (to)
   411                                  	;;sys	_stat, [edi], stbuf2  ; stat(to, &stbuf2)
   412                                  	; 22/04/2022
   413                                  	;sys	_stat, [di], stbuf2
   414                                  	;jnc	short cp_4
   415                                  	;jmp	cp_9
   416                                  	; 22/04/2022
   417 000000A8 8B2D                    	mov	bp, [di]
   418                                  	sys	_stat, bp, stbuf2  ; stat(to, &stbuf2)
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 000000AA 89EB                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 000000AC B9[8202]            <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 000000AF B81200              <1>  mov ax, %1
   103 000000B2 CD20                <1>  int 20h
   419                                  	;jnc	short cp_4
   420                                  	;jmp	cp_9
   421 000000B4 7262                    	jc	short cp_9
   422                                  cp_4:
   423                                  	; /* is target a directory? */
   424                                  
   425                                  	;; check retro unix v2 inode flags
   426                                  	;;	(a bit different than unix v7 inode flags)
   427                                  	;; regular file flag and dir flag must be 1 for a dir
   428                                  	;mov	al, [stbuf2+stat.mode+1]
   429                                  	;and	al, S_IFDIR|S_IFREG
   430                                  	;cmp	al, S_IFDIR|S_IFREG ; directory ?
   431                                  	;jne	short cp_8 ; no, overwrite (create file)
   432                                  			   ; (if the new file is not same file)
   433                                  
   434                                  	;; check if it is a device file
   435                                  	;;test	al, S_IFREG ; regular file ?
   436                                  	;;jz	short cp_error ; no
   437                                  	;;and	al, S_IFDIR ; directory ?
   438                                  	;;jz	short cp_error ; no
   439                                  
   440                                  	; 21/04/2022
   441                                  	; check (unix v1 inode) directory flag
   442 000000B6 F606[8502]40            	test	byte [stbuf2+stat.mode+1], S_IFDIR ; directory ?
   443 000000BB 7439                    	jz	short cp_8 ; no, overwrite (create file)
   444                                  			   ; (if the new file is not same file)
   445                                  
   446                                  	; add (old) file name to (destination ) path
   447                                  	; (directory name +'/'+ file name)  
   448                                  	
   449                                  	;mov	ebp, esi   ; save esi
   450                                  	;mov	esi, [edi] ; directory name address
   451                                  	;mov	ebx, edi   ; save edi			
   452                                  	;mov	edi, iobuf ; (new) path name buffer addr
   453                                  	; 22/04/2022 - Retro UNIX 8086 v1 (16 bit utility)
   454 000000BD 89F5                    	mov	bp, si
   455 000000BF 8B35                    	mov	si, [di]
   456 000000C1 89FB                    	mov	bx, di
   457 000000C3 BF[C802]                	mov	di, iobuf
   458                                  
   459                                  	; p1 = from;
   460                                  	; p2 = to;
   461                                  	; bp = iobuf;
   462                                  cp_5:	; while(*bp++ = *p2++)
   463 000000C6 AC                      	lodsb	
   464 000000C7 AA                      	stosb
   465 000000C8 20C0                    	and	al, al
   466 000000CA 75FA                    	jnz	short cp_5
   467                                  	;mov	byte [edi-1], '/' ; bp[-1] = '/';
   468                                  	; 22/04/2022
   469 000000CC C645FF2F                	mov	byte [di-1], '/'
   470                                  	; p2 = bp
   471                                  	;mov	edx, edi
   472                                  	;mov	esi, [ebp] ; *p1 ; from
   473                                  	; 22/04/2022
   474 000000D0 89FA                    	mov	dx, di
   475 000000D2 8B7600                  	mov	si, [bp]
   476                                  
   477                                  cp_6:	; while(*bp = *p1++)
   478 000000D5 AC                      	lodsb
   479 000000D6 AA                      	stosb
   480 000000D7 08C0                    	or	al, al
   481 000000D9 7408                    	jz	short cp_7
   482 000000DB 3C2F                    	cmp	al, '/' ; if (*bp++ == '/')
   483 000000DD 75F6                    	jne	short cp_6
   484                                  	; bp = p2
   485                                  	; 21/04/2022
   486                                  	;mov	edi, edx ; (discard path before file name)
   487                                  	; 22/04/2022
   488 000000DF 89D7                    	mov	di, dx
   489 000000E1 EBF2                    	jmp	short cp_6
   490                                  cp_7:	
   491                                  	;mov	esi, ebp ; restore esi
   492                                  	;mov	edi, ebx ; restore edi
   493                                  	; 22/04/2022
   494 000000E3 89EE                    	mov	si, bp
   495 000000E5 89DF                    	mov	di, bx
   496                                  	; to = iobuf
   497                                  	;mov	ebp, iobuf
   498                                  	; 22/04/2022
   499 000000E7 BD[C802]                	mov	bp, iobuf	
   500                                  	
   501                                  	;sys	_stat, ebp, stbuf2  ; stat(to, &stbuf2) >= 0
   502                                  	sys	_stat, bp, stbuf2 ; 22/04/2022
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 000000EA 89EB                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 000000EC B9[8202]            <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 000000EF B81200              <1>  mov ax, %1
   103 000000F2 CD20                <1>  int 20h
   503 000000F4 7222                    	jc	short cp_10 ; create new file
   504                                  
   505                                  cp_8:
   506                                  	;if (stbuf1.st_dev == stbuf2.st_dev &&
   507                                  	;   stbuf1.st_ino == stbuf2.st_ino) {
   508                                  	;	fprintf(stderr, "cp: cannot copy file to itself.\n");
   509                                  	; 	return(1);
   510                                  
   511                                  	; 10/05/2022 (new -retro unix 8086 v1- kernel)
   512                                  	; (is same device ?)
   513                                  	; ((device number: ax return from sysstat))
   514                                  	; ax = [idev2]
   515                                  
   516 000000F6 3B06[C602]              	cmp	ax, [idev1]	
   517 000000FA 751C                    	jne	short cp_10
   518                                  
   519 000000FC A1[A402]                	mov	ax, [stbuf1+stat.inode]
   520 000000FF 3B06[8202]              	cmp	ax, [stbuf2+stat.inode]
   521 00000103 7513                    	jne	short cp_10
   522                                  
   523                                  	; same file ! error...
   524                                  	;mov	ebp, cncis_err_msg ; error message
   525                                  	; 09/05/2022
   526                                  	; 22/04/2022
   527 00000105 BD[1302]                	mov	bp, cncis_err_msg ; error message 
   528                                  	; esi = file name (from)
   529                                  write_err_msg:
   530                                  	;sys	_msg, ebp, 255, 07h
   531                                  	; 22/04/2022
   532 00000108 89E8                    	mov	ax, bp
   533                                  	; ax = error message address
   534 0000010A E814FF                  	call	print_msg
   535                                  	;
   536                                  	; close (old) file
   537                                  	sys	_close, [fold]
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 0000010D 8B1E[7E02]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000111 B80600              <1>  mov ax, %1
   103 00000114 CD20                <1>  int 20h
   538 00000116 F9                      	stc	; return with error (cf=1)
   539 00000117 C3                      	retn
   540                                  
   541                                  cp_9:	
   542                                  	; 22/04/2022
   543                                  	; bp = [di]
   544                                  	;; new file (asciiz name address)
   545                                  	;;mov	ebp, [edi] ; 21/04/2022
   546                                  	;mov	bp, [di] ; 22/04/2022
   547                                  
   548                                  	; create new file (truncate if it exists) 
   549                                  cp_10:
   550                                  	; fnew = creat(to, mode)
   551                                  	;movzx 	ecx, word [stbuf1+stat.mode]
   552                                  	; ecx = mode 
   553                                  	; 22/04/2022
   554 00000118 8B0E[A602]              	mov	cx, [stbuf1+stat.mode]
   555                                  	;sys	_creat, ebp
   556                                  	sys	_creat, bp ; 22/04/2022
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 0000011C 89EB                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 0000011E B80800              <1>  mov ax, %1
   103 00000121 CD20                <1>  int 20h
   557 00000123 7314                    	jnc	short cp_11
   558                                  
   559                                  	;if ((fnew = creat(to, mode)) < 0) {
   560                                  	;	fprintf(stderr, "cp: cannot create %s\n", to);
   561                                  	;	close(fold);
   562                                  	;	return(1);
   563                                  
   564                                  cp_10_err:
   565                                  	; 24/04/2022
   566                                  	sys	_close, [fold]
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000125 8B1E[7E02]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000129 B80600              <1>  mov ax, %1
   103 0000012C CD20                <1>  int 20h
   567                                  
   568                                  	; error message
   569                                  	;sys	_msg, ccf_err_msg, 255, 07h
   570                                  	; 22/04/2022
   571 0000012E B8[3702]                	mov	ax, ccf_err_msg ; 'can not create' error msg
   572 00000131 E8EDFE                  	call	print_msg
   573                                  
   574                                  	; and file name (to) -at the end of error message-
   575                                  	;sys	_msg, ebp, 255, 07h
   576                                  	; 22/04/2022
   577 00000134 89E8                    	mov	ax, bp	 ; (new) file name
   578                                  	;call	print_msg 
   579                                   
   580                                  	; write next line (move cursor to next line)
   581                                  	; and return (from this/copy subroutine)
   582                                  	;jmp	write_nl
   583 00000136 E952FF                  	jmp	write_err_nl ; 24/04/2022
   584                                  
   585                                  cp_11:
   586                                  	; 25/04/2022
   587                                  	; temporary solution
   588                                  	; to overcome freezing/failure problem while
   589                                  	; creating a new file (which does not appear
   590                                  	; when the target file exists) 
   591                                  	;
   592                                  	; [ possible reason:
   593                                  	;        buffer flush/update problem
   594                                  	;		in retro unix 8086 v1 kernel code ]
   595                                  	; 25/04/2022
   596                                  	; close new file
   597                                  	sys	_close, ax ; flush buffers ?
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000139 89C3                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 0000013B B80600              <1>  mov ax, %1
   103 0000013E CD20                <1>  int 20h
   598                                  	; open it again 
   599                                  	sys	_open, bp, 1 ; open for write
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000140 89EB                <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 00000142 B90100              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000145 B80500              <1>  mov ax, %1
   103 00000148 CD20                <1>  int 20h
   600 0000014A 72D9                    	jc	short cp_10_err ; nonsense !?
   601                                  	
   602                                  	; 21/04/2022 
   603                                  	;mov	[fnew], eax
   604                                  	; 22/04/2022 - Retro UNIX 8086 v1
   605 0000014C A3[8002]                	mov	[fnew], ax ; (16 bit)
   606                                  
   607                                  cp_rw_next:
   608                                  	; while(n = read(fold, iobuf, BSIZE))
   609                                  	sys	_read, [fold], iobuf, BSIZE
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 0000014F 8B1E[7E02]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 00000153 B9[C802]            <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98 00000156 BA0002              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000159 B80300              <1>  mov ax, %1
   103 0000015C CD20                <1>  int 20h
   610 0000015E 730E                    	jnc	short cp_12
   611                                  
   612                                  	;if (n < 0) {
   613                                  	;   fprintf(stderr, "cp: read error\n");
   614                                  
   615                                  	; write read error message
   616                                  	;mov	ebp, crd_err_msg
   617 00000160 BD[4C02]                	mov	bp, crd_err_msg ; 22/04/2022	
   618                                  
   619                                  cp_rw_err:
   620                                  	; 21/04/2022
   621                                  	; cf = 1
   622                                  	sys	_close, [fnew]	
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000163 8B1E[8002]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000167 B80600              <1>  mov ax, %1
   103 0000016A CD20                <1>  int 20h
   623 0000016C EB9A                    	jmp	write_err_msg
   624                                  
   625                                  cp_12:
   626                                  	; eax = read count
   627                                  	; eax = 0 -> eof
   628                                  	;or	eax, eax
   629 0000016E 09C0                    	or	ax, ax ; 22/04/2022 (Retro UNIX 8086 v1)
   630 00000170 7419                    	jz	short cp_14 ; eof
   631                                  
   632                                  	;mov	ebp, eax  ; n
   633 00000172 89C2                    	mov	dx, ax ; 22/04/2022
   634                                  	; write(fnew, iobuf, n)
   635                                  	;sys	_write, [fnew], iobuf, ebp
   636                                  	; 22/04/2022
   637                                  	sys	_write, [fnew], iobuf
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000174 8B1E[8002]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96 00000178 B9[C802]            <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 0000017B B80400              <1>  mov ax, %1
   103 0000017E CD20                <1>  int 20h
   638 00000180 7204                    	jc	short cp_13
   639                                  
   640                                  	;if (write(fnew, iobuf, n) != n)
   641                                  	;   fprintf(stderr, "cp: write error.\n");
   642                                  	;   close(fold);
   643                                  	;   close(fnew);
   644                                  	;   return(1);
   645                                  
   646                                  	; eax = written bytes
   647                                  	;cmp	eax, ebp
   648                                  	;;je	short cp_11 ; read next (block)
   649                                  	;; 21/04/2022
   650                                  	;je	short cp_rw_next
   651                                  	; 22/04/2022
   652 00000182 39D0                    	cmp	ax, dx
   653 00000184 74C9                    	je	short cp_rw_next		
   654                                  
   655                                  	; error !
   656                                  	;; eax < ebp --> cf = 1
   657                                  	; 22/04/2022 - Retro UNIX 8086 v1
   658                                  	; ax < dx --> cf = 1
   659                                  cp_13:
   660                                  	; close new file
   661                                  	; and then write error mesage
   662                                  	; and then close old file
   663                                  	; and then write (move cursor to) next line
   664                                  	; and then return (from subroutine) 
   665                                  	;sys	_close, [fnew]
   666                                  
   667                                  	; write error message
   668                                  	;mov	ebp, cwr_err_msg
   669                                  	; 22/04/2022
   670 00000186 BD[6002]                	mov	bp, cwr_err_msg
   671                                  	;
   672                                  	;jmp	short write_err_msg
   673                                  	; 21/04/2022
   674 00000189 EBD8                    	jmp	short cp_rw_err
   675                                  
   676                                  	; eof
   677                                  cp_14:
   678                                  	;close(fold);
   679                                  	;close(fnew);
   680                                  	;return(0);
   681                                  	
   682                                  	sys	_close, [fold]
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 0000018B 8B1E[7E02]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 0000018F B80600              <1>  mov ax, %1
   103 00000192 CD20                <1>  int 20h
   683                                  	sys	_close, [fnew]
    92                              <1> 
    93                              <1>  %if %0 >= 2
    94 00000194 8B1E[8002]          <1>  mov bx, %2
    95                              <1>  %if %0 >= 3
    96                              <1>  mov cx, %3
    97                              <1>  %if %0 >= 4
    98                              <1>  mov dx, %4
    99                              <1>  %endif
   100                              <1>  %endif
   101                              <1>  %endif
   102 00000198 B80600              <1>  mov ax, %1
   103 0000019B CD20                <1>  int 20h
   684                                  	
   685                                  	;clc
   686 0000019D C3                      	retn
   687                                  	
   688                                  ;-----------------------------------------------------------------
   689                                  ;  data - initialized data
   690                                  ;-----------------------------------------------------------------
   691                                  
   692                                  ;argc:	dd 0
   693 0000019E 00                      argc:	db 0
   694                                  
   695                                  ; ----------------------------------------------------------------
   696                                  
   697                                  program_msg:
   698 0000019F 0D0A                    	db  0Dh, 0Ah
   699 000001A1 526574726F20554E49-     	db  'Retro UNIX 8086 v1 COPY by Erdogan TAN - 10/05/2022'
   699 000001AA 582038303836207631-
   699 000001B3 20434F505920627920-
   699 000001BC 4572646F67616E2054-
   699 000001C5 414E202D2031302F30-
   699 000001CE 352F32303232       
   700 000001D4 0D0A00                  	db  0Dh, 0Ah, 0
   701                                  
   702                                  usage_msg:
   703 000001D7 0D0A                    	db  0Dh, 0Ah
   704 000001D9 55736167653A206370-     	db  'Usage: cp: f1 f2; or cp f1 ... fn d2'
   704 000001E2 3A2066312066323B20-
   704 000001EB 6F7220637020663120-
   704 000001F4 2E2E2E20666E206432 
   705                                  nextline:
   706 000001FD 0D0A00                  	db  0Dh, 0Ah, 0
   707                                  
   708                                  cno_err_msg:
   709 00000200 0D0A                    	db 0Dh, 0Ah
   710 00000202 63703A2063616E6E6F-     	db 'cp: cannot open '
   710 0000020B 74206F70656E20     
   711 00000212 00                      	db 0
   712                                  cncis_err_msg:
   713 00000213 0D0A                    	db 0Dh, 0Ah
   714 00000215 63703A2063616E6E6F-     	db 'cp: cannot copy file to itself.'
   714 0000021E 7420636F7079206669-
   714 00000227 6C6520746F20697473-
   714 00000230 656C662E           
   715 00000234 0D0A00                  	db 0Dh, 0Ah, 0
   716                                  
   717                                  ccf_err_msg:
   718 00000237 0D0A                    	db 0Dh, 0Ah
   719 00000239 63703A2063616E6E6F-     	db 'cp: cannot create '
   719 00000242 742063726561746520 
   720 0000024B 00                      	db 0
   721                                  
   722                                  crd_err_msg:
   723 0000024C 0D0A                    	db 0Dh, 0Ah
   724 0000024E 63703A207265616420-     	db 'cp: read error.'
   724 00000257 6572726F722E       
   725 0000025D 0D0A00                  	db 0Dh, 0Ah, 0
   726                                  
   727                                  cwr_err_msg:
   728 00000260 0D0A                    	db 0Dh, 0Ah
   729 00000262 63703A207772697465-     	db 'cp: write error.'
   729 0000026B 206572726F722E     
   730 00000272 0D0A00                  	db 0Dh, 0Ah, 0
   731                                  
   732                                  ok_msg:
   733 00000275 0D0A                    	db  0Dh, 0Ah
   734 00000277 4F4B2E                  	db  'OK.'
   735 0000027A 0D0A00                  	db  0Dh, 0Ah, 0
   736                                  
   737 0000027D 00                      errors:	db 0
   738                                  
   739                                  ;-----------------------------------------------------------------
   740                                  ;  bss - uninitialized data
   741                                  ;-----------------------------------------------------------------
   742                                  
   743                                  align 2
   744                                  
   745                                  bss_start:
   746                                  
   747                                  ABSOLUTE bss_start
   748                                  
   749                                  ; 20/04/2022 - Retro UNIX 386 v1 & v1.1 & v1.2
   750                                  ;fold:	resd 1
   751                                  ;fnew:	resd 1
   752                                  ; 22/04/2022 - Retro UNIX 8086 v1
   753 0000027E ????                    fold:	resw 1
   754 00000280 ????                    fnew:	resw 1 
   755                                  
   756                                  ;stbuf2: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data)
   757                                  ;stbuf1: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data)
   758                                  ; 21/04/2022
   759 00000282 <res 22h>               stbuf2: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data)
   760 000002A4 <res 22h>               stbuf1: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data)
   761                                  ; 10/05/2022
   762 000002C6 ????                    idev1:	resw 1 ; device number (0= root, >0 or 1 = mounted)	
   763                                  ;idev2:	resw 1 ; device number (0= root, >0 or 1 = mounted)
   764                                  
   765 000002C8 <res 200h>              iobuf:	resb BSIZE ; resb 512 ; path name buffer
   766                                  
   767                                  ; 20/04/2022
   768                                  ;-----------------------------------------------------------------
   769                                  ; Original UNIX v7 - cp (utility) c source code (cp.c)
   770                                  ;-----------------------------------------------------------------
   771                                  ;/* UNIX V7 source code: see www.tuhs.org for details. */;
   772                                  ;
   773                                  ;/*
   774                                  ; * cp oldfile newfile
   775                                  ; */
   776                                  ;
   777                                  ;#define BSIZE	512
   778                                  ;#include <stdio.h>
   779                                  ;#include <sys/types.h>
   780                                  ;#include <sys/stat.h>
   781                                  ;struct	stat stbuf1, stbuf2;
   782                                  ;char iobuf[BSIZE];
   783                                  ;
   784                                  ;main(argc, argv)
   785                                  ;char *argv[];
   786                                  ;{
   787                                  ;	register i, r;
   788                                  ;
   789                                  ;	if (argc < 3) 
   790                                  ;		goto usage;
   791                                  ;	if (argc > 3) {
   792                                  ;		if (stat(argv[argc-1], &stbuf2) < 0)
   793                                  ;			goto usage;
   794                                  ;		if ((stbuf2.st_mode&S_IFMT) != S_IFDIR) 
   795                                  ;			goto usage;
   796                                  ;	}
   797                                  ;	r = 0;
   798                                  ;	for(i=1; i<argc-1;i++)
   799                                  ;		r |= copy(argv[i], argv[argc-1]);
   800                                  ;	exit(r);
   801                                  ;usage:
   802                                  ;	fprintf(stderr, "Usage: cp: f1 f2; or cp f1 ... fn d2\n");
   803                                  ;	exit(1);
   804                                  ;}
   805                                  ;
   806                                  ;copy(from, to)
   807                                  ;char *from, *to;
   808                                  ;{
   809                                  ;	int fold, fnew, n;
   810                                  ;	register char *p1, *p2, *bp;
   811                                  ;	int mode;
   812                                  ;	if ((fold = open(from, 0)) < 0) {
   813                                  ;		fprintf(stderr, "cp: cannot open %s\n", from);
   814                                  ;		return(1);
   815                                  ;	}
   816                                  ;	fstat(fold, &stbuf1);
   817                                  ;	mode = stbuf1.st_mode;
   818                                  ;	/* is target a directory? */
   819                                  ;	if (stat(to, &stbuf2) >=0 &&
   820                                  ;	   (stbuf2.st_mode&S_IFMT) == S_IFDIR) {
   821                                  ;		p1 = from;
   822                                  ;		p2 = to;
   823                                  ;		bp = iobuf;
   824                                  ;		while(*bp++ = *p2++)
   825                                  ;			;
   826                                  ;		bp[-1] = '/';
   827                                  ;		p2 = bp;
   828                                  ;		while(*bp = *p1++)
   829                                  ;			if (*bp++ == '/')
   830                                  ;				bp = p2;
   831                                  ;		to = iobuf;
   832                                  ;	}
   833                                  ;	if (stat(to, &stbuf2) >= 0) {
   834                                  ;		if (stbuf1.st_dev == stbuf2.st_dev &&
   835                                  ;		   stbuf1.st_ino == stbuf2.st_ino) {
   836                                  ;			fprintf(stderr, "cp: cannot copy file to itself.\n");
   837                                  ;			return(1);
   838                                  ;		}
   839                                  ;	}
   840                                  ;	if ((fnew = creat(to, mode)) < 0) {
   841                                  ;		fprintf(stderr, "cp: cannot create %s\n", to);
   842                                  ;		close(fold);
   843                                  ;		return(1);
   844                                  ;	}
   845                                  ;	while(n = read(fold,  iobuf,  BSIZE)) {
   846                                  ;		if (n < 0) {
   847                                  ;			fprintf(stderr, "cp: read error\n");
   848                                  ;			close(fold);
   849                                  ;			close(fnew);
   850                                  ;			return(1);
   851                                  ;		} else
   852                                  ;			if (write(fnew, iobuf, n) != n) {
   853                                  ;				fprintf(stderr, "cp: write error.\n");
   854                                  ;				close(fold);
   855                                  ;				close(fnew);
   856                                  ;				return(1);
   857                                  ;			}
   858                                  ;	}
   859                                  ;	close(fold);
   860                                  ;	close(fnew);
   861                                  ;	return(0);
   862                                  ;}
