1 ; **************************************************************************** 2 ; mkdir386.s (mkdir1.s) - by Erdogan Tan - 10/03/2022 3 ; ---------------------------------------------------------------------------- 4 ; Retro UNIX 386 v1 - makdir -- make a directory 5 ; 6 ; [ Last Modification: 11/03/2022 ] 7 ; 8 ; Derived from (original) UNIX v5 'mkdir.s' (PDP-11 assembly) source Code 9 ; Ref: 10 ; www.tuhs.org (https://minnie.tuhs.org/cgi-bin/utree.pl?file=V5) 11 ; v5root.tar.gz 12 ; **************************************************************************** 13 ; [ v5root.tar - usr/source/s2/mkdir.s (directory archive date: 27-11-1974) ] 14 ; 15 ; Assembler: NASM v2.15 16 ; ((nasm mkdir1.s -l mkdir1.txt -o mkdir1 -Z error.txt)) 17 18 ; 12/01/2022 (Retro UNIX 386 v1.2) 19 ; 13/10/2015 20 21 ; UNIX v1 system calls 22 _rele equ 0 23 _exit equ 1 24 _fork equ 2 25 _read equ 3 26 _write equ 4 27 _open equ 5 28 _close equ 6 29 _wait equ 7 30 _creat equ 8 31 _link equ 9 32 _unlink equ 10 33 _exec equ 11 34 _chdir equ 12 35 _time equ 13 36 _mkdir equ 14 37 _chmod equ 15 38 _chown equ 16 39 _break equ 17 40 _stat equ 18 41 _seek equ 19 42 _tell equ 20 43 _mount equ 21 44 _umount equ 22 45 _setuid equ 23 46 _getuid equ 24 47 _stime equ 25 48 _quit equ 26 49 _intr equ 27 50 _fstat equ 28 51 _emt equ 29 52 _mdate equ 30 53 _stty equ 31 54 _gtty equ 32 55 _ilgins equ 33 56 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 57 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 58 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 59 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 60 _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 61 ; 12/01/2022 - Retro UNIX 386 v1.2 62 ; Retro UNIX 386 v2 system calls 63 _setgid equ 37 64 _getgid equ 38 65 _sysver equ 39 ; (get) Retro Unix 386 version 66 67 ;;; 68 ESCKey equ 1Bh 69 EnterKey equ 0Dh 70 71 %macro sys 1-4 72 ; 03/09/2015 73 ; 13/04/2015 74 ; Retro UNIX 386 v1 system call. 75 %if %0 >= 2 76 mov ebx, %2 77 %if %0 >= 3 78 mov ecx, %3 79 ;%if %0 = 4 80 %if %0 >= 4 ; 11/03/2022 81 mov edx, %4 82 %endif 83 %endif 84 %endif 85 mov eax, %1 86 int 30h 87 %endmacro 88 89 ; Retro UNIX 386 v1 system call format: 90 ; sys systemcall (eax) , , 91 92 ; 11/03/2022 93 ; Note: Above 'sys' macro has limitation about register positions; 94 ; ebx, ecx, edx registers must not be used after their 95 ; positions in sys macro. 96 ; for example: 97 ; 'sys _write, 1, msg, ecx' is defective, because 98 ; ecx will be used/assigned before edx in 'sys' macro. 99 ; correct order may be: 100 ; 'sys _write, 1, msg, eax ; (eax = byte count) 101 102 ;----------------------------------------------------------------- 103 ; text - code 104 ;----------------------------------------------------------------- 105 106 [BITS 32] ; 32-bit intructions (for 80386 protected mode) 107 108 [ORG 0] 109 110 START_CODE: 111 sys _getuid ; sys getuid ; get user id 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 <1> mov ebx, %2 77 <1> %if %0 >= 3 78 <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 00000000 B818000000 <1> mov eax, %1 86 00000005 CD30 <1> int 30h 112 ;mov [uid], eax 113 00000007 A2[5D010000] mov [uid], al ; mov r0,uid 114 115 0000000C 89E6 mov esi, esp ; mov sp,r5 116 0000000E AD lodsd ; number of arguments ; tst (r5)+ 117 ;mov [args], al ; -- (sp) -- dword [esp] -- 118 119 ; temporary - 11/03/2022 120 ; print test message (if argument count = 1) 121 0000000F 48 dec eax 122 00000010 7516 jnz short _loop 123 sys _msg, test_msg, 255, 0Fh 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 00000012 BB[65010000] <1> mov ebx, %2 77 <1> %if %0 >= 3 78 00000017 B9FF000000 <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 0000001C BA0F000000 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 00000021 B823000000 <1> mov eax, %1 86 00000026 CD30 <1> int 30h 124 125 _loop: ; loop: 126 00000028 AD lodsd ; (next) argument's addr in eax ; tst (r5)+ 127 ;dec byte [args] 128 00000029 FF0C24 dec dword [esp] ; dec (sp) 129 ;jg short md_1 ; bgt 1f 130 0000002C 7507 jnz short md_1 131 sys _exit ; sys exit 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 <1> mov ebx, %2 77 <1> %if %0 >= 3 78 <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 0000002E B801000000 <1> mov eax, %1 86 00000033 CD30 <1> int 30h 132 ;hlt: 133 ; nop 134 ; nop 135 ; jmp short hlt 136 137 md_1: ; 1: 138 00000035 8B1E mov ebx, [esi] ; mov (r5),r0 139 00000037 89DD mov ebp, ebx ; -- (r5) -- new sub dir name 140 00000039 BF[92010000] mov edi, buf1 ; mov $buf1,r1 141 0000003E BA[F6010000] mov edx, buf2 ; mov $buf2,r2 142 00000043 29C9 sub ecx, ecx ; clr r3 143 00000045 B42F mov ah, '/' 144 md_2: ; 1: 145 00000047 8A03 mov al, [ebx] ; movb (r0)+,r4 146 00000049 08C0 or al, al 147 0000004B 740D jz short md_3 ; beq 2f 148 0000004D AA stosb ; movb r4,(r1)+ 149 0000004E 8802 mov [edx], al ; movb r4,(r2)+ 150 00000050 42 inc edx 151 00000051 43 inc ebx 152 ;cmp al, '/' ; directory separator 153 00000052 38E0 cmp al, ah ; cmpb r4,$'/ 154 00000054 75F1 jne short md_2 ; bne 1b 155 ; save position of the last dir seperator 156 00000056 89D1 mov ecx, edx ; mov r2,r3 157 00000058 EBED jmp short md_2 ; br 1b 158 md_3: ; 2: 159 ;mov al, '/' 160 0000005A 88E0 mov al, ah 161 0000005C AA stosb ; movb $'/,(r1)+ 162 0000005D B02E mov al, '.' ; movb $'.,(r1)+ 163 0000005F AA stosb 164 00000060 28C0 sub al, al ; 0 165 00000062 8807 mov [edi], al ; clrb (r1) 166 00000064 C705[61010000]- mov dword [dir], dot ; mov $dot,dir 166 0000006A [8B010000] 167 0000006E 21C9 and ecx, ecx ; tst r3 168 00000070 7417 jz short md_4 ; beq 1f 169 00000072 C705[61010000]- mov dword [dir], buf2 ; mov $buf2,dir 169 00000078 [F6010000] 170 0000007C 8801 mov [ecx], al ; 0 ; clrb (r3) 171 0000007E 81F9[F7010000] cmp ecx, buf2+1 ; cmp r3,$buf2+1 172 00000084 7403 je short md_4 ; beq 1f 173 00000086 49 dec ecx 174 00000087 8801 mov [ecx], al ; 0 ; clrb -(r3) / ??? 175 md_4: ; 1: 176 ;test word [uid], 0FFFFh ; (Retro UNIX 386 v1.2) 177 ; (Retro UNIX 386 v1.0 & v1.1) 178 00000089 F605[5D010000]FF test byte [uid], 0FFh ; tstb uid ; (pdp-11 unix v5) 179 00000090 742F jz short md_6 ; beq 2f ; root (super user) 180 sys _stat, [dir], stbuf 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 00000092 8B1D[61010000] <1> mov ebx, %2 77 <1> %if %0 >= 3 78 00000098 B9[5A020000] <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 0000009D B812000000 <1> mov eax, %1 86 000000A2 CD30 <1> int 30h 181 ; sys stat; dir:..; stbuf / status of parent dir 182 000000A4 726A jc short error ; bes error 183 184 ; inode mode/flags (from sysstat output) 185 ; (Retro UNIX 386 v1 & v1.1 &v1.2) 186 000000A6 66A1[5C020000] mov ax, [stbuf+2] ; mov stbuf+4,r0 187 ; (pdp-11 unix v5) 188 ; get owner's uid (from sysstat output) 189 ;mov bx, [stbuf+6] ; (Retro UNIX 386 v1.2) 190 000000AC 8A1D[5F020000] mov bl, [stbuf+5] ; (Retro UNIX 386 v1.0 & v1.1) 191 ;cmp bx, [uid] ; (Retro UNIX 386 v1.2) 192 ; (Retro UNIX 386 v1.0 & v1.1) 193 000000B2 3A1D[5D010000] cmp bl, [uid] ; cmpb uid,stbuf+7 ; (unix v5) 194 000000B8 7503 jne short md_5 ; bne 1f 195 ; owner's r/w/e permissions 196 ;shr ax, 6 ; ash $-6,r0 197 ; ... 198 ; unix v5 inode mode r/w/e bits: 199 ; IEXEC = 40h (execute, owner) 200 ; bit3 = 08h (execute, group) 201 ; bit0 = 01h (execute, others) 202 ; IWRITE = 80h (write, owner) 203 ; bit4 = 10h (write, group) 204 ; bit1 = 02h (write, others) 205 ; IREAD = 100h (read, owner) 206 ; bit5 = 20h (read, group) 207 ; bit2 = 04h (read, others) 208 ; 209 000000BA C0E802 shr al, 2 ; Retro UNIX 386 v1 & v1.1 210 ; unix v1 inode mode r/w/e bits: 211 ; bit 0 = write perm, others, 1 212 ; bit 1 = read perm, others, 2 213 ; bit 2 = write perm, owner, 4 214 ; bit 3 = read perm, owner, 8 215 ; bit 4 = executable file, 16 216 ; 217 ;shr ax, 6 ; Retro UNIX 386 v1.2 (& v2) 218 ; unix v7 inode mode r/w/e bits: 219 ; bit 0 = exec perm, others, 1 220 ; bit 1 = write perm, others, 2 221 ; bit 2 = read perm, owner, 4 222 ; bit 3 = exec perm, group, 8 223 ; bit 4 = write perm, group, 16 224 ; bit 5 = read perm, group, 32 225 ; bit 6 = exec perm, owner, 64 226 ; bit 7 = write perm, owner, 128 227 ; bit 8 = read perm, owner, 256 228 ; ... 229 md_5: 230 ;ror al, 1 ; ror r0 ; (bit 6 to cf) 231 ;ror al, 1 ; ror r0 ; (bit 7 to cf) 232 ;;ror al, 2 ; bit 7 to cf (for unix v5/v7) 233 ; (Retro UNIX 386 v1 & v1.1) 234 000000BD D0C8 ror al, 1 ; bit 2 to cf (for unix v1) 235 ; (Retro UNIX 386 v1.2 & v2) 236 ;ror al, 2 ; bit 7 to cf 237 000000BF 734F jnc short error ; bcc error 238 ; / no write permission in parent 239 md_6: 240 ;mov ebx, ebp ; mov (r5),0f 241 ;sys _mkdir, ebp, 0C1FFh ; Retro UNIX 386 v1.2 242 ; sys makdir; 0:..; 140777; 0 243 ; ... 244 ; 0C1FFh = 140777 (octal) = 1100000111111111b 245 ; bit15 = allocated flag/bit 246 ; bit14 = directory flag/bit 247 ; bit8 to bit0 = r/w/e permissions 248 249 sys _mkdir, ebp, 0C00Fh ; Retro UNIX 386 v1 & v1.1 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 000000C1 89EB <1> mov ebx, %2 77 <1> %if %0 >= 3 78 000000C3 B90FC00000 <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 000000C8 B80E000000 <1> mov eax, %1 86 000000CD CD30 <1> int 30h 250 251 ; Retro UNIX 386 v1: (& v1.1) 252 ; mkdir mode setting: 1100000000001111b 253 ; (unixcopy.com sett: 1100000000001110b) 254 ; bit15 = allocated flag 255 ; bit14 = directory flag 256 ; bit13 = file modified flag (not used) 257 ; bit12 = large file flag 258 ; bit11 to bit6 are not used 259 ; bit5 = setuid on execution flag 260 ; bit4 = executable file flag 261 ; bit3 to bit0 = r/w/e permissions 262 ; 263 ; Retro UNIX 386 v1.2: (& v2) 264 ; mkdir mode setting: 1100000111111111b 265 ; (unixcopy/unixhdcp: 1100000111101101b) 266 ; bit15 = regular file (not device) flag 267 ; bit14 = directory flag 268 ; bit13 = reserved flag (or char special) 269 ; bit12 = large file flag 270 ; bit11 = setuid on execution flag 271 ; bit10 = setgid on execution flag 272 ; bit9 = use extents flag (not used) 273 ; bit8 to bit0 = r/w/e permissions 274 275 000000CF 723F jc short error ; bes error ; / prob already exists 276 277 ;mov ebx, ebp ; mov (r5),0f 278 ;movzx ecx, byte [uid] 279 ;sys _chown, ebp 280 sys _chown, ebp, [uid] ; sys chown; 0:..; uid:.. 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 000000D1 89EB <1> mov ebx, %2 77 <1> %if %0 >= 3 78 000000D3 8B0D[5D010000] <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 000000D9 B810000000 <1> mov eax, %1 86 000000DE CD30 <1> int 30h 281 ;mov ebx, ebp ; mov (r5),0f 282 sys _link, ebp, buf1 ; sys link; 0:..; buf1 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 000000E0 89EB <1> mov ebx, %2 77 <1> %if %0 >= 3 78 000000E2 B9[92010000] <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 000000E7 B809000000 <1> mov eax, %1 86 000000EC CD30 <1> int 30h 283 000000EE 7220 jc short error ; bes error 284 000000F0 B02E mov al, '.' 285 000000F2 AA stosb ; movb $'.,(r1)+ 286 000000F3 28C0 sub al, al ; 0 287 000000F5 8807 mov [edi], al ; clrb (r1) 288 ;mov ebx, [dir] ; mov dir,0f 289 sys _link, [dir], buf1 ; sys link; 0:..; buf1 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 000000F7 8B1D[61010000] <1> mov ebx, %2 77 <1> %if %0 >= 3 78 000000FD B9[92010000] <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 00000102 B809000000 <1> mov eax, %1 86 00000107 CD30 <1> int 30h 290 00000109 7205 jc short error 291 0000010B E918FFFFFF jmp _loop ;jnc _loop ; bec loop 292 293 error: 294 ;sys _msg, nl, 2, 07h 295 sys _write, 1, nl, 2 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 00000110 BB01000000 <1> mov ebx, %2 77 <1> %if %0 >= 3 78 00000115 B9[88010000] <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 0000011A BA02000000 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 0000011F B804000000 <1> mov eax, %1 86 00000124 CD30 <1> int 30h 296 297 00000126 89EA mov edx, ebp ; mov (r5),r0 298 ; mov r0,0f 299 ; clr 0f+2 300 err1: ;1: 301 00000128 F602FF test byte [edx], 0FFh ; tstb (r0)+ 302 0000012B 7403 jz short err2 ; beq 1f 303 0000012D 42 inc edx ; inc 0f+2 304 0000012E EBF8 jmp short err1 ; br 1b 305 err2: ; 1: 306 00000130 29EA sub edx, ebp ; count 307 00000132 740E jz short err3 308 ;mov ebx, 1 ; mov $1,r0 309 ;;;sys _write, ebx, ebp, edx 310 ;;sys _write, 1, ebp, edx 311 ; sys write; 0:..; .. 312 sys _write, 1, ebp 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 00000134 BB01000000 <1> mov ebx, %2 77 <1> %if %0 >= 3 78 00000139 89E9 <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 0000013B B804000000 <1> mov eax, %1 86 00000140 CD30 <1> int 30h 313 ;sys _msg, ebp, edx, 0Ch 314 err3: 315 ;mov ebx, 1 ; mov $1,r0 316 sys _write, 1, ques, 4 ; (SPACE+'?'+CR+LF) 72 <1> 73 <1> 74 <1> 75 <1> %if %0 >= 2 76 00000142 BB01000000 <1> mov ebx, %2 77 <1> %if %0 >= 3 78 00000147 B9[8D010000] <1> mov ecx, %3 79 <1> 80 <1> %if %0 >= 4 81 0000014C BA04000000 <1> mov edx, %4 82 <1> %endif 83 <1> %endif 84 <1> %endif 85 00000151 B804000000 <1> mov eax, %1 86 00000156 CD30 <1> int 30h 317 ;sys _write, 1, ques, 3 ; (' ?'+CR) 318 ; sys write; ques; 3 319 ;sys _msg, ques, 4, 0Ch 320 321 00000158 E9CBFEFFFF jmp _loop ; br loop 322 323 ;----------------------------------------------------------------- 324 ; data - initialized data 325 ;----------------------------------------------------------------- 326 327 ;args: db 0 328 0000015D 00000000 uid: dd 0 329 ;uid: db 0 330 00000161 00000000 dir: dd 0 331 332 ; ---------------------------------------------------------------- 333 334 test_msg: 335 00000165 0D0A db 0Dh, 0Ah 336 00000167 4D4B44495220627920- db 'MKDIR by Erdogan TAN - 11/03/2022' 336 00000170 4572646F67616E2054- 336 00000179 414E202D2031312F30- 336 00000182 332F32303232 337 nl: 338 00000188 0D0A00 db 0Dh, 0Ah, 0 339 340 0000018B 2E00 dot: db '.', 0 341 0000018D 203F0D0A ques: db ' ?', 0Dh, 0Ah 342 343 ;----------------------------------------------------------------- 344 ; bss - uninitialized data 345 ;----------------------------------------------------------------- 346 347 00000191 90 align 2 348 349 bss_start: 350 351 ABSOLUTE bss_start 352 353 00000192 buf1: resb 100 ; new sub directory name/path buffer (make) 354 000001F6 buf2: resb 100 ; parent directory name/path buffer (perms) 355 0000025A stbuf: resb 40 ; sysstat output buffer 356 ;stbuf: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data) 357 358 ; 10/03/2022 359 ;----------------------------------------------------------------- 360 ; Original UNIX v5 - mkdir (utility) source code (mkdir.s) 361 ; in PDP-11 (unix) assembly language 362 ;----------------------------------------------------------------- 363 ;/ makdir -- make a directory 364 ; 365 ; sys getuid 366 ; mov r0,uid 367 ; mov sp,r5 368 ; tst (r5)+ 369 ; 370 ;loop: 371 ; tst (r5)+ 372 ; dec (sp) 373 ; bgt 1f 374 ; sys exit 375 ;1: 376 ; mov (r5),r0 377 ; mov $buf1,r1 378 ; mov $buf2,r2 379 ; clr r3 380 ;1: 381 ; movb (r0)+,r4 382 ; beq 2f 383 ; movb r4,(r1)+ 384 ; movb r4,(r2)+ 385 ; cmpb r4,$'/ 386 ; bne 1b 387 ; mov r2,r3 388 ; br 1b 389 ;2: 390 ; movb $'/,(r1)+ 391 ; movb $'.,(r1)+ 392 ; clrb (r1) 393 ; mov $dot,dir 394 ; tst r3 395 ; beq 1f 396 ; mov $buf2,dir 397 ; clrb (r3) 398 ; cmp r3,$buf2+1 399 ; beq 1f 400 ; clrb -(r3) / ??? 401 ;1: 402 ; tstb uid 403 ; beq 2f 404 ; sys stat; dir:..; stbuf / status of parent dir 405 ; bes error 406 ; mov stbuf+4,r0 407 ; cmpb uid,stbuf+7 408 ; bne 1f 409 ; ash $-6,r0 410 ;1: 411 ; ror r0 412 ; ror r0 413 ; bcc error / no write permission in parent 414 ;2: 415 ; mov (r5),0f 416 ; sys makdir; 0:..; 140777; 0 417 ; bes error / prob already exists 418 ; mov (r5),0f 419 ; sys chown; 0:..; uid:.. 420 ; mov (r5),0f 421 ; sys link; 0:..; buf1 422 ; bes error 423 ; movb $'.,(r1)+ 424 ; clrb (r1) 425 ; mov dir,0f 426 ; sys link; 0:..; buf1 427 ; bec loop 428 ; 429 ;error: 430 ; mov (r5),r0 431 ; mov r0,0f 432 ; clr 0f+2 433 ;1: 434 ; tstb (r0)+ 435 ; beq 1f 436 ; inc 0f+2 437 ; br 1b 438 ;1: 439 ; mov $1,r0 440 ; sys write; 0:..; .. 441 ; mov $1,r0 442 ; sys write; ques; 3 443 ; br loop 444 ; 445 ;dot: <.\0> 446 ;ques: < ?\n> 447 ; .even 448 ; 449 ;.bss 450 ;buf1: .=.+100. 451 ;buf2: .=.+100. 452 ;stbuf: .=.+40. 453 ;