Difference between revisions of "CSC231 Homework 8 Solution 2012"

From dftwiki3
Jump to: navigation, search
(Option 2)
(Option 2)
Line 676: Line 676:
 
<br />
 
<br />
 
* Assemble, link, and then run the program
 
* Assemble, link, and then run the program
* Figure out what PID the process has:
+
* Figure out what PID the process has.  The command for that is '''ps''' typed at the prompt:
  
   ps  
+
   '''ps'''
 
   PID TTY          TIME CMD
 
   PID TTY          TIME CMD
 
   20543 pts/7    00:00:00 tcsh
 
   20543 pts/7    00:00:00 tcsh
Line 685: Line 685:
 
   20646 pts/7    00:00:00 ps
 
   20646 pts/7    00:00:00 ps
  
* Our process Id is 20645
+
* Our process Id is shown to be '''20645'''
 +
* Ask Linux what information it has about this process, using the command '''cat /proc/20645/maps''':
 
   
 
   
  cat /proc/20645/maps
+
  '''cat /proc/20645/maps'''
 
  08048000-08049000 r-xp 00000000 00:13 9935063                            /Users/classes/231a/handout/howMuchStack
 
  08048000-08049000 r-xp 00000000 00:13 9935063                            /Users/classes/231a/handout/howMuchStack
 
  f7707000-f7708000 r-xp 00000000 00:00 0                                  [vdso]
 
  f7707000-f7708000 r-xp 00000000 00:00 0                                  [vdso]
 
  fff73000-fff94000 rwxp 00000000 00:00 0                                  [stack]
 
  fff73000-fff94000 rwxp 00000000 00:00 0                                  [stack]
  
 +
* subtracting fff73000 from fff94000 we get  0x21000, or 135,168, or 135 KB.
 +
 +
* This is also the information we get by using the command '''cat /proc/20645/status''', whose output is shown below:
 +
 +
 +
'''cat /proc/20645/status '''
 +
Name: howMuchStack
 +
State: R (running)
 +
Tgid: 20119
 +
Pid: 20119
 +
PPid: 20060
 +
TracerPid: 0
 +
Uid: 17700 17700 17700 17700
 +
Gid: 17700 17700 17700 17700
 +
FDSize: 64
 +
Groups: 17700 17710
 +
VmPeak:     144 kB
 +
VmSize:     144 kB
 +
VmLck:       0 kB
 +
VmPin:       0 kB
 +
VmHWM:       4 kB
 +
VmRSS:       4 kB
 +
VmData:       4 kB
 +
'''VmStk:     136 kB'''
 +
VmExe:       4 kB
 +
VmLib:       0 kB
 +
VmPTE:       8 kB
 +
VmSwap:       0 kB
 +
Threads: 1
 +
SigQ: 0/63717
 +
SigPnd: 0000000000000000
 +
ShdPnd: 0000000000000000
 +
SigBlk: 0000000000000000
 +
SigIgn: 0000000000000000
 +
SigCgt: 0000000000000000
 +
CapInh: 0000000000000000
 +
CapPrm: 0000000000000000
 +
CapEff: 0000000000000000
 +
CapBnd: ffffffffffffffff
 +
Cpus_allowed: f
 +
Cpus_allowed_list: 0-3
 +
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,... 00000000,00000001
 +
Mems_allowed_list: 0
 +
voluntary_ctxt_switches: 3
 +
nonvoluntary_ctxt_switches: 3470
 +
 +
VmStk is the information for our stack: 136 KB.
  
 
<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 18:33, 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



Problem 3: Optional and Extra Credit

Option 1

  • First option: write a program that constantly pushes stuff in the stack until it seg-faults. Make it print the size of the stack as it do so.


;;; hwtest.asm
;;; a simple demo program to test I/O with
;;; a C "wrapper" program

%include "asm_io.inc"

             ;; -------------------------
             ;; data segment
             ;; -------------------------
             section .data
msg     db      "Hello! Please enter an integer number: ",0x00
msg2    db      "You have entered ",0x00
x       dd      0

             ;; -------------------------
             ;; code area
             ;; -------------------------
             section .text
             global  asm_main
asm_main:       

	mov	ebx, esp
for:	mov	eax, esp
	sub	eax, ebp
	neg	eax
	call	print_int
	call	print_nl
	
	sub	esp, 100000	;equivalent to pushing 100,000 bytes
	
	jmp	for


        ret


  • The output of the program is:
12
100012
200012
300012
400012
500012
600012
700012
800012
900012
...
11900012
12000012
12100012
12200012
12300012
12400012
12500012
Segmentation fault
  • So our program had about 12.5 MBytes of stack when it started. At least that's what was printed when the segmentation fault message was printed, but we cannot be sure that the stack was not actually larger. It is possible that there were many more messages from our program "queued" to come inside the Operating System buffer and ready to be printed when the privileged "Seg Fault" happened.

Option 2

  • write an infinite loop program, or program that runs for a long time without using the stack necessarily, and lookup its Process Id. Then look in the /proc directory maintained by Linux how much space is allocated to that process's stack.

Here's our infinite-loop program:

; howMuchStack.asm
; D. Thiebaut
; Infinite loop
;
             section .text
             global  _start
_start:	
	     jmp     _start



  • Assemble, link, and then run the program
  • Figure out what PID the process has. The command for that is ps typed at the prompt:
 ps 
 PID TTY          TIME CMD
 20543 pts/7    00:00:00 tcsh
 20641 pts/7    00:00:00 nasmld
 20645 pts/7    00:00:03 howMuchStack
 20646 pts/7    00:00:00 ps
  • Our process Id is shown to be 20645
  • Ask Linux what information it has about this process, using the command cat /proc/20645/maps:
cat /proc/20645/maps
08048000-08049000 r-xp 00000000 00:13 9935063                            /Users/classes/231a/handout/howMuchStack
f7707000-f7708000 r-xp 00000000 00:00 0                                  [vdso]
fff73000-fff94000 rwxp 00000000 00:00 0                                  [stack]
  • subtracting fff73000 from fff94000 we get 0x21000, or 135,168, or 135 KB.
  • This is also the information we get by using the command cat /proc/20645/status, whose output is shown below:


cat /proc/20645/status 
Name:	howMuchStack
State:	R (running)
Tgid:	20119
Pid:	20119
PPid:	20060
TracerPid:	0
Uid:	17700	17700	17700	17700
Gid:	17700	17700	17700	17700
FDSize:	64
Groups:	17700 17710 
VmPeak:	     144 kB
VmSize:	     144 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	       4 kB
VmRSS:	       4 kB
VmData:	       4 kB
VmStk:	     136 kB
VmExe:	       4 kB
VmLib:	       0 kB
VmPTE:	       8 kB
VmSwap:	       0 kB
Threads:	1
SigQ:	0/63717
SigPnd:	0000000000000000
ShdPnd:	0000000000000000
SigBlk:	0000000000000000
SigIgn:	0000000000000000
SigCgt:	0000000000000000
CapInh:	0000000000000000
CapPrm:	0000000000000000
CapEff:	0000000000000000
CapBnd:	ffffffffffffffff
Cpus_allowed:	f
Cpus_allowed_list:	0-3
Mems_allowed:	00000000,00000000,00000000,00000000,00000000,... 00000000,00000001
Mems_allowed_list:	0
voluntary_ctxt_switches:	3
nonvoluntary_ctxt_switches:	3470

VmStk is the information for our stack: 136 KB.