Difference between revisions of "CSC231 Top-Down Design Example"

From dftwiki3
Jump to: navigation, search
(Version 5)
(Version 6)
 
(One intermediate revision by the same user not shown)
Line 345: Line 345:
  
 
==Version 5==
 
==Version 5==
<source lang=asm highlight="50,76-82,90-97">
+
<source lang=asm highlight="50,76-82,91-97">
 
;;; towDown.asm
 
;;; towDown.asm
 
;;; in this version we modify the functions to print extra stars to form a box
 
;;; in this version we modify the functions to print extra stars to form a box
Line 475: Line 475:
  
 
==Version 6==
 
==Version 6==
<source lang=asm>
+
<source lang=asm highlight="17-28">
 
;;; towDown.asm
 
;;; towDown.asm
 
;;; in this version we create a loop to print all the boxed names.
 
;;; in this version we create a loop to print all the boxed names.
 +
;;; we also change the "for" labels into ".for" (local labels)
  
 
section .data
 
section .data
Line 614: Line 615:
  
 
</source><br /><br />
 
</source><br /><br />
 +
 
==Version 7==
 
==Version 7==
 
<source lang=asm>
 
<source lang=asm>

Latest revision as of 11:25, 4 November 2012

--D. Thiebaut 10:53, 4 November 2012 (EST)


Evolution of a program through the top-down design approach. The problem is given this data structure:


strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"

write a program that prints all strings (preceded by the number of chars they contain) in a box of stars.

Version 1

;;; towDown.asm
;;; only the main program is expanded here.

		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"

		section	.text
		global	_start
_start:	


		mov	eax, strings+0 ; eax <- address count+string
		call	printBoxName

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	eax		;eax contains address of 5
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5

		mov	al, byte[eax]   ;al contains 5
		call	printStars
		ret

;;; ----------------------------------------------------------------------
;;; printStars
printStars:
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		ret



Version 2

;;; towDown.asm
;;; in this version we expand printName
	
		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"

		section	.text
		global	_start
_start:	


		mov	eax, strings+0 ; eax <- address count+string
		call	printBoxName

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	eax		;eax contains address of 5
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5

		mov	al, byte[eax]   ;al contains 5
		call	printStars
		ret

;;; ----------------------------------------------------------------------
;;; printStars
printStars:
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		push	eax		; save registers
		push	ebx
		push	ecx
		push	edx

		mov	dl, byte[eax] 	;get # chars in dl
		and	edx,0x000000ff  ;clear upper part of edx (not dl)

		inc	eax		;eax points to string
		mov	ecx, eax	;ecx points to string
		mov	eax, 4
		mov	ebx, 1
		int	0x80
	
		pop	edx		;restore the registers
		pop	ecx
		pop	ebx
		pop	eax
		ret


Version 3

;;; towDown.asm
;;; in this version we  modify printName and add printInt80
	
		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"

		section	.text
		global	_start
_start:	


		mov	eax, strings+0 ; eax <- address count+string
		call	printBoxName

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	eax		;eax contains address of 5
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5

		mov	al, byte[eax]   ;al contains 5
		call	printStars
		ret

;;; ----------------------------------------------------------------------
;;; printStars
printStars:
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		push	eax		; save registers
		push	ebx
		push	ecx
		push	edx

		mov	dl, byte[eax] 	;get # chars in dl
		and	edx,0x000000ff  ;clear upper part of edx (not dl)

		inc	eax		;eax points to string
		mov	ecx, eax	;ecx points to string
		call	printInt80
	
		pop	edx		;restore the registers
		pop	ecx
		pop	ebx
		pop	eax
		ret

;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
		pop	ebx
		pop	eax
		ret


Version 4

;;; towDown.asm
;;; in this version we expand printStars and print a new-line after the name and the line of stars

		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"
oneStar		db	'* '
nl		db	0x0a
	
		section	.text
		global	_start
_start:	


		mov	eax, strings+0 ; eax <- address count+string
		call	printBoxName

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	eax		;eax contains address of 5
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5

		mov	al, byte[eax]   ;al contains 5
		call	printStars
		ret

