All pastes #442401 Raw Edit

Szymek

public text v1 · immutable
·published 2007-04-16 07:54 UTC
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