pgubook-readers
[Top][All Lists]
Advanced

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

Re: [Pgubook-readers] Chapt 5 - Heynow Create Files Exercise


From: Mark Schmid
Subject: Re: [Pgubook-readers] Chapt 5 - Heynow Create Files Exercise
Date: Tue, 25 Sep 2007 12:09:04 +0200

Hi Emmet,

> My experience (which is not particularly current) is that gdb fails to 
> execute a break point placed on the very first instruction of a program. 
> A breakpoint placed elsewhere should fare better.
> 
> --Emmet Ford

Actually I didn't set the break point to line 1 at first.
First I tried setting it to line 10.
Then one to line 20, 30 and 55 and finally, when NOTHING
could stop gdb, I set one to line 1 (just because I
did not know if these are source code lines or 
machine code lines, in which case I wouldn't even
know if my program had 20 or more lines).
NOTHING stopped gdb.
It does show the break points correctly though when
I enter "info breakpoints".
It nicely lists all break points, it just doesn't 
pay attention to them...
:-(

Anyway, here's the good news of today: :-)
I debugged my program myself, fresh morning = fresh ideas!
:-)
I noticed right away that in my former program my cmpl
which was supposed to find the string terminating 0 (NUL)
character was simply not working because I was comparing
apples and oranges! Or actually LONGs and BYTEs!
:-)

After some testing with a hand-made debugger (which is
simple an inserted piece of code which writes a register
value of interest into %ebx and then exits the program
so you can check on that register after running the program
wich echo $?), I was able to correct the error.

