rendered paste body#----------------------------------------------------------------
.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