#---------------------------------------------------------------- .equ kernel, 0x80 #Linux system functions entry .equ exit, 0x01 #exit program function .equ fork, 0x02 .equ read, 0x03 #read data from file function .equ write, 0x04 #write data to file function .equ open, 0x05 #open file function .equ close, 0x06 #close file function .equ waitpid,0x07 .equ create, 0x08 #create file function .equ stdin, 0x00 #handle to stdin .equ stdout, 0x01 #handle to stdout .equ stderr, 0x02 #handle to stderr #---------------------------------------------------------------- .data digits: .ascii "0123456789ABCDEF" numberbuf: .space 128, 0 numberend: .long ( . - numberbuf ) #---------------------------------------------------------------- .text .global _start _start: MOVL $10, %ebx CALL read_number MOVL %eax,%ecx XOR %eax,%eax loopek: ADD %ecx,%eax LOOP loopek MOVL $10, %ebx CALL print_number end: # zakończ proces MOVL $exit, %eax INT $kernel #---------------------------------------------------------------- .type print_number,@function # # Wypisuje liczbę na stdout # # Parametry: # %eax - liczba # %ebx - podstawa (np. 10 dla dziesiętnego) # # Używa rejestrów: %eax, %ebx # %ecx wskaźnik na cyfrę # %edx reszta z dzielenia # %edi liczba znaków # print_number: MOVL $numberend, %ecx XOR %edi, %edi #wyzeruj ilość znaków pn_nextdig: DEC %ecx XOR %edx,%edx DIV %ebx MOVB digits(, %edx, 1), %dl MOVB %dl,(%ecx) INC %edi CMPL $0,%eax JNZ pn_nextdig # wyświetl wynik konwersji MOVL $write,%eax #identyfikator funkcji MOVL $stderr,%ebx #uchwyt do pliku MOVL %edi, %edx INT $kernel RET #---------------------------------------------------------------- .type getval,@function # # Dokonuje konwersji cyfra (znak) -> liczba # # Parametry: # %dl - szukany znak # %ebx - podstawa (np. 10 dla dziesiętnego) # # Zwraca: # %dl - liczba (-1 jeśli błąd) # getval: PUSH %rcx MOVL %ebx, %ecx gv_loop: DEC %ecx CMPB %dl, digits(, %ecx, 1) JE gv_found CMPL $0, %ecx JNE gv_loop MOVB $-1, %cl gv_found: MOVB %cl, %dl POP %rcx RET #---------------------------------------------------------------- .type read_number,@function # # Wczytuje liczbę z stdin # # Parametry: # %ebx - podstawa (np. 10 dla dziesiętnego) # # Używa rejestrów: %eax, %ebx # %ecx wskaźnik na cyfrę # %edx reszta z dzielenia # %edi liczba znaków # # Zwraca: # %eax - liczba (-1 jeśli błąd) # read_number: PUSH %rbx MOVL $read,%eax #identyfikator funkcji MOVL $stdin,%ebx #uchwyt do pliku MOVL $numberbuf,%ecx #wskaźnik na bufor MOVL numberend,%edx #ilość bajtów do wczytania INT $kernel POP %rbx CMP $0,%eax JLE rn_error #jeśli wczytano 0 znaków to błąd MOVL %eax, %ecx #przenieś do %ecx ilość wczytanych znaków XOR %edi, %edi #zeruj indeks tablicy XOR %eax, %eax #zeruj wynik rn_nextdig: XOR %edx, %edx #wyzeruj %edx MOVB numberbuf(, %edi, 1), %dl CALL getval #dokonaj konwersji znak->liczba CMP $-1, %dl JE rn_out #zakończ jeśli znak nie jest cyfrą PUSH %rdx #zapamiętaj rejestr (MUL nadpisuje) MUL %ebx #pomnóż wynik przez podstawę POP %rdx #przywróc zawartość ADD %edx, %eax #dodaj INC %edi #zwiększ indeks LOOP rn_nextdig rn_out: CMP $0, %edi JE rn_error #jeśli wczytano 0 znaków to błąd RET rn_error: MOVL $-1, %eax RET