Difference between revisions of "CSC231 Homework 8 Solution 2012"

From dftwiki3
Jump to: navigation, search
(Problem #2)
(Problem #2)
Line 449: Line 449:
 
<br />
 
<br />
 
<source lang="asm">
 
<source lang="asm">
;;; File: hw8b.asm
+
;;; ; hw8b.asm
;;; Name: Emma Gould (edited by D. Thiebaut)
+
;;; ; Gavi Levy Haskell
;;; Account: 231a-ap
+
;;; ; 231a-ae
;;; Due: 11/7/12
+
;;; ;
;;; Description: This program computes and displays the first 10 rows of Pascal's triangle.
+
;;; ; Uses functions to print the first ten
;;; 01 00 00 00 00 00 00 00 00 00  
+
;;; ; lines of the Pascal Triangle in hex
;;; 01 01 00 00 00 00 00 00 00 00  
+
;;; ;
;;; 01 02 01 00 00 00 00 00 00 00  
+
;;; ; prints:
;;; 01 03 03 01 00 00 00 00 00 00  
+
;;; ;
;;; 01 04 06 04 01 00 00 00 00 00  
+
;;; 01 00 00 00 00 00 00 00 00 00
;;; 01 05 0A 0A 05 01 00 00 00 00  
+
;;; ; 01 01 00 00 00 00 00 00 00 00
;;; 01 06 0F 14 0F 06 01 00 00 00  
+
;;; ; 01 02 01 00 00 00 00 00 00 00
;;; 01 07 15 23 23 15 07 01 00 00  
+
;;; ; 01 03 03 01 00 00 00 00 00 00
;;; 01 08 1C 38 46 38 1C 08 01 00  
+
;;; ; 01 04 06 04 01 00 00 00 00 00
;;; 01 09 24 54 7E 7E 54 24 09 01  
+
;;; ; 01 05 0A 0A 05 01 00 00 00 00
;;;
+
;;; ; 01 06 0F 14 0F 06 01 00 00 00
;;; To assemble, link, and run: nasm -f elf -F stabs hw8b.asm ; ld -melf_i386 -o hw8b hw8b.o ; ./hw8b
+
;;; ; 01 07 15 23 23 15 07 01 00 00
 
+
;;; ; 01 08 1C 38 46 38 1C 08 01 00
 
+
;;; ; 01 09 24 54 7E 7E 54 24 09 01
;; -------------------------------
+
;;; ;
;; Data Section
+
;;; ;
;; -------------------------------
+
;;; ;    nasm -f elf -F stabs hw8b.asm
section .data
+
;;; ;     ld -melf_i386 -o hw8b hw8b.o
Pascal db 0,0,0,0,0,0,0,0,0,0 ; Pascal array of 10 bytes
+
;;; ;    ./hw8b
 
+
hexChars db "0123456789ABCDEF" ; list of hex characters
+
;; -----------------
hexCharLen equ 1 ; length of a single character
+
;; DATA SECTION
 
+
;; -----------------
space db "   " ; to space the characters of the array
+
section .data
spaceLen equ $-space ; length of space
+
Pascal times 10 db 0
 
+
hexChr db "0123456789ABCDEF"
newLine db 10 ; hex characters for new line
+
return db 10
newLineLen equ $-newLine ; length of newLine
+
space db " "
 
+
;; -------------------------------
+
;; -----------------
;; Code Section
+
;; CODE SECTION
;; -------------------------------
+
;; -----------------
section .text
+
section .text
global _start
+
global _start
 
 
;; -------------------------------
 
;; main program
 
;; -------------------------------
 
 
_start:
 
_start:
mov ebx, Pascal ; pass address of array in ebx
+
mov ebx, Pascal ; pass address of array in ebx
call init ; store 0 in Pascal array
+
call init ; store 0 in Pascal array and 1
; and 1 in first cell
+
; in first cell
 +
mov ecx, 10
 +
for: mov ebx, Pascal ; pass address of array
 +
call printArray ; print Pascal array
  
mov ecx, 10
+
mov ebx, Pascal
for: mov ebx, Pascal ; pass address of array in ebx
+
call nextLine ; compute next line of triangle
call printArray ; print Pascal array
 
  
mov ebx, Pascal ; pass address of array
+
loop for
call nextLine ; compute next line of triangle
 
 
 
loop for
 
  
 
;;; exit
 
;;; exit
mov eax, 1
+
mov eax, 1
mov ebx, 0
+
mov ebx, 0
int 0x80
+
int 0x80
  
;; -------------------------------
+
;;; init
;; function init takes the address
+
;;; recieves address of Pascal in ebx
;; in ebx and puts one in the first byte
+
;;; modifies no registers
;; at that address and zero in the other nine
 
;; bytes that follow
 
;; -------------------------------
 
 
init:
 
init:
mov     byte[ebx], 1 ; move 1 into the first cell
+
mov dword[ebx], 0 ; change first 4 terms to zero
mov edi, 1 ; edi <- index = 1
+
mov dword[ebx + 4], 0 ; change next 4 terms to 0
mov ecx, 9 ; ecx <- n = 9
+
mov word[ebx + 8], ; change last 2 terms to 0
for1: mov byte[ebx+edi], 0 ; Fib[n] <- 0
+
mov byte[ebx], 1 ; change first term of array to 1
inc edi ; index <- index + 1
+
ret
loop for1 ; n <- n - 1
 
ret
 
  
;; -------------------------------
+
;;; printArray
;; function printArray takes the address
+
;;; recieves address of Pascal in ebx
;; in ebx and prints it a byte at a time
+
;;; modifies eax, ebx, edx
;; in hexadecimal (by passing it to printByte)
 
;; between the string "0x" and three spaces
 
;; with a new line at the very beginning and end
 
;; -------------------------------
 
 
printArray:
 
printArray:
push ecx ; save ecx from main program
+
push ecx ; save outer loop position
call printNewLine
+
mov ecx, 10
 
+
.for:
mov ecx, 10 ; n = 10
+
push ecx ; save loop position
for3:
+
push ebx ; save address
push ecx ; save n
 
push ebx ; save address of Pascal array
 
 
 
pop ebx ; ebx <- address of Pascal array (from stack)
 
pop ecx ; ecx <- n (from stack)
 
mov edi, 10 ; edi <- 10
 
sub edi, ecx ; edi <- 10 - n
 
mov    eax, 0 ; eax <- 0 (initialize)
 
mov al, byte[ebx+edi] ; al <- Pascal[10 - n]
 
push ecx ; save n
 
push ebx ; save address of Pascal array
 
call printByte ; print the byte in al in hexadecimal
 
 
 
mov ecx, space ; ecx <- address of tab
 
mov edx, spaceLen ; edx <- length of tab
 
mov eax, 4 ; print " "
 
mov ebx, 1
 
int 0x80
 
 
 
pop ebx ; ebx <- return address of Pascal array (from stack)
 
pop ecx ; ecx <- n (returned from stack)
 
loop for3 ; n <- n - 1
 
 
 
call printNewLine
 
 
 
pop ecx ; ecx <- restore value from main program
 
 
 
ret
 
;; -------------------------------
 
;; function printNewLine takes no
 
;; parameters and simply prints a new line
 
;; -------------------------------
 
printNewLine:
 
push ebx
 
push ecx
 
mov eax, 4
 
mov ebx, 1
 
mov ecx, newLine
 
mov edx, newLineLen
 
int 0x80
 
pop ecx
 
pop ebx
 
ret
 
 
 
;; -------------------------------
 
;; function printByte takes the value
 
;; stored in eax and print the two nybbles
 
;; (most significant first) in al
 
;; -------------------------------
 
printByte:
 
rol al, 4 ; move most significant nybble to least
 
push eax ; save eax in stack
 
and eax, 0x0000000F ; get rid of upper nybble
 
 
 
mov ecx, hexChars ; ecx <- address of hexChars
 
add ecx, eax ; ecx <- address of hexChars + value of nybble
 
mov edx, hexCharLen ; edx <- length of a single character
 
 
 
mov eax, 4 ; print the character
 
mov ebx, 1
 
int 0x80
 
 
 
pop eax ; eax <- full hex value (from stack)
 
rol al, 4 ; move lower nybble back to least significant
 
and eax, 0x0000000F ; get rid of upper nybble
 
 
 
mov ecx, hexChars ; ecx <- address of hexChars
 
add ecx, eax ; ecx <- address of hexChars + value of nybble
 
mov edx, hexCharLen ; edx <- length of a single character
 
  
mov eax, 4 ; print the character
+
mov cl, byte[ebx] ; first digit
mov ebx, 1
+
ror ecx, 4       ; get correct digit
int 0x80
+
and ecx, 0x0F ; keep only this digit
 +
add ecx, hexChr ; add address of hexChr
 +
mov eax, 4
 +
mov ebx, 1
 +
mov edx, 1
 +
int 0x80 ; print first digit
  
ret
+
pop ebx
 +
push ebx
 +
mov cl, byte[ebx] ; second digit
 +
and ecx, 0x0F ; keep only this digit
 +
add ecx, hexChr ; add address of hexChr
 +
mov eax, 4
 +
mov ebx, 1
 +
mov edx, 1
 +
int 0x80 ; print second digit
  
;; -------------------------------
+
mov eax, 4
;; function nextLine uses the address stored in ebx
+
mov ebx, 1
;; to compute the next row of pascal's triangle
+
mov ecx, space
;; and stores it in the Pascal array
+
mov edx, 1
;; -------------------------------
+
int 0x80 ; print space
nextLine: push ecx
+
mov ecx, 9 ; ecx <- m = 9 (length of array - 1)
+
pop ebx
mov edi, 9 ; edi <- n = 9 (length of array - 1)
+
pop ecx ; retrieve loop position
 +
add ebx, 1
 +
 +
loop .for ; retrieve outer loop position
  
for4: mov al, byte[ebx+edi] ; al <- Pascal[n] (starting at the rightmost
+
mov eax, 4
; number and working left)
+
mov ebx, 1
add al, byte[ebx+edi-1] ; al <- Pascal[n-1]
+
mov ecx, return ; return
mov byte[ebx+edi], al ; Fib[n] <- al
+
mov edx, 1
dec edi ; n = n - 1
+
int 0x80 ; next line
loop for4 ; m = m - 1
+
 +
pop ecx
 +
ret
  
pop ecx
+
;;; nextLine
ret
+
;;; recieves address of Pascal in ebx
 +
;;; modifies eax, ebx
 +
nextLine:
 +
push ecx ; save outer loop position
  
 +
mov ecx, 9
 +
add ebx, 9
 +
.for:
 +
push ecx ; save loop position
 +
mov al, byte[ebx - 1] ; n = row[x - 1]
 +
add byte[ebx], al ; row[x] += n
 +
dec ebx ; x -= 1
 +
pop ecx ; retrieve loop position
 +
loop .for
  
 +
pop ecx ; retrieve loop position
 +
ret
 
</source>
 
</source>
 
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
 
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
 
<br /><br /><br /><br /><br /><br />
 
<br /><br /><br /><br /><br /><br />
 
[[Category:CSC231]][[Category:Homework]]
 
[[Category:CSC231]][[Category:Homework]]

Revision as of 12:29, 13 November 2012

--D. Thiebaut 12:15, 13 November 2012 (EST)


Problem #1, Version 1

This version contains the complete code. Version 2 below separates the dumpRegs functions and main program into two files.

;;; ---------------------------------------------------------
;;; hw8aSol.asm
;;; D. Thiebaut
;;; 11/13/12
;;; This program supports several functions that allow the user
;;; to dump the contents of the main 6 registers (eax, ebx, ecx,
;;; edx, esi and edi) to the screen.  Great for debugging without
;;; a debugger.
;;;
;;; Typical output:
;;; 	+-----------------+
;;; 	| eax = 1234 5678 |
;;; 	| ebx = 55FF 55FF |
;;; 	| ecx = FEDC BA98 |
;;; 	| edx = 0000 0000 |
;;; 	| esi = 1111 2222 |
;;; 	| edi = 2222 3333 |
;;; 	+-----------------+
;;; 	+-----------------+
;;; 	| eax = 1234 5678 |
;;; 	| ebx = 55FF 55FF |
;;; 	| ecx = FEDC BA98 |
;;; 	| edx = 0000 0000 |
;;; 	| esi = 1111 2222 |
;;; 	| edi = 2222 3333 |
;;; 	+-----------------+
;;;
;;; To assemble, link and run:
;;;   nasm -f elf hw8aSol.asm
;;;   ld -melf_i386 hw8aSol.o -o hw8aSol
;;;   ./hw8aSol
;;; ---------------------------------------------------------

		section	.data
hex		db	"0123456789ABCDEF"
regs		db	"axbxcxdxsidi"
line		db	"+-----------------+", 10
string		db	"| exx = .... .... |", 10
lineLen 	equ	$-string
reg		equ	string+3
word1		equ	string+8

		section	.text
		global	_start

_start:

;;; Initialize the registers
		mov	eax, 0x12345678
		mov	ebx, 0x55FF55FF
		mov	ecx, 0xFEDCBA98
		mov	edx, 0x00000000
		mov	esi, 0x11112222
		mov	edi, 0x22223333

;;; dump them twice to verify that no registers gets modified...
	        call    dumpRegs
		call	dumpRegs


;;; exit back to OS
		mov	ebx, 0
		mov	eax, 1
		int	0x80

;;; ---------------------------------------------------------
;;; dumpRegs: dumps the contents of the 6 main registers (eax
;;; ebx, ecx, edx, esi and edi) in a box on the screen.
;;; the screen.  Does not modify any register
;;; ---------------------------------------------------------
dumpRegs:	pushad

;;; put all the registers to print in the stack.  The loop
;;; will pop each one, one at a time, once per loop.
	
		push	edi
		push	esi
		push	edx
		push	ecx
		push	ebx
		push	eax

;;; print top bar
		call	printBar
	
;;; prepare to loop 6 times (6 registers )
		mov	ecx, 6
		mov	esi, 0

.for		pop	ebx			;get value of register to convert from stack
		push	ecx			;save loop counter
		lea	eax, [regs + esi*2]	;get address of string representing register
	
		mov	ax, word [eax] 		;ax gets "ax" or "bx" or "cx" or ... "di"
		mov	word[reg], ax		;modify string with name of register
	
		mov	edx, word1 		;edx points to buffer where to store hex digits
						;ebx contains register to convert
		call 	storeDWord		;store hex equivalent of ebx in string
	
		mov	ecx, string 		;print the whole string
		mov	edx, lineLen
		call	printInt80
		inc	esi			;index into register names incremented
		pop	ecx			;get loop counter back
		loop	.for

;;; print bottom bar
		call 	printBar
	
		popad
		ret

;;; ---------------------------------------------------------
;;; storeDWord: gets
;;; 	ebx: register to convert
;;; 	edx: address where to put information
;;; ---------------------------------------------------------
		
storeDWord:	rol	ebx, 16			;bring most sig word in least sig word
		call	storeWord
	
		inc	edx			;make edx skip space in string
	
		rol	ebx, 16			;get lower byte back in least sig pos
		call	storeWord
		
		ret

;;; ---------------------------------------------------------
;;; storeWord: gets
;;;     bx: word to convert
;;; 	edx: address where to put information. edx incremented by 4
;;; ---------------------------------------------------------
storeWord:	rol	bx, 8			;put most sig byte of bx in lower position
		call	storeByte		;and convert it.  Store it in where edx 
						;points to. 
		rol	bx, 8			;same with lower nybble
		call	storeByte
		ret
	
;;; ---------------------------------------------------------
;;; storeByte: gets
;;;     bl: byte to convert
;;; 	edx: address where to store information.  edx incremented by 2 automatically
;;; ---------------------------------------------------------
storeByte:	push	ebx
		push	eax
	
		rol	bl, 4			;get upper nybble in lower position (LSB)
		mov	al, bl			;play with al now
		and	eax, 0x0000000F		;clear all but the least significant nybble
		add	eax, hex		;get ascii in hex array equivalentn to nybble
		mov	al, [eax] 		;hex digit now in bl
		mov	byte [edx], al		;store ascii in string
		inc	edx

		rol	bl, 4			;get lower nybble back
		mov	al, bl			;play with al
		and	eax, 0x0000000F
		add	eax, hex
		mov	al, [eax]
		mov	byte [edx], al
		inc	edx
	
		pop	eax
		pop	ebx
		ret
		
;;; ---------------------------------------------------------
;;; printInt80: prints on the screen the string whose address
;;; is in ecx and length in edx.
;;; does not modify registers
;;; ---------------------------------------------------------
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
	
		pop	ebx
		pop	eax
		ret
	
;;; ---------------------------------------------------------
;;; printBar: prints the horizontal bar
;;; does not modify registers
;;; ---------------------------------------------------------
printBar:	push	ecx
		push	edx
	
		mov	ecx, line
		mov	edx, lineLen
		call	printInt80
	
		pop	edx
		pop	ecx
		ret


Problem #1, Version 2

Main Program


;;; ---------------------------------------------------------
;;; hw8aSol2.asm
;;; D. Thiebaut
;;; 11/13/12
;;; This program uses the library dumpRegs.asm to dump 
;;; the contents of the main 6 registers (eax, ebx, ecx,
;;; edx, esi and edi) to the screen.  Great for debugging without
;;; a debugger.
;;;
;;; Typical output:
;;; 	+-----------------+
;;; 	| eax = 1234 5678 |
;;; 	| ebx = 55FF 55FF |
;;; 	| ecx = FEDC BA98 |
;;; 	| edx = 0000 0000 |
;;; 	| esi = 1111 2222 |
;;; 	| edi = 2222 3333 |
;;; 	+-----------------+
;;; 	+-----------------+
;;; 	| eax = 1234 5678 |
;;; 	| ebx = 55FF 55FF |
;;; 	| ecx = FEDC BA98 |
;;; 	| edx = 0000 0000 |
;;; 	| esi = 1111 2222 |
;;; 	| edi = 2222 3333 |
;;; 	+-----------------+
;;;
;;; To assemble, link and run:
;;;   nasm -f elf hw8aSol.asm
;;;   ld -melf_i386 hw8aSol.o -o hw8aSol
;;;   ./hw8aSol
;;; ---------------------------------------------------------

%include "dumpRegs.asm"
	
		section	.text
		global	_start

_start:

;;; Initialize the registers
		mov	eax, 0x12345678
		mov	ebx, 0x55FF55FF
		mov	ecx, 0xFEDCBA98
		mov	edx, 0x00000000
		mov	esi, 0x11112222
		mov	edi, 0x22223333

;;; dump them twice to verify that no registers gets modified...
	        call    dumpRegs
		call	dumpRegs


;;; exit back to OS
		mov	ebx, 0
		mov	eax, 1
		int	0x80


Library


;;; ---------------------------------------------------------
;;; dumpRegs.asm
;;; D. Thiebaut
;;; 11/13/12
;;; This libary supports several functions that allow the user
;;; to dump the contents of the main 6 registers (eax, ebx, ecx,
;;; edx, esi and edi) to the screen.  Great for debugging without
;;; a debugger.
;;;
;;; Typical output:
;;; 	+-----------------+
;;; 	| eax = 1234 5678 |
;;; 	| ebx = 55FF 55FF |
;;; 	| ecx = FEDC BA98 |
;;; 	| edx = 0000 0000 |
;;; 	| esi = 1111 2222 |
;;; 	| edi = 2222 3333 |
;;; 	+-----------------+
;;; Include in program as follows:
;;; 
;;; 
;;; %include "dumpRegs.asm"
;;; ---------------------------------------------------------

		section	.data
hex		db	"0123456789ABCDEF"
regs		db	"axbxcxdxsidi"
line		db	"+-----------------+", 10
string		db	"| exx = .... .... |", 10
lineLen 	equ	$-string
reg		equ	string+3
word1		equ	string+8

		section	.text

;;; ---------------------------------------------------------
;;; dumpRegs: dumps the contents of the 6 main registers (eax
;;; ebx, ecx, edx, esi and edi) in a box on the screen.
;;; the screen.  Does not modify any register
;;; ---------------------------------------------------------
dumpRegs:	pushad

;;; put all the registers to print in the stack.  The loop
;;; will pop each one, one at a time, once per loop.
	
		push	edi
		push	esi
		push	edx
		push	ecx
		push	ebx
		push	eax

;;; print top bar
		call	printBar
	
;;; prepare to loop 6 times (6 registers )
		mov	ecx, 6
		mov	esi, 0

.for		pop	ebx			;get value of register to convert from stack
		push	ecx			;save loop counter
		lea	eax, [regs + esi*2]	;get address of string representing register
	
		mov	ax, word [eax] 		;ax gets "ax" or "bx" or "cx" or ... "di"
		mov	word[reg], ax		;modify string with name of register
	
		mov	edx, word1 		;edx points to buffer where to store hex digits
						;ebx contains register to convert
		call 	storeDWord		;store hex equivalent of ebx in string
	
		mov	ecx, string 		;print the whole string
		mov	edx, lineLen
		call	printInt80
		inc	esi			;index into register names incremented
		pop	ecx			;get loop counter back
		loop	.for

;;; print bottom bar
		call 	printBar
	
		popad
		ret

;;; ---------------------------------------------------------
;;; storeDWord: gets
;;; 	ebx: register to convert
;;; 	edx: address where to put information
;;; ---------------------------------------------------------
		
storeDWord:	rol	ebx, 16			;bring most sig word in least sig word
		call	storeWord
	
		inc	edx			;make edx skip space in string
	
		rol	ebx, 16			;get lower byte back in least sig pos
		call	storeWord
		
		ret

;;; ---------------------------------------------------------
;;; storeWord: gets
;;;     bx: word to convert
;;; 	edx: address where to put information. edx incremented by 4
;;; ---------------------------------------------------------
storeWord:	rol	bx, 8			;put most sig byte of bx in lower position
		call	storeByte		;and convert it.  Store it in where edx 
						;points to. 
		rol	bx, 8			;same with lower nybble
		call	storeByte
		ret
	
;;; ---------------------------------------------------------
;;; storeByte: gets
;;;     bl: byte to convert
;;; 	edx: address where to store information.  edx incremented by 2 automatically
;;; ---------------------------------------------------------
storeByte:	push	ebx
		push	eax
	
		rol	bl, 4			;get upper nybble in lower position (LSB)
		mov	al, bl			;play with al now
		and	eax, 0x0000000F		;clear all but the least significant nybble
		add	eax, hex		;get ascii in hex array equivalentn to nybble
		mov	al, [eax] 		;hex digit now in bl
		mov	byte [edx], al		;store ascii in string
		inc	edx

		rol	bl, 4			;get lower nybble back
		mov	al, bl			;play with al
		and	eax, 0x0000000F
		add	eax, hex
		mov	al, [eax]
		mov	byte [edx], al
		inc	edx
	
		pop	eax
		pop	ebx
		ret
		
;;; ---------------------------------------------------------
;;; printInt80: prints on the screen the string whose address
;;; is in ecx and length in edx.
;;; does not modify registers
;;; ---------------------------------------------------------
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
	
		pop	ebx
		pop	eax
		ret
	
;;; ---------------------------------------------------------
;;; printBar: prints the horizontal bar
;;; does not modify registers
;;; ---------------------------------------------------------
printBar:	push	ecx
		push	edx
	
		mov	ecx, line
		mov	edx, lineLen
		call	printInt80
	
		pop	edx
		pop	ecx
		ret


Problem #2


;;; ; hw8b.asm
;;; ; Gavi Levy Haskell
;;; ; 231a-ae
;;; ;
;;; ; Uses functions to print the first ten
;;; ; lines of the Pascal Triangle in hex
;;; ;
;;; ; prints:
;;; ;
;;; ;   01 00 00 00 00 00 00 00 00 00
;;; ;	01 01 00 00 00 00 00 00 00 00
;;; ;	01 02 01 00 00 00 00 00 00 00
;;; ;	01 03 03 01 00 00 00 00 00 00
;;; ;	01 04 06 04 01 00 00 00 00 00
;;; ;	01 05 0A 0A 05 01 00 00 00 00
;;; ;	01 06 0F 14 0F 06 01 00 00 00
;;; ;	01 07 15 23 23 15 07 01 00 00
;;; ;	01 08 1C 38 46 38 1C 08 01 00
;;; ;	01 09 24 54 7E 7E 54 24 09 01	
;;; ;
;;; ;
;;; ;     nasm -f elf -F stabs hw8b.asm
;;; ;     ld -melf_i386 -o hw8b hw8b.o
;;; ;     ./hw8b
	
	;; -----------------
	;; DATA SECTION
	;; -----------------
	section	.data
Pascal	times 10 db 0
hexChr	db	"0123456789ABCDEF"
return	db	10
space	db	" "
	
	;; -----------------
	;; CODE SECTION
	;; -----------------
	section	.text
	global	_start
_start:
	mov	ebx, Pascal	; pass address of array in ebx
	call	init		; store 0 in Pascal array and 1
				; in first cell
	mov	ecx, 10		
for:	mov	ebx, Pascal	; pass address of array
	call	printArray	; print Pascal array

	mov	ebx, Pascal
	call 	nextLine	; compute next line of triangle

 	loop	for

;;; exit
	mov	eax, 1
	mov	ebx, 0
	int	0x80

;;; init
;;; recieves address of Pascal in ebx
;;; modifies no registers
init:
	mov	dword[ebx], 0	; change first 4 terms to zero
	mov	dword[ebx + 4], 0 ; change next 4 terms to 0
	mov	word[ebx + 8], 0  ; change last 2 terms to 0
	mov	byte[ebx], 1	; change first term of array to 1
	ret

;;; printArray
;;; recieves address of Pascal in ebx
;;; modifies eax, ebx, edx
printArray:
	push	ecx		; save outer loop position
	mov	ecx, 10
.for:
	push	ecx		; save loop position
	push	ebx		; save address

 	mov	cl, byte[ebx] 	; first digit
	ror	ecx, 4	      	; get correct digit
 	and	ecx, 0x0F	; keep only this digit
 	add	ecx, hexChr	; add address of hexChr
 	mov	eax, 4
 	mov	ebx, 1
 	mov	edx, 1
 	int	0x80		; print first digit

	pop	ebx
	push	ebx
 	mov	cl, byte[ebx] 	; second digit
 	and	ecx, 0x0F	; keep only this digit
 	add	ecx, hexChr	; add address of hexChr
 	mov	eax, 4
 	mov	ebx, 1
 	mov	edx, 1
 	int	0x80		; print second digit

	mov	eax, 4
	mov	ebx, 1
	mov	ecx, space
	mov	edx, 1
	int	0x80		; print space
	
	pop	ebx
	pop	ecx		; retrieve loop position
	add	ebx, 1
	
	loop	.for		; retrieve outer loop position

	mov	eax, 4
	mov	ebx, 1
	mov	ecx, return	; return
	mov	edx, 1
	int	0x80		; next line
	
	pop	ecx
	ret

;;; nextLine
;;; recieves address of Pascal in ebx
;;; modifies eax, ebx
nextLine:
	push	ecx		; save outer loop position

	mov	ecx, 9
	add	ebx, 9
.for:
	push	ecx		; save loop position
	mov	al, byte[ebx - 1] ; n = row[x - 1]
	add	byte[ebx], al	; row[x] += n
	dec	ebx		; x -= 1
	pop	ecx		; retrieve loop position
	loop	.for

	pop	ecx		; retrieve loop position
	ret