www.knechtruprecht.de


Assembler Links

discount.asm
dircount.asm ist ein kleines Programm, das die Anzahl von File (und Dirs) in einem Verzeichnis zaehlt. Ähnlich wie "ls -1 | wc -l", nur wesentlich schneller da ls u.a. alle Attribute der Files usw. liesst.
Geschrieben habe ich das mal, nachdem ich immer lange auf "ls -1| wc -l" warten musste weil in den Directories zwischen 200.000 und 500.000 Files waren.
Verwendet habe ich es nie, da ich nie mehr so viele File zählen musste. Es war aber nach über 25 Jahren mein erstes Assembler-Programm.

Aus dem Sourcecode ein ausführbares Programm machen:

ACHTUNG: Dies ist für 32Bit Linux!

nasm -f elf dircount.asm
ld -s -o dircount dircount.o

Download dircount.asm

section .text
global _start

_start:
; als erstes die commandline-arguments holen - auf dem stack finden wir:
; [word "number of args"] [dword "address of first parameter] .... [dword address of x.parameter]
pop ecx ;get "number of args (wiederspricht gerade der zeile davor - aendere ich noch)
mov ebx,dir ;Adresse des defaultdirectory holen, falls kein Parameter da ist
cmp cx,1
je open_dir ;Parameter fehlt, wir nehmen default dir ./
pop ebx ;Adresse des ersten Parameters - das ist der Programmname - in ebx für open_dir
pop ebx

open_dir:
directory zum lesen oeffnen
mov eax,5 ;system call fuer open
mov ecx,0 ;read only
int 80h

test eax,eax ;pruefen ob das Erfolgreich war
jns go_readdir
jmp exit_prog ;hat nicht geklappt, prg beenden


go_readdir:
mov dword[fd],eax ;file descripter fuers dir merken, brauchen wir oefter
xor ecx,ecx ;Filecounter auf null
read_dir:
push ecx ;den brauche ich noch, also auf den Stack damit
mov eax,141 ;getdents sys_call
mov ebx,dword[fd] ;file descripter des Dirs nach ebx
mov ecx,dirent ;pointer to buffer
mov edx,600 ;buffersize
int 80h
pop ecx ;ecx wieder vom Stack holen
or eax,eax ;Hier stehen die gelesen Bytes, wenn 0 => wir haben alles
jz print_info ;die beiden letzten Zeilen sind das gleiche wie "cmp eax,0; je print_info" - frueher war das so aber bischen schneller - keine ahnung obs noch so ist

xor ebx,ebx ;mein lesepointer - auf null stellen
mov edi,dirent ;Bufferadresse laden
call count_files ;zaehlen
jmp read_dir ;und naechsten Teil des Dirs lesen

print_info:
;int 3 ;Debugger Breakpoint
mov edi,counterstring ;ausgabebuffer fürs printen
add edi,20 ;ans ende des Buffers
mov byte[edi],10 ;Zeilenvorschub in den Buffer
dec edi ;pointer ein zurueck
mov ebx,10 ;divisionwert
mov eax,ecx ;in ecx steht die Anzahl der Files
mov ecx,20 ;max 20 Stellen printen
print_info1:
mov ebx,10
xor edx,edx ;ist das gleiche wie mov edx,0
or eax,eax ;wieder ein vergleich mit or, ob eax gleich 0 ist
jz print_info2 ;div geht nur, wenn eax UND ebx nicht 0 ist
div ebx ;eax/ebx -> Ergebnis eax, Rest in edx
add edx,48 ;edx ist rest der Division, Ascii draus machen
mov [edi],dl ;und die ASCII-Zahl in den Printbuffer
dec edi ;Zeiger eins zurueck
dec cx ;Zaehler-1
or cx,cx ;ist der zaehler=0?
jnz print_info1 ;noe? alles nochmal
jmp print_info3
print_info2:
mov eax,4 ;write
mov ebx,1 ;stdio
mov edx,21 ;Anzahl der zu printenden Zeichen
sub edx,ecx ;minus cx (haben nicht volle 20 Stellen
add ecx,counterstring ;und auf cx den Pointer vom Ausgabestring addieren
int 80h
jmp exit_prog
print_info3:
; nun ausgeben, wir haben volle 20 Stellen
mov eax,4 ;write
mov ebx,1 ;stdio
mov ecx,counterstring
mov edx,21 ;laenge
int 80h

exit_prog:
;Programm ordentlich beenden
mov eax,1 ;sys call exit
int 80h

count_files:
; eax enthaelt die aktuelle Groesse im Buffers
; ecx enthaelt die anzahl der files
; Aufbau der dirent mit "man 2 getdents"
xor edx,edx ;edx auf 0
mov dx,[edi+8] ;laenge des dirent
add ebx,edx
add edi,edx ;edi auf den naechsten Direintrag
inc ecx ;Filecounter+1
cmp ebx,eax
jl count_files ;Buffer vollstaendig gelesen?
ret

section .data

dir db './',0

section .bss

fd resd 1
dirent resb 600
counterstring resb 21

'
-->