;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
		push	eax
		push	ecx
		push	edx
	
		mov	ecx, oneStar
		mov	edx, 1
for:		call	printInt80
		dec	al
		jnz	for

		mov	ecx, nl
		call 	printInt80
	
		pop	edx
		pop	ecx
		pop	eax
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		push	eax		; save registers
		push	ebx
		push	ecx
		push	edx

		mov	dl, byte[eax] 	;get # chars in dl
		and	edx,0x000000ff  ;clear upper part of edx (not dl)

		inc	eax		;eax points to string
		mov	ecx, eax	;ecx points to string
		call	printInt80

		mov	ecx, nl
		mov	edx, 1
		call	printInt80
	
		pop	edx		;restore the registers
		pop	ecx
		pop	ebx
		pop	eax
		ret

;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
		pop	ebx
		pop	eax
		ret


Version 5

;;; towDown.asm
;;; in this version we modify the functions to print extra stars to form a box

		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"
oneSpace	db	' '	
oneStar		db	'*'
nl		db	0x0a
	
		section	.text
		global	_start
_start:	


		mov	eax, strings+0 ; eax <- address count+string
		call	printBoxName

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	eax		;eax contains address of 5
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5

		mov	al, byte[eax]   ;al contains 5
		call	printStars
		ret

;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
		push	eax
		push	ecx
		push	edx

		add	al, 2+2		; add 2 stars in front and back
		mov	ecx, oneStar
		mov	edx, 1 		; print 1 start
for:		call	printInt80
		dec	al
		jnz	for

		mov	ecx, nl
		call 	printInt80
	
		pop	edx
		pop	ecx
		pop	eax
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		push	eax		; save registers
		push	ebx
		push	ecx
		push	edx

		mov	ecx, oneStar 	; print '*'
		mov	edx, 1
		call	printInt80
	
		mov	ecx, oneSpace   ; print ' '
		mov	edx, 1
		call	printInt80

		mov	dl, byte[eax] 	;get # chars in dl
		and	edx,0x000000ff  ;clear upper part of edx (not dl)

		inc	eax		;eax points to string
		mov	ecx, eax	;ecx points to string
		call	printInt80

		mov	ecx, oneSpace 	; print ' '
		mov	edx, 1
		call	printInt80

		mov	ecx, oneStar 	; print '*'
		mov	edx, 1
		call	printInt80
	
		mov	ecx, nl		; go to the next line
		mov	edx, 1
		call	printInt80
	
		pop	edx		;restore the registers
		pop	ecx
		pop	ebx
		pop	eax
		ret

;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
		pop	ebx
		pop	eax
		ret


Version 6

;;; towDown.asm
;;; in this version we create a loop to print all the boxed names.	
;;; we also change the "for" labels into ".for" (local labels)

		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"
oneSpace	db	' '	
oneStar		db	'*'
nl		db	0x0a
	
		section	.text
		global	_start
_start:	

		mov	ecx, 3
	
		mov	eax, strings+0 ; eax <- address count+string
	
.for:		call	printBoxName

		mov	bl, byte[eax]   ; bl gets # bytes
		and	ebx, 0x000000ff ; extend bl in ebx
		inc	ebx		; add 1 for byte containing #
		add	eax, ebx	; make eax point to next string
		loop	.for

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	eax		;eax contains address of 5
	
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5
		push	eax
	
		mov	al, byte[eax]   ;al contains 5
		call	printStars

		pop	eax
		ret

;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
		push	eax
		push	ecx
		push	edx

		add	al, 2+2		; add 2 stars in front and back
		mov	ecx, oneStar
		mov	edx, 1 		; print 1 start
