ics312_countodds.asm [Download]

; This simple program takes 10 integers from the user and
; counts how many of these integers are odd

%include "asm_io.inc"

segment .data
	msg_odd	db	"The number of odd numbers is: ",0

segment .bss
	integers resd	10	; space to store 10 32-bit integers

segment .text
	global	asm_main
asm_main:
	enter	   0,0		; set up
	pusha			; set up

    	push	integers	; we pass integers to get_integers
	push	dword 10	; we pass the number of integers to get_integers 
	call	get_integers	; call get_integers
	add	esp, 8		; clean up the stack (often done as op ecx twice, which may be quicker)
	mov	eax, msg_odd	; store the address of the message to print into eax
	call	print_string	; print the message
	push 	integers	; we pass integers to count_odds	
	push	10		; we pass the number of integers to count_odds
	call	count_odds	; call count_odds
	add	esp, 8		; clean up the stack
	call	print_int	; print the content of eax as an integer (this is what count_odds returned)
	call	print_nl	; print a new line

	popa			; clean up
	mov	   eax, 0	; clean up
	leave			; clean up
	ret			; clean up

;   	FUNCTION: Get_Integers
; 	Takes two parameters:  an address in memory in which to store integers, and a number of integers to store (>0)
; 	Destroys values of eax, ebx, and ecx!!

segment .data
	msg_int		db	"Enter an integer: ",0

