pgubook-readers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pgubook-readers] toupper segmentation fault - please help - 2


From: Felix Chivite
Subject: [Pgubook-readers] toupper segmentation fault - please help - 2
Date: Tue, 12 Jul 2005 02:13:51 +0100 (BST)

 I'm using a 2003 edition of "Programming from the Ground Up", I've got through to chapter 4 without problems and also managed to assemble and link toupper in chapter 5, but when I try to run it as indicated (./toupper toupper.s toupper.uppercase), the console returns a segmentation fault.

After a few searches I've learned that this is probably a problem with memory addressing, or pointers or arrays. I've checked my source file against the original in the book many times but I can't see where I've gone wrong. Could anybody help? Thank you all in advance,

Felix (a complete beginner).

There follows a copy of my source file:


# Purpose:	This program converts an input file to an output file with all the letters converted to                #			uppercase

# Processing:	1. Open the input file
#		2. Open the output file
#		3. While we are not at the end of the input file
#			a. read part of file into our memory buffer
#			b. go through each bit of memory - if the byte is a lower case letter, convert to          #			uppercase
#			c. write the memory buffer to output file

.section .data

	#CONSTANTS#
	#SYSTEM CALL NUMBERS - They go into eax
	.equ SYS_OPEN, 5
	.equ SYS_WRITE, 4
	.equ SYS_READ, 3
	.equ SYS_CLOSE, 6
	.equ SYS_EXIT, 1

	#OPTIONS FOR OPEN FILE
	.equ O_RDONLY, 0
	.equ O_CREAT_WRONLY_TRUNC, 03101

	#STANDARD FILE DESCRIPTORS
	.equ STDIN, 0
	.equ STDOUT, 1
	.equ STERR, 2

	#SYSTEM CALL INTERRUPT
	.equ LINUX_SYSCALL, 0x80

	#RETURN VALUE OF READ - this means that we have reached the end of the file
	.equ END_OF_FILE, 0

	.equ NUMBER_ARGUMENTS, 2

.section .bss	#This is where the data is loded into from the data file and written from into the output file
	.equ BUFFER_SIZE, 500
	.lcomm BUFFER_DATA, BUFFER_SIZE	# this directive, .lcomm, will create a symbol,  								#BUFFER_DATA, that refers to a BUFFER_SIZE
							# storage location that we can use as a buffer

.section .text

	#STACK POSITIONS
	.equ ST_SIZE_RESERVE, 8
	.equ ST_FD_IN, -4	# FD means file descriptor
	.equ ST_FD_OUT, -8
				# ARGV=file opening arguments automatically stored by Linux in the stack, 				#these take care
				# of the command line input automatically
	.equ ST_ARGC, 0		# number of arguments
	.equ ST_ARGV_0, 4	# name of program
	.equ ST_ARGV_1, 8	# name of input file
	.equ ST_ARGV_2, 12	# name of output file

.globl _start
_start:
		# INITIALISE PROGRAM
	
	movl %esp, %ebp			# save the stack pointer
	subl $ST_SIZE_RESERVE, %esp	# allocate space for our file descriptors, FD, on the stack
open_files:

		# OPEN INPUT FILES
	
open_fd_in:
	movl $SYS_OPEN, %eax		# open system call
	movl ST_ARGV_1(%ebp), %ebx	# input filename into ebx
	movl $O_RDONLY, %ecx		# read only flag - read/write mode number
	movl $0666, %edx		# permission number - not really necessary for reading
	int $LINUX_SYSCALL		# call linux, the system call number is in eax

store_fd_in:
	movl %eax, ST_FD_IN(%ebp)	# store the file descriptor here (stack loc. -4)

		# OPEN OUTPUT FILES
	
open_fd_out:
	movl $SYS_OPEN, %eax			# open the output file
	movl ST_ARGV_2(%ebp), %ebx		# filename goes into ebx
	movl $O_CREAT_WRONLY_TRUNC, %ecx	# flag for writing to the file
	movl $0666, %edx			# permission for creating file
	int $SYS_OPEN				# call linux - system call number is in eax

