汇编语言实现DOS下的文件目录清单(DIR)
题目名称:文件目录清单(Dir)
程序设计要求:
1.显示指定目录下的文件清单,包括文件名、扩展名、文件大小(十进制数表示)、最后修改日期和时间等项内容(不显示属性为隐含的文件,各项内容之间以制表符的位置起始);
2.根据参数确定显示方式(W:紧凑显示,每个文件只显示文件的文件名及扩展名;P:显示文件的全部信息,对清单进行分页处理,满屏后暂停,并提示按任意键继续显示剩余的信息;无参数则当满屏后作滚屏处理);
3.清单显示完成后,给出所有文件占用空间及磁盘可用空间(十进制数表示)。
这学期选修了汇编语言课程实践,实现了题目中的全部要求,肝project的时候临近考试了,只是用了几个晚上达到了最低纲领,实现的不是很优雅,代码中甚至有一定的冗余代码,仅供参考。
实习报告见github
实现起来本身不算难,但当时找不到详尽的文档就很烦,这里贴几个当时的参考资料:
http://stanislavs.org/helppc/dta.html
http://www2.ift.ulaval.ca/~marchand/ift17583/dosints.pdf
http://www.plantation-productions.com/Webster/www.artofasm.com/DOS/pdf/ch13.pdf
1 data segment 2 org 80h 3 psp dw 0ffh dup(?) 4 ddd db 'diretory:$' 5 head db 'name size type date time ',0dh,0ah,24h 6 space db ' ',24h 7 dir db 'xxx <dir> ',24h 8 fn db 200h dup(?) 9 dta db 128 dup(?) 10 msg db 'press any key to continue...',0dh,0ah,24h 11 newline db 0dh,0ah,24h 12 count db ? 13 show db 0 14 base_10 dw 10 15 used_32bits_high dw 0 16 used_32bits_low dw 0 17 var_32bits_high dw 0 18 var_32bits_low dw 0 19 quotidient_32bits_high dw 0 20 quotidient_32bits_low dw 0 21 negate_mask equ 0FFFFh 22 lowest_signed_32bits_high dw 8000h 23 lowest_signed_32bits_low dw 0000h 24 lowest_signed_32bits_string db '-2147483648$' 25 qhigh dw 0 26 rhigh dw 0 27 qlow dw 0 28 rlow dw 0 29 qhigh_redundant dw 0 30 rhigh_redundant dw 0 31 q_0 dw 0 32 qhigh0 equ 0h 33 rhigh0 equ 0h 34 qhigh1 equ 1999h 35 rhigh1 equ 6h 36 qhigh2 equ 3333h 37 rhigh2 equ 2h 38 qhigh3 equ 4CCCh 39 rhigh3 equ 8h 40 qhigh4 equ 6666h 41 rhigh4 equ 4h 42 qhigh5 equ 8000h 43 rhigh5 equ 0h 44 qhigh6 equ 9999h 45 rhigh6 equ 6h 46 qhigh7 equ 0B333h 47 rhigh7 equ 2h 48 qhigh8 equ 0CCCCh 49 rhigh8 equ 8h 50 qhigh9 equ 0E666h 51 rhigh9 equ 4h 52 filenum db 0 53 dirnum db 0 54 filespace db ' File(s) $' 55 dirspace db ' Dir(s) $' 56 bytes db ' Bytes.',0dh,0ah,24h 57 bytesfree db ' Bytes free.',0dh,0ah,24h 58 data ends 59 60 stack1 segment stack 61 dw 0ffh dup(0) 62 stack1 ends 63 64 main segment 65 assume cs:main,ds:data,ss:stack1 66 org 100h 67 cmdln equ byte ptr es:[82h] ;command line data 68 69 ;------------------------------------------------------------------------------- 70 p1 proc near 71 push ds 72 mov ax,data 73 mov ds,ax 74 pop psp 75 mov es,psp 76 mov ax,stack1 77 mov ss,ax 78 mov cl,byte ptr es:[80h] 79 cmp cl,0 ;command line? 80 jne l4 ;yes 81 no_dir: 82 mov ah,19h ;no 83 int 21h 84 add al,'a' 85 mov byte ptr[fn],al 86 mov word ptr[fn+1],5c3ah 87 mov ah,47h ;current directory but no driver,so have to 88 lea si,fn[3] ;use 19h to add myself 89 sub al,'a' 90 mov dl,al 91 int 21h 92 93 lea di,fn[3] ;to point di to the end of the diretory 94 95 l7: 96 mov al,[di] 97 cmp al,0 98 je l6 99 inc di 100 jmp l7 101 102 l4: 103 lea si,cmdln 104 lea di,fn 105 cld 106 xor ch,ch 107 dec cl 108 ;rep movsb 109 110 lea di,fn 111 lea bx,cmdln 112 lea bp,fn 113 114 repeat: 115 116 mov al,es:[bx] 117 mov ds:[bp],al 118 inc bx 119 inc bp 120 inc di 121 dec cl 122 jnz repeat 123 124 l6: 125 mov cl,[di-1] ;end by '\' ? 126 cmp cl,92 ;92-->'\' 127 je l8 ;yes 128 ;mov byte ptr[di],92 ;no 129 ;inc di 130 131 cmp byte ptr[di-1],'W' 132 jne notW 133 mov al,1 134 mov [show],al 135 notW: 136 cmp byte ptr[di-1],92 ;'\' 137 je l8 138 dec di 139 jz no_dir 140 jmp notW 141 142 l8: 143 mov word ptr[di],0a0dh ;end by $ for printing 144 mov byte ptr[di+2],24h 145 mov ah,09h ;print "directory:*:\*\*\" 146 ;lea dx,ddd 147 mov dx,offset ddd 148 int 21h 149 mov ah,09h 150 lea dx,fn 151 int 21h 152 mov ah,09h 153 mov al,[show] 154 cmp al,1 155 je w_head 156 lea dx,head 157 int 21h 158 w_head: 159 160 161 mov word ptr[di],2e2ah ;add '*.* ' at the end 162 mov word ptr[di+2],002ah 163 164 l5: 165 lea dx,dta 166 mov ah,1ah 167 int 21h 168 mov ah,4eh ;first fdt matched 169 mov cx,16h ;all file 170 lea dx,fn 171 int 21h 172 173 call outp ;print first file imformation 174 mov cl,1 175 mov count,cl 176 ;------------- 177 ;mov ah,4ch 178 ;int 21h 179 ;----------- 180 l2: 181 mov ah,4fh ;next fdt 182 int 21h 183 jc l0 ;end when no file any more 184 185 call outp ;print next file imformation 186 mov cl,count 187 inc cl 188 mov count,cl 189 190 cmp cl,14h 191 ja pause 192 pause_end: 193 jmp l2 194 195 pause: 196 mov dl,[show] 197 cmp dl,1 198 je pause_end 199 mov ah,9h;move 9 into ah (9 is the interrupt for output) 200 lea dx,msg;move the message into dx 201 int 21h ;call dos function 202 mov ah,7h;move 7 into ah (7 is the interrupt for input) 203 mov dx,00h;get the actual input 204 int 21h ;dos interrupt 205 mov cl,0 206 mov count,cl 207 jmp pause_end 208 209 l0: ;int 20h ;end 210 mov dl,[show] 211 cmp dl,0 212 je not_newline 213 214 mov ah,2 ;new line 215 mov dl,0dh 216 int 21h 217 mov ah,2 218 mov dl,0ah 219 int 21h 220 221 not_newline: 222 lea dx,[space] 223 mov ah,09h 224 int 21h 225 mov al,[filenum] 226 xor ah,ah 227 mov [var_32bits_low],ax 228 xor al,al 229 mov [var_32bits_high],ax 230 call showspace 231 232 lea dx,filespace 233 mov ah,09h 234 int 21h 235 236 mov ax,[used_32bits_high] 237 mov [var_32bits_high],ax 238 mov ax,[used_32bits_low] 239 mov [var_32bits_low],ax 240 call showspace 241 lea dx,bytes 242 mov ah,09h 243 int 21h 244 245 246 lea dx,[space] 247 mov ah,09h 248 int 21h 249 250 mov al,[dirnum] 251 xor ah,ah 252 mov [var_32bits_low],ax 253 xor al,al 254 mov [var_32bits_high],ax 255 call showspace 256 257 lea dx,[dirspace] 258 mov ah,09h 259 int 21h 260 ;-----------------------get free space 261 mov dl,fn[0] 262 263 sub dl,'a' 264 mov ah,36h 265 int 21h 266 267 mul bx 268 mov bx,cx 269 xor cx,cx 270 271 call mymul32 272 273 mov var_32bits_high,cx 274 mov [var_32bits_low],bx 275 call showspace 276 277 lea dx,bytesfree 278 mov ah,09h 279 int 21h 280 281 mov ah,4ch 282 int 21h 283 284 285 p1 endp 286 287 pspace proc near 288 push dx 289 push ax 290 mov dl, ' ' 291 mov ah, 2h 292 int 21h 293 pop ax 294 pop dx 295 pspace endp 296 297 printax proc near 298 cmp ax,0 299 je pret 300 push bx 301 push cx 302 push ax 303 push dx 304 305 xor cx,cx 306 ;jmp lable1 307 b11: xor dx,dx 308 lable1: mov si,10 309 div si 310 311 push dx 312 inc cx 313 cmp ax,0 314 jne b11 315 316 b22: pop dx 317 add dl,30h 318 mov ah,2 319 int 21h 320 loop b22 321 322 pop dx 323 pop ax 324 pop cx 325 pop bx 326 pret: ret 327 printax endp 328 329 printax_hex proc near 330 mov cx,4 ; print 4 hex digits (= 16 bits) 331 .print_digit: 332 rol ax,4 ; move the currently left-most digit into the least significant 4 bits 333 mov dl,al 334 and dl,0Fh ; isolate the hex digit we want to print 335 add dl,'0' ; and convert it into a character.. 336 cmp dl,'9' ; ... 337 jbe .ok ; ... 338 add dl,7 ; ... (for 'A'..'F') 339 .ok: ; ... 340 push ax ; save EAX on the stack temporarily 341 mov ah,2 ; INT 21H / AH=2: write character to stdout 342 int 21h 343 pop ax ; restore EAX 344 loop .print_digit 345 ret 346 printax_hex endp 347 348 ;----------------------------print the file imfomation-------------------- 349 outp proc near 350 push bx 351 push dx 352 push ax 353 push cx 354 mov cx,16 355 lea bx,dta[1eh] ;print name 356 o0: 357 mov dl,[bx] 358 cmp dl,0 359 je o1 360 mov ah,2 361 int 21h 362 dec cx 363 inc bx 364 jmp o0 365 366 367 o1: 368 mov ah,02h ;print space between name and size 369 mov dl,20h 370 int 21h 371 loop o1 372 call b2d ;print size and dir type 373 ;----judge is W 374 mov dl,[show] 375 cmp dl,1 376 je w_file 377 call datm ;print date and time 378 379 380 mov ah,2 ;new line 381 mov dl,0dh 382 int 21h 383 mov ah,2 384 mov dl,0ah 385 int 21h 386 w_file: 387 pop cx 388 pop ax 389 pop dx 390 pop bx 391 ret 392 outp endp 393 ;------------------------------print size------------------------------------- 394 b2d proc near 395 push cx 396 push ax 397 push dx 398 push si 399 400 401 xor cx,cx 402 lea si,dta[1ah] 403 mov ax,[si] 404 call add_used_space 405 call add_filenum 406 cmp ax,0 407 je b4 408 ;----judge is W 409 mov dl,[show] 410 cmp dl,1 411 je b5 412 xor cx,cx 413 b1: 414 xor dx,dx 415 mov si,10 416 div si 417 418 push dx 419 inc cx 420 cmp ax,0 421 jne b1 422 mov si,cx 423 424 b2: 425 pop dx 426 add dl,30h 427 mov ah,2 428 int 21h 429 loop b2 430 431 mov cx,10 432 sub cx,si 433 b3: 434 mov ah,02h 435 mov dl,20h 436 int 21h 437 loop b3 438 439 ;----judge is W 440 mov dl,[show] 441 cmp dl,1 442 je b5 443 444 mov ah,9 445 lea dx,space 446 int 21h 447 jmp b5 448 449 b4: 450 call add_dirnum 451 call sub_filenum 452 ;----judge is W 453 mov dl,[show] 454 cmp dl,1 455 je b5 456 mov ah,09h 457 lea dx,dir 458 int 21h 459 460 b5: 461 pop si 462 pop dx 463 pop ax 464 pop cx 465 ret 466 b2d endp 467 468 add_filenum proc near 469 push ax 470 mov al,[filenum] 471 inc al 472 mov [filenum],al 473 pop ax 474 ret 475 add_filenum endp 476 477 add_dirnum proc near 478 push ax 479 mov al,[dirnum] 480 inc al 481 mov [dirnum],al 482 pop ax 483 ret 484 add_dirnum endp 485 486 sub_filenum proc near 487 push ax 488 mov al,[filenum] 489 dec al 490 mov [filenum],al 491 pop ax 492 ret 493 sub_filenum endp 494 495 ;------------------------------print date and time----------------------------------------------- 496 datm proc near 497 push ax 498 push bx 499 push cx 500 push dx 501 push di 502 503 504 lea bx,dta[18h];data 505 mov di,[bx] 506 mov cx,7;year 507 xor bx,bx 508 d1: 509 shl di,1 510 rcl bx,1 511 loop d1 512 add bx,1980 513 call bi2de 514 mov ah,2 515 mov dl,"." 516 int 21h 517 518 mov cx,4;month 519 xor bx,bx 520 d2: 521 shl di,1 522 rcl bx,1 523 loop d2 524 call bi2de 525 mov ah,2 526 mov dl,"." 527 int 21h 528 529 mov cx,5;day 530 xor bx,bx 531 d3: 532 shl di,1 533 rcl bx,1 534 loop d3 535 call bi2de 536 mov cx,3 537 d7: 538 mov ah,2 539 mov dl," " 540 int 21h 541 loop d7 542 543 ;time 544 lea bx,dta[16h] 545 mov di,[bx] 546 mov cx,5;hour 547 xor bx,bx 548 d5: 549 shl di,1 550 rcl bx,1 551 loop d5 552 call bi2de 553 mov ah,2 554 mov dl,":" 555 int 21h 556 mov cx,6;min 557 xor bx,bx 558 d6: 559 shl di,1 560 rcl bx,1 561 loop d6 562 call bi2de 563 564 565 pop di 566 pop dx 567 pop cx 568 pop bx 569 pop ax 570 ret 571 datm endp 572 573 ;---------------------------------binary2decimal----------------------------- 574 bi2de proc near 575 push ax 576 577 cmp bx,9 578 ja bi0 579 mov ah,2 580 mov dl,'0' 581 int 21h 582 bi0: 583 xor cx,cx 584 mov ax,bx 585 bi1: 586 xor dx,dx 587 mov si,10 588 div si 589 590 push dx 591 inc cx 592 cmp ax,0 593 jne bi1 594 595 bi2: 596 pop dx 597 add dl,30h 598 mov ah,2 599 int 21h 600 loop bi2 601 602 pop ax 603 ret 604 bi2de endp 605 606 ;----------------multiplies dx:ax x cx:bx return dx:ax:cx:bx 607 mymul32 proc near 608 609 push si 610 push di 611 mov si,dx ;save op1hi in si 612 mov di,ax ;save op1lo in di 613 mul bx ;op1l0 x op2lo 614 push ax ;save 1st (32 bit) pp. on stack 615 push dx 616 ; 617 mov ax,si ;op1hi in ax 618 mul bx ;op1hi x op2l0 619 pop bx ;add 2nd (48 bit) pp. to pp1 620 add ax,bx 621 adc dx,0 622 push ax 623 mov bx,dx ;pp1 + pp2 in bx:tos:tos+2 624 ; 625 mov ax,di ;op1lo in ax 626 mul cx ;op1lo x op2hi 627 pop di ;add 3rd (48 bit) pp. to pp1 + pp2 628 add di,ax 629 push di 630 mov di,0 631 adc bx,dx 632 adc di,0 ;pp1+pp2+pp3 in di:bx:tos:tos+2 633 ; 634 mov ax,si ;op1hi in ax 635 mul cx ;op1hi x op2hi 636 add ax,bx ;add 4th (64 bit) pp. to pp1+pp2+pp3 637 adc dx,di 638 pop cx 639 pop bx ;final product in dx:ax:cx:bx 640 ; 641 pop di 642 pop si 643 ret 644 mymul32 endp 645 646 showspace proc near 647 push ax 648 push bx 649 push dx 650 push cx 651 mov ax,0 652 mov bx,0 ;bx: quotidient_32bits_high 653 mov dx,0 ;dx: quotidient_32bits_low 654 mov cx,0 ;counter = 0 655 ;16bits or 32bits ? 656 mov ax,var_32bits_high 657 cmp ax,0 658 jne _32bits_routine 659 jmp _16bits_routine 660 661 ;;; 662 _32bits_routine: 663 mov cx,0 664 ;if == -2147483648 (-2^31) 665 mov ax,var_32bits_high 666 cmp ax,lowest_signed_32bits_high 667 jne check_if_neg 668 mov ax,var_32bits_low 669 cmp ax,lowest_signed_32bits_low 670 jne check_if_neg 671 ;then 672 lea dx,lowest_signed_32bits_string 673 mov ah,9 674 int 21h 675 jmp return_to_dos 676 ;if < 0 677 check_if_neg: 678 mov ax,var_32bits_high 679 cmp ax,0 680 jnl preparations 681 ;then print "-" ... 682 mov ah,2 683 mov dl,'-' 684 int 21h 685 ;... and negate number 686 ;---------xor 0ffffffff , + 1---------- 687 mov ax,var_32bits_high 688 xor ax,negate_mask 689 mov var_32bits_high,ax 690 mov ax,var_32bits_low 691 xor ax,negate_mask 692 inc ax 693 mov var_32bits_low,ax 694 jnc preparations 695 mov ax,var_32bits_high 696 inc ax 697 mov var_32bits_high,ax 698 preparations: 699 mov ax,var_32bits_high 700 mov quotidient_32bits_high,ax 701 mov ax,var_32bits_low 702 mov quotidient_32bits_low,ax 703 while_32bits: 704 ; while >0 do 705 mov ax,quotidient_32bits_high 706 cmp ax,0 707 jne div_high_part 708 mov ax,quotidient_32bits_low 709 cmp ax,0 710 jne div_high_part 711 jmp print_char 712 div_high_part: 713 ;divide high part 714 mov dx,0 715 mov ax,quotidient_32bits_high 716 div base_10 717 mov qhigh,ax 718 mov rhigh,dx 719 ;case rhigh 720 mov ax,rhigh 721 cmp ax,0 722 je _rhigh0 723 cmp ax,1 724 je _rhigh1 725 cmp ax,2 726 je _rhigh2 727 cmp ax,3 728 je _rhigh3 729 cmp ax,4 730 je _rhigh4 731 cmp ax,5 732 je _rhigh5 733 cmp ax,6 734 je _rhigh6 735 cmp ax,7 736 je _rhigh7 737 cmp ax,8 738 je __rhigh8 739 cmp ax,9 740 je __rhigh9 741 _rhigh0: 742 mov ax,qhigh0 743 mov qhigh_redundant,ax 744 mov ax,rhigh0 745 mov rhigh_redundant,ax 746 jmp _aftercase 747 748 _rhigh1: 749 mov ax,qhigh1 750 mov qhigh_redundant,ax 751 mov ax,rhigh1 752 mov rhigh_redundant,ax 753 jmp _aftercase 754 __rhigh8: 755 jmp _rhigh8 756 __rhigh9: 757 jmp _rhigh9 758 _rhigh2: 759 mov ax,qhigh2 760 mov qhigh_redundant,ax 761 mov ax,rhigh2 762 mov rhigh_redundant,ax 763 jmp _aftercase 764 _rhigh3: 765 mov ax,qhigh3 766 mov qhigh_redundant,ax 767 mov ax,rhigh3 768 mov rhigh_redundant,ax 769 jmp _aftercase 770 _rhigh4: 771 mov ax,qhigh4 772 mov qhigh_redundant,ax 773 mov ax,rhigh4 774 mov rhigh_redundant,ax 775 jmp _aftercase 776 _rhigh5: 777 mov ax,qhigh5 778 mov qhigh_redundant,ax 779 mov ax,rhigh5 780 mov rhigh_redundant,ax 781 jmp _aftercase 782 _rhigh6: 783 mov ax,qhigh6 784 mov qhigh_redundant,ax 785 mov ax,rhigh6 786 mov rhigh_redundant,ax 787 jmp _aftercase 788 _rhigh7: 789 mov ax,qhigh7 790 mov qhigh_redundant,ax 791 mov ax,rhigh7 792 mov rhigh_redundant,ax 793 jmp _aftercase 794 _rhigh8: 795 mov ax,qhigh8 796 mov qhigh_redundant,ax 797 mov ax,rhigh8 798 mov rhigh_redundant,ax 799 jmp _aftercase 800 _rhigh9: 801 mov ax,qhigh9 802 mov qhigh_redundant,ax 803 mov ax,rhigh9 804 mov rhigh_redundant,ax 805 jmp _aftercase 806 _aftercase: 807 ;divide low part 808 mov ax,0 809 mov q_0,ax 810 mov dx,0 811 mov ax,quotidient_32bits_low 812 div base_10 813 mov qlow,ax 814 mov rlow,dx 815 mov ax,rlow 816 add ax,rhigh_redundant 817 ;if remainder >= 10 818 cmp ax,base_10 819 jl after_if 820 sub ax,base_10 821 mov dx,1 822 mov q_0,dx 823 after_if: 824 mov rlow,ax 825 mov ax,q_0 826 add ax,qlow 827 mov qlow,ax 828 jnc label1 829 mov ax,qhigh 830 inc ax 831 mov qhigh,ax 832 label1: 833 mov ax,qlow 834 add ax,qhigh_redundant 835 mov qlow,ax 836 jnc label2 837 mov ax,qhigh 838 inc ax 839 mov qhigh,ax 840 label2: 841 ;push remainder to stack 842 mov ax,rlow 843 push ax 844 inc cx 845 mov ax,qhigh 846 mov quotidient_32bits_high,ax 847 mov ax,qlow 848 mov quotidient_32bits_low,ax 849 jmp while_32bits 850 851 ;;; 852 _16bits_routine: 853 mov ax,var_32bits_low 854 mov bx,0 ;bx: quotient 855 mov cx,0 856 while_loop: 857 cmp ax,0 858 je print_char 859 mov dx,0 860 div base_10 861 mov bx,ax ;ax stores quotidient 862 mov ax,dx ;dx stores remainder 863 ;push remainder 864 push ax 865 ;counter = counter + 1 866 inc cx 867 ;numerator = quotidient 868 mov ax,bx 869 jmp while_loop 870 print_char: 871 cmp cx,0 872 je return_to_dos 873 pop ax 874 ;because at this point 0 <= ax <= 9, setting ah = 2 does not change the results 875 mov ah,2 876 mov dl,al 877 add dl,30h ;0-> '0',1->'1',.... 878 int 21h 879 dec cx 880 jmp print_char 881 882 return_to_dos: 883 884 pop cx 885 pop dx 886 pop bx 887 pop ax 888 ret 889 showspace endp 890 891 ;--------input:ax---------- 892 add_used_space proc near 893 push ax 894 push bx 895 push cx 896 push dx 897 898 mov dx,[used_32bits_low] 899 add dx,ax 900 jnc add_finish 901 mov bx,[used_32bits_high] 902 inc bx 903 mov [used_32bits_high],bx 904 905 add_finish: 906 mov [used_32bits_low],dx 907 908 pop dx 909 pop cx 910 pop bx 911 pop ax 912 ret 913 add_used_space endp 914 915 main ends 916 end p1