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