I am trying to convert a seemingly simple function written in C into assembly. My assembly subroutine seems to work, except when it returns to main, *pCombo contains garbage. When I step through the debugger, it seems to put the characters in the right place, I suspect there is an issue in one of my addressing modes but at this point I am not sure.
I have included the main program, as well as the function to print out the input read in the assembly subroutine.
GDB trace (abcd is the input):
make main.gdb
as --gstabs -o readCombo.o readCombo.s
gcc -g -c main.c
g++ -o main.out readCombo.o main.o
gdb main.out
(gdb) r
Starting program: /home2/mccoyd/main.out
abcd
P�@
C Code
void readCombo(char *pCombo, unsigned n)
{
char ch;
int result;
do
{
result = read(0, &ch, 1);
if ((result != 0) and (n > 0))
{
*pCombo = ch;
n = n - 1;
pCombo = pCombo + 1;
}
}
while (result && ch != 10);
}
int main(void)
{
char x[5];
char y[5];
char nl = '\n';
readCombo(x, sizeof(x));
writeCombo(x, sizeof(x));
}
void writeCombo(const char *pCombo, unsigned n)
{
while (n > 0)
{
write(1, pCombo, 1);
pCombo = pCombo + 1;
n = n - 1;
}
}
Assembly code:
.text
.global readCombo
readCombo:
oldEbp = 0
retAddr = oldEbp + 4
pCombo = retAddr+4
n = pCombo + 4
readChar = oldEbp - 4 # Place to store the input character
# Save stack pointer
pushl %ebp
movl %esp,%ebp
# Allocate space for readChar, initialize to easy to see value
pushl $999
# Find the address of pCombo and put in %eax
movl %ebp, %eax
addl $pCombo, %eax
# The start of the loop
loopStart:
# Get the address of readChar
movl %ebp, %edx
addl $readChar, %edx
# Save the address of pCombo (in %eax)
pushl %eax
# Read a character and check
movl $3, %eax
movl $0, %ebx
movl %edx, %ecx
movl $1, %edx
int $0x80
# Restore the address of pCombo from earlier
popl %eax
# Make sure the input character is above 0
cmpb $0, (%ecx)
jna checkConditional
# Make sure n is above zero
cmpb $0, n(%ebp)
jna checkConditional
# Move the character into a temp register
movb (%ecx), %bl
# Put the input character into where pCombo points to
movb %bl, (%eax)
# Find the address of n and put in %ebx
movl %ebp, %ebx
addl $n, %ebx
# Subtract 1 from n
subb $1, (%ebx)
# Add one to the address of pCombo (saved in register %eax)
addl $1, %eax
checkConditional:
# Make sure the input character is not 0 (null)
cmpb $0, (%ecx)
jna exitLoop
# Make sure the input character is greater than 10 (line feed)
cmpb $10, (%ecx)
jna exitLoop
# Go back to the start of the loop
jmp loopStart
# Break out of the loop
exitLoop:
# Pop the local variable readChar (housekeeping)
popl %ecx
movl %ebp,%esp
popl %ebp
ret