store_fd_out:
	movl %eax, ST_FD_OUT(%ebp)	# store the file descriptor here (stack loc. -8)

		# BEGIN MAIN LOOP

read_loop_begin:			# read a  block from the input file
	movl SYS_READ, %eax		# system call code for reading (n.3) goes into eax
	movl ST_FD_IN(%ebp), %ebx	# get the input file descriptor
	movl $BUFFER_DATA, %ecx		# the location to read into
	movl $BUFFER_SIZE, %edx		# indicate the size of the buffer
	int $LINUX_SYSCALL		# size of buffer read is returned in eax

		# EXIT IF WE'VE REACHED THE END

	cmpl $END_OF_FILE, %eax	# check if we have reached the end of file marker (n.0)
	jle end_loop			# if found or in error, go to end

continue_read_loop:			# convert the block to upper case
	pushl $BUFFER_DATA		# location of buffer
	pushl %eax			# size of the buffer
	call convert_to_upper
	popl %eax			# get the size back
	addl $4, %esp			# restore %esp

		# WRITE BLOCK OUT TO OUTPUT FILE

	movl %eax, %edx
	movl $SYS_WRITE, %eax		# system call n.
	movl ST_FD_OUT(%ebp), %ebx	# file to use
	movl $BUFFER_DATA, %ecx		# location of the buffer
	int $LINUX_SYSCALL

		# CONTINUE THE LOOP

	jmp read_loop_begin

end_loop:

		# CLOSE THE FILES

	movl $SYS_CLOSE, %eax
	movl ST_FD_OUT(%ebp), %ebx	# close output file
	int $LINUX_SYSCALL

	movl $SYS_CLOSE, %eax
	movl ST_FD_IN(%ebp), %ebx	# close input file
	int $LINUX_SYSCALL

		# EXIT

	movl $SYS_EXIT, %eax
	movl $0, %ebx			# exit status n. goes into ebx
	int $LINUX_SYSCALL


	# FUNCTION convert_to_upper

	# Purpose: this function does the conversion to upper case for a block

	# Input: the first parameter is the location of the block of memory to convert
	#	 the sencond is the length of that buffer

	# Variables:	%eax - beginning of buffer
	#		%ebx - legth of buffer
	#		%edi - current buffer offset
	#		%cl  - current byte being examined (first part of %ecx)

	#CONSTANTS
	.equ LOWERCASE_A, 'a'	# the lower boundary of our search - ASCII characters are inputed between apostrophes
	.equ LOWERCASE_Z, 'z'	# the upper boundary of our search
	.equ UPPER_CONVERSION, 'A' - 'a'

	#STACK LOCATIONS, ETC
	.equ ST_BUFFER_LEN, 8	# Length of buffer
	.equ ST_BUFFER, 12	# actual buffer

convert_to_upper:
	pushl %ebp
	movl %esp, %ebp

	# SET UP VARIABLES

	movl ST_BUFFER(%ebp), %eax
	movl ST_BUFFER_LEN(%ebp), %ebx
	movl $0, %edi
	cmpl $0, %ebx		# if a buffer with zero length was given to us, exit
	je end_convert_loop	# jump if equal

convert_loop:
	movb (%eax,%edi,1), %cl	# get the current byte
	cmpb $LOWERCASE_A, %cl
	jl next_byte			# go to the next byte unless it is between 'a' and 'z'
	cmpb $LOWERCASE_Z, %cl
	jg next_byte			# jump if second value greater than first

		# otherwise, convert to uppercase
	
	addb $UPPER_CONVERSION, %cl

		# and store it back

	movb %cl, (%eax, %edi,1)

next_byte:
	incl %edi		# load next byte
	cmpl %edi, %ebx
	jne convert_loop	# continue unless we've reached the end

end_convert_loop:
	movl %ebp, %esp
	popl %ebp
	ret
	




Visit my homepage on www.geocities.com/felixchivite


Yahoo! Messenger NEW - crystal clear PC to PC calling worldwide with voicemail
reply via email to

[Prev in Thread] Current Thread [Next in Thread]