//----------------------------------------------------------------
//	forkdemo.s
//
//	This program illustrates the Linux 'fork' and 'waitpid' 
//	system-calls.  The parent-process forks a child-process
//	which displays a message and then terminates, while the
//	parent waits for its child to finish.  After the parent
//	resumes execution, it displays its child's exit-status. 
//	
//	 assemble using: $ as forkdemo.s -o forkdemo.o
//	 and link using: $ ld forkdemo.o eax2hex.o -o forkdemo
//
//	programmer: ALLAN CRUSE
//	written on: 19 FEB 2006
//----------------------------------------------------------------

	# manifest constants
	.equ	sys_exit, 1
	.equ	sys_fork, 2
	.equ	sys_write, 4
	.equ	sys_waitpid, 7
	.equ	STDOUT, 1
	.equ	OPTIONS, 0

	.section	.data
pid:	.space		4		# holds fork return-value
status:	.space		4		# holds child exit-status
msg1:	.ascii		"\nChild-process says \'Hello\' \n"
len1:	.int		. - msg1	# length of child message
msg2:	.ascii		"\nParent-process says "
	.ascii		"'\Child-process terminated with status="
buf1:	.ascii		"xxxxxxxx\' \n\n"
len2:	.int		. - msg2	# length of parent message

	.section	.text
_start:	# fork a 'child' process
	movl	$sys_fork, %eax		# setup the service-ID
	int	$0x80			# invoke kernel service
	movl	%eax, pid		# save the return-value

	# control branches to parent or child
	cmpl	$0, pid			# did 'fork' return zero?
	je	child			# yes, child is executing
	jmp	parent			# else parent is executing
	
child:	# display a confirmation message
	movl	$sys_write, %eax	# setup the service-ID
	movl	$STDOUT, %ebx		# specify the device-ID
	leal	msg1, %ecx		# point to child message
	movl	len1, %edx		# length of this message
	int	$0x80			# invoke kernel service

	# terminate the child process
	movl	$sys_exit, %eax		# setup the service-ID
	movl	$0x12345678, %ebx	# specify the exit-code
	int	$0x80			# invoke kernel service

parent:	# wait for the child to finish
	movl	$sys_waitpid, %eax	# setup the service-ID
	movl	pid, %ebx		# specify the process-ID
	leal	status, %ecx		# point to status variable
	movl	$OPTIONS, %edx		# specify the 'wait' flags 
	int	$0x80			# invoke kernel service

	# format message #2 
	movl	status, %eax		# load 'status' into EAX
	leal	buf1, %edi		# point EDI to dst'n field
	call	eax2hex			# convert number to string

	# display parent's report
	movl	$sys_write, %eax	# setup the service-ID
	movl	$STDOUT, %ebx		# specify the device-ID
	leal	msg2, %ecx		# point to parent message
	movl	len2, %edx		# length of this message
	int	$0x80			# invoke kernel service

	# terminate the parent process
	movl	$sys_exit, %eax		# setup the service-ID
	movl	$0, %ebx		# specify the exit-code
	int	$0x80			# invoke kernel service

	.global	_start			# make entry-point visible
	.end				# nothing more to assemble