flat assembler
Message board for the users of flat assembler.
Index
> DOS > 219-byte LFN dir lister (386+) |
Author |
|
rugxulo 12 Oct 2006, 02:44
It only lists LFN filenames and their filesizes w/ commas (but > 4 GB works, if your filesystem supports it, e.g. NTFS). The default filespec is * (aka, *.*) but another can be specified at the cmdline. It assembles out of the box w/ NASM or YASM. FASM is supported by a .BAT that uses sed. Octasm also works w/ the included sed script.
I would post this under Windows except it works in pure DOS (w/ DOSLFN) plus it's a DOS .COM (not exactly a native Win32 format). P.S. To manipulate LFN files under pure DOS w/ no TSR, use Odi's LFN tools (w/ src). P.P.S. There's lots of good 256 byte demos (usually w/ src) at http://www.256b.com (e.g., selfdasm, tet, inv, wolf, smile256). P.P.P.S. Don't whine about how useless it is because of cluster size: use ARK (comes w/ ASM src) to combine a lot of stray .COMs to save space! :) Code: ; ---------------------------------------------------------------------- ; LFNDIR.ASM (0.10) -- simple 386+ LFN dir lister (names + fsizes only) ; ; Monday June 11, 2007 5:35pm ; ; ====================================================================== ; CRC32 = 406D2C10 ; ; begin 644 lfndir.com ; MOH``C50"K(3`=07'1`$J`),P_X@XN$YQN?<`Z!P`<AF.X.@?`+A/<8SCZ`T` ; MZ!0`<_.XH7&,X\TAP[\)`KX!`/G-(<-R_;()Z(``]@40=`6R6^AV`(UU+.AC ; M`/8%$'0'LEWH9@#K4^AF`&8/MLIFBU4<9HM%(+_;`3'M9I)F4F8QTF;W\6:3 ; M9EAF]_%FA].`RS!%B!V#_0-R!D?&!2PQ[4=FA=)UU6:%P'703X`]+'0!1ZJ- ; G=?[]Z`0`Z!,`PZR$P'0&DN@$`.OU_,.T`LTAP[(-Z/;_L@K-(<,` ; ` ; end ; ====================================================================== ; ; +-----------------+ ; | Requirements: | ; +-----------------+ ; ; Tested successfully on the following: ; ; = Win XP Home SP2 (Intel P4 2.52 Ghz) ; = DR-DOS 7.03 w/ DOSLFN 0.40e (Intel Pentium 166 Mhz w/o MMX) ; = FreeDOS 1.0 (kernel 2036) w/ DOSLFN 0.40e (Intel 486 Sx/25) ; ; FASM (use .BAT below) : 219 bytes ; OCTASM (use .sed below) : 219 bytes ; NASM or YASM : 219/220 bytes (depending on version) ; ; "nasm lfndir.asm -o lfndir.com -O5v" ; ; +------------+ ; | Credits: | ; +------------+ ; ; rugxulo AT gmail DOT com (no spam, please!) ; ; public domain, free for any use, no credit necessary ("nenies proprajxo") ; ; with much grace from: ; = Our Lord Jesus Christ (seriously!) ; ; and a few nifty tips from: ; = Jason Hood (jadoxa) ; = brief look at some optimization texts (e.g. Agner Fog) ; = FASM forum (for being VERY helpful, in general, towards assembly) ; ; +---------------+ ; | Optimizing: | ; +---------------+ ; ; = nothing else ... yet! ;-) ; = possibly using other instructions: AAM, BSWAP, CMC ?? ; ; +---------+ ; | Make: | ; +---------+ ; ---------------------------------------------------------------------- ; ; @echo off ; REM Makes it w/ FASM (needs sed: e.g., SED15X.ZIP or SEDMOD10.ZIP) ; ; for %%a in (lfndir*.asm) do set L1=%%a ; set O1=lf.asm ; if not exist %L1% goto end ; sed "/sec.* \./d;/^bit/d;s/^.\(org.*h\)./\1/;s/res\([bw]\)/r\1/" %L1% >%O1% ; if not exist %O1% goto end ; REM cwsdpmi (for weird mem. manager situations, e.g. DOSBox) ; fasm %O1% lfndir-fasm.com >NUL ; for %%l in (lfndir-*.com) do set C1=%%l ; if "%C1%"=="" goto end ; %C1% %1 ; :end ; REM !! this would delete it (to save space) !! ; REM for %%f in (%O1% %C1%) do if exist %%f del %%f ; for %%e in (O1 L1 C1) do set %%e= ; ; ---------------------------------------------------------------------- ; ; # sed script for LFNDIR to work w/ Octasm ; # ; # sed -f lfn-oct.sed lfndir.asm > lfn-oct.asm ; # octasm \lfn-oct.asm file_out \lfn-oct.com ; # ; # N.B. Make sure to remove all trailing whitespace (or sed won't work!): ; # ; # sed "s/ *$//" lfn-oct.sed > oct.sed ; ; 1s/..*/LANG OCTASM,0.1\ ; &/ ; s/jc find\.ret/jc <1/ ; s/ equ /=/ ; /^section \.text/d ; /^section \.data/d ; s/^section \.bss/virtual/ ; $s/..*/&\ ; code/ ; s/.\(org 100h\)./\1/ ; s/^bits /use/ ; s/\(j[a-z][a-z]*\) \.ret/\1 >1/ ; s/^\.ret:/#/ ; s/^\([.a-zA-Z0-9_][.a-zA-Z0-9_]*\):/#\1/ ; s/byte \[/b[/ ; s/dword \[/d \[/ ; s/word \[/w[/ ; s/res\([bw]\)/r\1/ ; s/^\.*[a-zA-Z0-9_][a-zA-Z0-9_]* [dr][bw]/#&/ ; s/jmp short/jmp / ; /0\.1/!s/\.//g ; s/^;;;*/;/ ; ; ---------------------------------------------------------------------- ; ; +------------+ ; | Changes: | ; +------------+ ; ; 0.10: 219 bytes: removed useless strlen (and more tweaks) ; 0.9 : 231 bytes: yet more size optimizations ; 0.8 : 236 bytes: more size optimizations! ;-) ; 0.7 : 243 bytes: tweaked a bit w/ some optimizations ; 0.6 : 255 bytes: no code changes, only various text updates ; 0.5 : 255 bytes; filespec can now be specified (default '*.*') ; 0.4 : 251 bytes; fairly simple optimizations vs. previous ; 0.3 : 277 bytes: now prints both names and filesizes ; 0.2 : 145 bytes: minor optimizations vs. previous version ; 0.1 : 151 bytes: initial version (filenames only) ; ; ---------------------------------------------------------------------- ; ; +----------------+ ; | Misc. Notes: | ; +----------------+ ; ; P.S. You can shave more bytes if you're willing to compromise by ; removing the filesize commas and/or adapting "call print_char" ; to use int 29h (which isn't redirectable). ; ; I wasn't willing to do so, and my goal was 256 bytes, so ; ; ; also, from Ralf Brown's interrupt list, ; (http://www.delorie.com/djgpp/doc/rbinter/id/16/32.html): ; ; "only works when IFSMgr is running, not under bare MS-DOS 7" ; ; BUT, it does work with DOSLFN 0.40e under pure DR-DOS 7.03! ; ; http://www.geocities.com/jadoxa/ (DOSLFN, Jason Hood) ; ; ---------------------------------------------------------------------- CR equ 13 LF equ 10 ALL equ 0F7h ; everything but volume label (bit 3) ; i.e., 0FFh and not 8 STDOUT equ 1 DIR equ 10000b ; bit 4 (aka, 10h) COMMA equ 2Ch SPACE equ 20h ; 20h = ' ' = bit 5 = 32 TAB equ 9 bits 16 section .text [org 100h] ; works w/ old YASM 0.3.0, too ;-------------------------------------------------------------------- Komenco: mov si,80h lea dx,[si+2] lodsb test al,al jnz Filespec mov word [si+1],'*' ; '*',0 is same as '*.*',0 Filespec: xchg ax,bx ; = 1 byte! :-D xor bh,bh mov byte [bx+si],bh Search: mov ax,714Eh ; LFN: find first mov cx,ALL call find jc Fino ; mov word [find_handle],ax mov fs,ax call print_fileinfo Next: mov ax,714Fh ; LFN: find next ; mov bx,word [find_handle] mov bx,fs call find call print_fileinfo jnc Next Adios: mov ax,71A1h ; close LFN find handle ; mov bx,word [find_handle] mov bx,fs int 21h Fino: ; mov ax,4C00h ; int 21h ; int 20h ret ; oldest trick in the book ; (saves a byte) ;-------------------------------------------------------------------- ; find find: mov di,finddata mov si,1 ; DOS date/time format stc int 21h .ret: ret ; print_fileinfo print_fileinfo: jc find.ret .begin: mov dl,TAB ; give us some space (to aide in call print_char ; telling the difference between ; two lines of one filename or two ; (compare listing of an 80+ length ; fname via DIR /B and this .COM) test byte [di],DIR jz .fname mov dl,'[' ; surround dirs w/ '[' and ']' call print_char ; e.g., '[My Documents]' .fname: lea si,[di+2Ch] ; LFN call print_str test byte [di],DIR jz .crlf mov dl,']' call print_char jmp short .crlf2 .crlf: call print_crlf ;;; mov ecx,word [outbase] ;; mov ecx,10 ; = 6 bytes ; lea ecx,[10] ; = 5 bytes movzx ecx,dl ; = 4 bytes .fsize: mov edx,dword [di+1Ch] ; filesize (qword) mov eax,dword [di+20h] .bin2dec: mov di,buffer_start_nul+1 ; put ASCIIZ decimal string xor bp,bp ; w/ commas in buffer (backwards) .start: xchg eax,edx push edx xor edx,edx div ecx xchg eax,ebx pop eax div ecx xchg edx,ebx or bl,'0' ; this only works for dec numbers! ; push eax ; this works for dec or hex nums ; xchg bl,al ; mov bx,asciihex ; xlatb ; translate digit to ASCII ; xchg bl,al ; pop eax inc bp mov byte [di],bl ; cmp bp,word [comma_number] cmp bp,3 jb .no_comma ; comma_number = 3 (dec) or 4 (hex) inc di mov byte [di],COMMA xor bp,bp .no_comma: inc di test edx,edx jnz .start test eax,eax jnz .start dec di ; now DX:AX = 0 cmp byte [di],COMMA ; this will allow 3-digit numbers jz .bye ; not to be printed w/ a comma inc di .bye: ; mov byte [di],0 stosb lea si,[di-2] std call print_str .crlf2: call print_crlf .ret: ret ; print_str print_str: ; print string (redirectable) lodsb test al,al jz .bye2 xchg ax,dx call print_char jmp short print_str .bye2: cld .ret: ret ; print_char print_char: ; print char (redirectable) mov ah,2 int 21h .ret: ret ; print_crlf print_crlf: ; print '\n' (redirectable) mov dl,CR call print_char mov dl,LF ; call print_char int 21h ; this saves a byte .ret: ret ;-------------------------------------------------------------------- ;section .data ; this line increases .COM size ??? ; (ah, NASM default: dword-aligned) ;asciihex db '0123456789ABCDEF',0 buffer_start_nul db 0 ;-------------------------------------------------------------------- section .bss ;find_handle resb 2 buffer resb 45 ; big enough for 64-bit no. w/ commas finddata: .attrib resb 4 .created_time resb 4 .accessed_time resb 4 .modified_time resb 4 .filesize_high resb 4 ; 64-bit filesize .filesize_low resb 4 .reserved resb 8 ; unused .long_name resb 260 ; ASCIIZ .short_name resb 14 ; ASCIIZ ; EOF
Last edited by rugxulo on 13 Jun 2007, 02:00; edited 15 times in total |
|||||||||||
12 Oct 2006, 02:44 |
|
vid 12 Oct 2006, 11:03
you can write "mov word [si+1],002Ah" simply as "mov word [si+1], '*'"
|
|||
12 Oct 2006, 11:03 |
|
rugxulo 13 Oct 2006, 14:42
EDIT: ... (redundant post)
Last edited by rugxulo on 09 Jan 2007, 23:35; edited 2 times in total |
|||
13 Oct 2006, 14:42 |
|
Octavio 15 Oct 2006, 13:46
rugxulo wrote: It only lists LFN filenames and their filesizes (but > 4 GB works). Fat 32 is limited to 4GB perhaps you mean >2GB. But the problem is in showing the complete charset wich is 2^16 diferent letters ,this would require a graphics videomode + bmps to show all chars above 80h like: ñÇü²³§ |
|||
15 Oct 2006, 13:46 |
|
rugxulo 18 Oct 2006, 23:12
Octavio, yes, I meant > 2 GB (though in my head I was thinking in terms of the limitations of a 32-bit number ... my 16-bit DOS prog VDIR apparently shows > 3 GB filesizes on my Win XP NTFS C: drive using only 16-bit regs, mainly DX:AX, so I'm actually comparing LFNDIR to that).
Complete charset? I guess you mean Unicode (probably won't work) instead of extended ASCII (apparently works). |
|||
18 Oct 2006, 23:12 |
|
rugxulo 06 Jan 2007, 03:01
And, for completeness' sake, here's a wimpy 16-bit DOS dir lister I've written (reassembles via a bunch of assemblers using sed, included). No flames, I know it ain't much, but whatever.
|
|||||||||||
06 Jan 2007, 03:01 |
|
ATV 08 Jan 2007, 13:06
rugxulo, you are very good with sed and using bat to convert source.
But then I found next line Quote: if "%CLEAN%"=="y" if exist %V%fasm.asm erase %V%fasm.asm Why, why, why you are deleting v49fasm.asm Any plans to add 24h time format? It's easier than am/pm +midnight stuff. |
|||
08 Jan 2007, 13:06 |
|
rugxulo 09 Jan 2007, 05:09
ATV wrote: rugxulo, you are very good with sed and using bat to convert source. ATV wrote:
If you don't like that behavior, in V49OTHER.BAT go to ":begin" and type below it "set clean=n". Because I use/edit only the main V49.ASM file, if I want to assemble via an assembler other than ArrowASM (default) or A86, I have to use sed. Now, most seds (except GNU sed -i, which I avoid because it's larger/slower/386-only) don't edit in-place. So, I have to create a second .ASM file (e.g., V49FASM.ASM) with suitable changes to allow it to be assembled in the target assembler's syntax. I see no reason to keep around the auxiliary .ASM by default because any changes made to it are not shared with the main V49.ASM source. Plus, it wastes storage space (e.g., on a floppy or RAM disk) to keep every little auxiliary .ASM if doing "V49OTHER all" for instance, so unless you "set CLEAN=n" before running V49OTHER.BAT (or type "V49OTH2 fasm notclean"), it deletes V49FASM.ASM. ATV wrote:
I dunno, 00:05 just looks dumb to me, so I typically use 12-hour, but it'd be easy to change. More to do! |
|||
09 Jan 2007, 05:09 |
|
rugxulo 11 Feb 2007, 21:57
Okay, ATV, here's a quick diff that makes /T! use 24-hour file times when using /V (instead of default 12-hours). After this, you can either enable it manually each time you use it, reassemble with "suboptions dw 31 or MILITARY", or put "set VDIR=t!" in your AUTOEXEC.BAT (or FDAUTO.BAT or whatever). Enjoy (heh, yeah right!).
Code: 565,566c569,571 < A_SUBOPT_X equ 1000h < A_SUBOPT_N equ 2000h --- > MILITARY equ 1000h > A_SUBOPT_X equ 2000h > A_SUBOPT_N equ 4000h 626,627c631,632 < ; cmp al,'T' ; /Z:T would be useless! < ; jz env_var_next --- > ;; cmp al,'T' ; /Z:T would be useless! > ;; jz env_var_next ; but /t! wouldn't 701,702c706,707 < cmp al,'T' ; /Z:T would be useless! < jz env_var2_next --- > ; cmp al,'T' ; /Z:T would be useless! > ; jz env_var2_next ; but /t! wouldn't 1787c1792,1798 < mov ax,word ptr [dta+16h] ; offset of file's time --- > ; offset of file's time > > mov si,offset buffer > mov word ptr [si],' ' ; needed by /t! > mov word ptr [si+2],0 > > mov ax,word ptr [dta+16h] 1792a1804,1807 > > test word ptr [suboptions],MILITARY > jnz file_time_continue > 1850a1866 > inc cx 1853d1868 < mov byte ptr [di],0 3915c3930,3938 < option_t: ; /T will print time and date --- > option_t: > call suboption_flag_check > ; cmp word ptr es:[si],2154h ; '!T' > jnz option_t_begin > xor word ptr [suboptions],MILITARY > inc si ; /T! prints 24h times (default: 12h) > jmp short option_t_ret > > option_t_begin: ; /T will print time and date 3959c3982 < ; ret ; bogus 'ret' for .SED scripts! --- > ret 4089,4090c4112,4113 < cmp byte ptr [si],'T' ; ignore /T or /H or /? or /Z < jz option_z_load --- > ; cmp byte ptr [si],'T' ; ignore /H or /? or /Z > ; jz option_z_load ; (keep /t for /t!) 4186c4209 < ; nxCYJIRXHDatds ; n=/A:N, x=/A:X --- > ; nxMCYJIRXHDatds ; n=/A:N, x=/A:X, M = MILITARY |
|||
11 Feb 2007, 21:57 |
|
rugxulo 13 Jun 2007, 02:21
Updated this, added .ZIP package
BTW, I spent a few hours poring over the code, so I seriously doubt I'll be decreasing it much, if at all, in the next few weeks (however, some of you obviously could, even though I doubt you will since DOS interest here seems to be low). Oh well. |
|||
13 Jun 2007, 02:21 |
|
rugxulo 04 Mar 2008, 16:39
Sorry to bump the thread, but at least I found this interesting:
Code: .crlf2: ; call print_crlf jmp print_crlf ; saves a byte .ret: ret |
|||
04 Mar 2008, 16:39 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.