segment .text
get_integers:
	push	ebp		; save the value of EBP of the caller
	mov	ebp, esp	; update the value of EBP for this subprogram

	mov	ecx, [ebp + 12]	; ECX = address at which to store the integers (parameter #1)
	mov	ebx, [ebp + 8]	; EBX = number of integers to read (parameter #2)
	shl	ebx, 2		; EBX = EBX * 4  (unsigned)
	add	ebx, ecx	; EBX = ECX + EBX = address beyond that of the last integer to be stored
loop1:
	mov	eax, msg_int	; EAX = address of the message to print
	call	print_string;	; print the message
	call	read_int	; read an integer from the keyboard (which will be stored in EAX)
	mov	[ecx], eax	; store the integer in memory at the correct address
	add	ecx, 4		; ECX = ECX + 4 
	cmp	ecx, ebx 	; compare ECX, EBX
	jb	loop1		; if ECX < EBX, jump to loop1   (unsigned)

	pop	ebp		; restore the value of EBP
	ret			; clean up

;	FUNCTION: count_odds
; 	Takes two parameters:  an address in memory in which integers are stored, and the number of integers (>0)
; 	Destroys values of eax, ebx, and edx!!  (eax = returned value)

segment .text
count_odds:
	push	ebp		; save the value of EBP of the caller
	mov	ebp, esp	; update the value of EBP for this subprogram

	mov	eax, [ebp + 12]	; ECX = address at which integers are stored (parameter #1)
	mov	ebx, [ebp + 8]	; EBX = number of integers (parameter #2)
	shl	ebx, 2		; EBX = EBX * 4  (unsigned)
	add	ebx, eax	; EBX = ECX + EBX = address beyond that of the last integer
	sub	ebx, 4		; EBX = EBX - 4 = address of the last integer
	xor	edx, edx	; EDX = 0
loop2:

	push	dword [ebx] 	; store the current integer on the stack
	call	is_odd		; call is_odd  
	add	esp, 4		; clean up the stack
	add	edx, eax	; EDX += EAX  (EAX = 0 if even, EAX = 1 if odd)
	sub	ebx, 4		; ECX = ECX - 4 
	cmp	ebx, [ebp+12] 	; compare EBX and the address of the first integer
	jnb	loop2		; if EBX >= [EBP+12]  jump to loop2   (unsigned)
	
	mov	eax, edx	; EAX = EDX (= number of odd integers)
	
	pop	ebp		; restore the value of EBP
	ret			; clean up


;  	FUNCTION: is_odd
; 	Takes one parameter:  an integers (>0)
; 	Destroys values of eax and ecx (eax = returned value)

segment .text
is_odd:
	push	ebp		; save the value of EBP of the caller
	mov	ebp, esp	; update the value of EBP for this subprogram

	mov	eax, 0		; EAX = 0
	mov	ecx, [ebp+8]	; EBX = integer (parameter #1)
	shr	ecx, 1		; Right logical shift
	adc	eax, 0		; EAX = EAX + carry  (if even: EAX = 0, if odd: EAX = 1)
	
	pop	ebp		; restore the value of EBP
	ret			; clean up

ics312_fibonacci.asm [Download]

; This simple program takes 10 integers from the user and
; counts how many of these integers are odd

%include "asm_io.inc"

segment .data
	msg1		db	"Enter n: ", 0
	msg2		db	"The result is: ", 0

segment .text
	global	asm_main
asm_main:
	enter	   0,0			; set up
	pusha				; set up

	mov		eax, msg1	; eax = address of msg1
	call		print_string	; print msg1
	call		read_int	; get an integer from the keyboard (in EAX)
	push		eax		; put the integer on the stack (parameter #1)
	call		f		; call recursive_sum
	pop		ebx		; remove the parameter from the stack
	mov		ebx, eax	; save the value returned by recursive_sum
	mov		eax, msg2	; eax = address of msg2
	call		print_string	; print msg2
	mov		eax, ebx	; eax = sum
	call		print_int	; print the sum
	call		print_nl	; print a new line

	popa				; clean up
	mov	   eax, 0		; clean up
	leave				; clean up
	ret				; clean up

;   	FUNCTION: f
; 	Takes one parameter:  an integer
; 	eax = return value
segment .data
	debug1	db	"Function f called with integer: ",0
segment .text
f:	enter  8,0		; num in [ebp+8], local var x in [ebp-4], local var sum in [ebp-8]
	push	ebx		; save ebx
	push 	ecx		; save ecx
	push  	edx		; save edx

	mov	eax, [ebp+8]	; eax = num
 	sub	eax, 2		; eax -= 2
	jns	next		; if not <0, goto next
 	add	eax, 2		; eax += 2
	jmp	end
next:
	mov	eax, [ebp+8]	; eax = num
	add	eax, -1		; eax -= 1
	push	eax		; put (num -1) on the stack
	call	f		; call f (recursively)
	add	esp, 4		; remove (num-1) from the stack
	mov	[ebp-4], eax	; put the returned value in x
	mov	eax, [ebp+8]	; eax = num
	add	eax, -2		; eax -= 2
	push	eax		; put (num -2) on the stack
	call	f		; call f (recursively), the return value is in eax
	add	esp, 4		; remove (num-1) from the stack
	add	eax, [ebp-4]	; eax += x

end:
	pop	edx		; restore ebx
	pop 	ecx		; restore ecx
	pop  	ebx		; restore edx
	leave			; clean up the stack
	ret			; return

ics312_recursivesum.asm [Download]

; This simple program takes 10 integers from the user and
; counts how many of these integers are odd

%include "asm_io.inc"

segment .data
	msg1		db	"Enter n: ", 0
	msg2		db	"The sum is: ", 0

segment .text
	global	asm_main
asm_main:
	enter	   0,0			; set up
	pusha				; set up

	mov		eax, msg1	; eax = address of msg1
	call		print_string	; print msg1
	call		read_int	; get an integer from the keyboard (in EAX)
	push		eax		; put the integer on the stack (parameter #1)
	call		recursive_sum	; call recursive_sum
	pop		ebx		; remove the parameter from the stack
	mov		ebx, eax	; save the value returned by recursive_sum
	mov		eax, msg2	; eax = address of msg2
	call		print_string	; print msg2
	mov		eax, ebx	; eax = sum
	call		print_int	; print the sum
	call		print_nl	; print a new line

	popa				; clean up
	mov	   eax, 0		; clean up
	leave				; clean up
	ret				; clean up

;   	FUNCTION: recursive_sum
; 	Takes one parameter:  an integer
; 	Destroys values of eax, ebx, ecx, and edx!! (eax = return value)
segment .bss
	value		resd  1		; to store the return value temporarily

segment .text
recursive_sum:
	push		ebp		; save ebp
	mov		ebp, esp	; set EBP = ESP
	pusha				; save all registers (probably overkill)
	mov		ebx, [ebp+8]	; ebx = integer (parameter #1)
	cmp		ebx, 0		; ebx = 0 ?
	jnz		next		; if (ebx != 0) go to next
	xor		ecx, ecx	; ECX = 0
	jmp		end		; Jump to end
next:
	mov		ecx, ebx	; ECX = EBX
	dec		ecx		; ECX = ECX - 1
	push		ecx		; put ECX on the stack
	call		recursive_sum	; recursive call to recursive_sum!
	pop		edx		; pop the parameter from the stack
	add		ebx, eax	; EBX = EBX + recursive_sum(EBX -1)
	mov		ecx, ebx	; ECX = EBX
end:					; at this point, ECX contains the result
	mov		[value], ecx	; save ECX, the return value, in memory
	popa				; restore all registers
	mov		eax, [value]	; put the saved returned value into eax

	pop		ebp		; restore EBP
	ret				; return