I ALSO found out why my output file "heynow.txt" STILL
wasn't displaying right with cat, even though it no longer 
added three 0 (NUL) characters at the end of the text before 
*sombody* inside the kernel thankfully stopped my previously 
non-stopping write-loop for me:
On Linux, unlike on Windows, EVERY text file should end with
a LF, Line Feed Character (ASCII #10). If it does not have
that at the end, "cat" will not display it at all and vi
will state "Partial last line" at the bottom of the screen
when opening heynow.txt without an ending LF in it.

Anyway, here's my final working version, 
just if someone is curious:

------------------------------------
########################################################################
###             heynow.s - Create "heynow.txt" file.                 ###
########################################################################
# PURPOSE:      This program creates a file with the name "heynow.txt"
#               which contains the text "Hey diddle diddle!".
#
# REGISTERS:    %esi - Used to hold the current memory address
#                      of the next byte of filetext to write.
#                      (Initialized with $filetext, then 
#                      $STRING_ELEMENT_SIZE is added in every loop
#                      pass.
#               %edi - Used as current offset from starting memory
#                      address of filetext.


########################################################################
.section .data

############# CONSTANTS ################
# System Call Numbers:
.equ SYS_OPEN, 5
.equ SYS_WRITE, 4
.equ SYS_READ, 3
.equ SYS_CLOSE, 6
.equ SYS_EXIT, 1

# Options for open (look at /usr/include/asm/fcntl.h for various
# values. - You can combine them by ADDing them or ORing them.)
.equ O_RDONLY, 0
.equ O_CREAT_WRONGLY_TRUNC, 03101

# Some standard file descriptors (perhaps not needed):
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2

# System call interrupt:
.equ LINUX_SYSCALL, 0x80

# End of string marker:
.equ END_OF_STRING, 0


# Define beginning of 'filename' label here:
filename:
.byte 'h','e','y','n','o','w','.','t','x','t',0
# Should be same as: .ascii "heynow.txt\0"

# Define beginning of 'filetext' label here:
# CAUTION:      Make sure you do NOT have a trailing 0 (NUL) byte in
#               your file or any opening program will assume it is a
#               binary file and NOT a text file!
#               On Windows, we do NOT need ANY terminating characters
#               for the file to be recognized as text file. Use 
#               Carriage Return (CR=ASCII #13) AND Line Feed 
#               (LF=ASCII #10) to end each line on Windows text files.
#               On UNIX, lines end with only a Line Feed (LF=ASCII #10)
#               AND, EVERY text file MUST END with one single Line
#               Feed (ASCII character #10) at the end to be recognized
#               and displayed correctly as a text file such as with
#               cat textfile.txt!
filetext:
.byte 'H','e','y',' ','d','i','d','d','l','e',' 
','d','i','d','d','l','e','!',10,0
# NOTE: Make sure EVERYTHING after .byte is on ONE LINE in your code
#       if your display/editor broke the line to two lines because
#       it's too long, otherwise you'll get an assembly error!
# Should be same as: .ascii "Hey diddle diddle!\n\0"

# Define STRING_ELEMENT_SIZE as used above:
.equ STRING_ELEMENT_SIZE, 1     # Byte, Ascii = 1, Int = 2, Long = 4


########################################################################
.section .bss

# Reserve space for output file descriptor:
.equ FILE_DESCRIPTOR_SIZE, 4
.lcomm FILE_DESCRIPTOR_OUT, FILE_DESCRIPTOR_SIZE



########################################################################
.section .text

.globl _start
_start:

### OPEN OUTPUT FILE: ###
# Open System call must be in %eax:
movl $SYS_OPEN, %eax
# Pointer to output file name must be in %ebx:
# (filename = first byte at filename = 'h', $filename = actual
# address number of first byte of filename = POINTER)
movl $filename, %ebx
# Flags for writing to the file must be in %ecx:
movl $O_CREAT_WRONGLY_TRUNC, %ecx
# Permission set for new file (if it's created) must be in %edx:
movl $0666, %edx
# Make system call to Linux:
int $LINUX_SYSCALL

# Store File Descriptor of output file returned by 
# Linux system call in %eax:
movl %eax, FILE_DESCRIPTOR_OUT



# Set filetext index counter %edi needed in this loop to 0:
movl $0, %edi

# Store first memory address of filetext in %esi so we can
# add the filetext index counter to that to iterate through
# the memory addresses of filetext:
movl $filetext, %esi

### BEGIN BYTE WRITING LOOP ###
byte_writing_loop_begin:

 # See if we've reached the end of the string yet:
 # For this, we must first fetch the value from the current
 # buffer position (which the pointer stored in %esi points
 # to) and store it in %eax, so we can see WHAT it is. We
 # do this with "Indirect Addressing Mode":
 # movl (%esi), %eax    # FALSE! NOT A LONG!
 # NOW we can compare the current value with END_OF_STRING:
 # cmpl $END_OF_STRING, %eax    # FALSE! NOT A LONG!
 
 # CAUTION! You're dealing with BYTES! NOT LONGs!
 movb (%esi), %al
 cmpb $END_OF_STRING, %al

# BUGHUNTING ROUTINE:
# Exit the program here to check what's in %al:
# movl $0, %ebx         # Write 0 in %ebx to clear all 32 bits.
# movb %al, %bl         # Copy %al into lowest byte of %ebx.
# movl $END_OF_STRING, %ebx     # OR: See what's in $END_OF_STRING
# movl $1, %eax         # Set up %eax with 1 as EXIT code.
# int $0x80             # Interrupt: Call Linx

 # If second value is less or equal to first, go to end:
 jle byte_writing_loop_end
 
 ### WRITE SINGLE BYTE TO THE OUTPUT FILE ###
 # Move the WRITE System Call number into %eax:
 movl $SYS_WRITE, %eax
 # Move the Pointer of the output File Descriptor into %ebx:
 movl FILE_DESCRIPTOR_OUT, %ebx
 # Move pointer (=the beginning memory address) to the buffer to
 # write (that's $filetext + $STRING_ELEMENT_SIZE in %esi) into 
 # %ecx:
 movl %esi, %ecx
 # Move the size of the buffer being written into %edx:
 movl $STRING_ELEMENT_SIZE, %edx
 # Make the sytem call to write this to the output file descriptor:
 int $LINUX_SYSCALL
 
 # Add the STRING_ELEMENT_SIZE to the starting memory address
 # of filetext (=$filetext) (stored in %esi) and store that in 
 # %esi:
 addl $STRING_ELEMENT_SIZE, %esi 

 # Increase index counter %edi:
 incl %edi
 
 # Jump back to beginning of loop:
 jmp byte_writing_loop_begin
 
byte_writing_loop_end:
### END BYTE WRITING LOOP ###

### CLOSE OUTPUT FILE: ###
# Move the close file system call number into %eax:
movl $SYS_CLOSE, %eax
# Move the pointer to the output File Descriptor into %ebx:
movl FILE_DESCRIPTOR_OUT, %ebx
# Make the system call to Linux:
int $LINUX_SYSCALL

### EXIT PROGRAM ###
# Move the exit system call number into %eax:
movl $SYS_EXIT, %eax
# Move the return status $0 into %ebx:
movl $0, %ebx
# Make the system call to Linux:
int $LINUX_SYSCALL

------------------------------------

Writing your first OWN assembly code program that WORKS
is truly TREMENDOUSLY SATISFYING!!
:-))))

Greetings,
Mark

-- 
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kanns mit allen: http://www.gmx.net/de/go/multimessenger




reply via email to

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