I'm trying to sum the ascii value's of a string from a loop. I think I'm missing something, but I keep either getting wrong values returned at the end of the program (ie. not matching the values i manually summed using the ascii table), or seg faults.
My program:
.data # .data section begins
name: .ascii "Json" # name is ASCII chars (.ascii or .byte)
len: .int 4 # name length is 4 chars, an integer
newline: .ascii "\n" # new line character
count: .int 0 # counter for loop (start at 0)
return: .int 0 # return code value
tmp: .int 0 # temp value
.text # text section starts
.global _start # main program entry
_start: # start instruction
again: # begin loop
mov $1, %edx # 1 byte at a time
mov $name, %ecx # mem addr
add count, %ecx # offset in string
#### Trouble area ####
# this seg faults
mov count(%ecx), %ebx
add %ebx, return
#### Trouble area ####
mov $1, %ebx # file descriptor 1 is computer display
mov $4, %eax # system call 4 is sys_write (output)
int $128 # interrupt 128 is entry to OS services
add $1, count # incr count
mov count, %eax # copy count to eax
cmp %eax, len # and compare values
jne again # if not equal, goto again
mov $newline, %ecx # mem addr
mov $1, %ebx # file desc 1
mov $4, %eax # sys call 4
int $128 # interrupt 128
mov $1, %eax # system call 1 is sys_exit
mov return, %ebx # status return
int $128 # interrupt 128
I think I'm missing something basic, but I understand this to be move the value in ecx
register offset by the value of count
(ie. loop iteration and therefore the array element), into register ebx
. Then add the value in ebx
to return
. Then at the endof the program, move the summed value that is in return
to register ebx
and then call the interrupt. During runtime this seg faults, but I'm unsure why.
I would expect it to not seg fault (obviously lol), and when calling ~]# echo $?
for it to print 410
(ie, 'J' + 's' + 'o' + 'n' or... 74 + 115 + 111 + 110).
UPDATE:------------>
I have updated the "trouble spot" to the following per advice from @Michael (if I understood correctly).
#### Trouble area ####
# this returns a garbage number, 154 instead of 410
mov count, %edi
mov name(%edi), %ebx
add %ebx, return
#### Trouble area ####
POSIX exit status codes are effectively an unsigned byte.
#include <stdio.h>
int main() {
printf("%d\n", (unsigned char)410);
return 410;
}
This will both print and return 154
, which is 410 % 256
.
Read the POSIX section here: http://en.wikipedia.org/wiki/Exit_status#POSIX
You can run your process in gdb and use i r
to print the register contents, or print return
.
You can convert your int into a string [1] and call the write
syscall [2] on stdout with a pointer to the resulting string (write(1, "string\n", len)
).
[1] integer to string: mod 10 to get rightmost digit, divide by 10 to remove the rightmost digit, repeat until n = 0, then reverse the string or do a call to sprintf()
, itoa()
, etc
[2] http://asm.sourceforge.net/articles/linasm.html#Syscalls