.for:		call	printInt80
		dec	al
		jnz	.for

		mov	ecx, nl
		call 	printInt80
	
		pop	edx
		pop	ecx
		pop	eax
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		push	eax		; save registers
		push	ebx
		push	ecx
		push	edx

		mov	ecx, oneStar 	; print '*'
		mov	edx, 1
		call	printInt80
	
		mov	ecx, oneSpace   ; print ' '
		mov	edx, 1
		call	printInt80

		mov	dl, byte[eax] 	;get # chars in dl
		and	edx,0x000000ff  ;clear upper part of edx (not dl)

		inc	eax		;eax points to string
		mov	ecx, eax	;ecx points to string
		call	printInt80

		mov	ecx, oneSpace 	; print ' '
		mov	edx, 1
		call	printInt80

		mov	ecx, oneStar 	; print '*'
		mov	edx, 1
		call	printInt80
	
		mov	ecx, nl		; go to the next line
		mov	edx, 1
		call	printInt80
	
		pop	edx		;restore the registers
		pop	ecx
		pop	ebx
		pop	eax
		ret

;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
		pop	ebx
		pop	eax
		ret


Version 7

;;; towDown.asm
;;; in this version we clean up the code.

		section	.data
strings		db	5, "Hello"
		db	6, "Sharon"
		db	7, "Pamela!"
oneSpace	db	' '	
oneStar		db	'*'
nl		db	0x0a
	
		section	.text
		global	_start
_start:	

		mov	ecx, 3
	
		mov	eax, strings+0 ; eax <- address count+string
	
.for:		call	printBoxName

		mov	bl, byte[eax]   ; bl gets # bytes
		and	ebx, 0x000000ff ; extend bl in ebx
		inc	ebx		; add 1 for byte containing #
		add	eax, ebx	; make eax point to next string
		loop	.for

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

;;; ----------------------------------------------------------------------
;;; printBoxName
printBoxName:	push	ecx
		push	edx
		push	eax		;eax contains address of 5
	
		mov	al,byte[eax]	;al contains 5
		call	printStars

		pop	eax		;address of 5
		push	eax		;put the address of 5 back in stack
	
		call	printName
		pop	eax		;get back address of 5
		push	eax
	
		mov	al, byte[eax]   ;al contains 5
		call	printStars

		mov	ecx, nl		;print extra nl char
		mov	edx, 1
		call	printInt80
	
		pop	eax
		pop	edx
		pop	ecx
		ret

;;; ----------------------------------------------------------------------
;;; printStars
;;; gets the number of stars to print in al
;;; maintains all the other registers
printStars:
		push	eax
		push	ecx
		push	edx

		add	al, 2+2		; add 2 stars in front and back
		mov	ecx, oneStar
		mov	edx, 1 		; print 1 start
.for:		call	printInt80
		dec	al
		jnz	.for

		mov	ecx, nl
		call 	printInt80
	
		pop	edx
		pop	ecx
		pop	eax
		ret
	
;;; ----------------------------------------------------------------------
;;; printName
;;; gets the address of the byte containing the number of chars to print
;;; in eax.  address of string is at eax+1
;;; Does not modify any registers.
printName:
		push	eax		; save registers
		push	ebx
		push	ecx
		push	edx

		mov	ecx, oneStar 	; print '*'
		mov	edx, 1
		call	printInt80
	
		mov	ecx, oneSpace   ; print ' '
		mov	edx, 1
		call	printInt80

		mov	dl, byte[eax] 	;get # chars in dl
		and	edx,0x000000ff  ;clear upper part of edx (not dl)

		inc	eax		;eax points to string
		mov	ecx, eax	;ecx points to string
		call	printInt80

		mov	ecx, oneSpace 	; print ' '
		mov	edx, 1
		call	printInt80

		mov	ecx, oneStar 	; print '*'
		mov	edx, 1
		call	printInt80
	
		mov	ecx, nl		; go to the next line
		mov	edx, 1
		call	printInt80
	
		pop	edx		;restore the registers
		pop	ecx
		pop	ebx
		pop	eax
		ret

;;; ----------------------------------------------------------------------
;;; printInt80
;;; gets the address and # of chars to print in ecx and edx.
;;; maintains eax and ebx.
printInt80:	push	eax
		push	ebx
	
		mov	eax, 4
		mov	ebx, 1
		int	0x80
		pop	ebx
		pop	eax
		ret