Есть несколько проблем с этим кодом, но вы на правильном пути.
1. Состояние петли
Вы используете это, чтобы выйти из цикла, когда ebx >= ecx
:
cmpl %ebx,%ecx
jg exit
Синтаксис довольно запутанный, но на самом деле это означает «выход, если ecx больше, чем ebx». Изменение на jng exit
устраняет эту проблему.
2. Аргументы в стеке
Вы ссылаетесь на аргументы с 8(%ebp,%ebx,4)
, но аргументы фактически начинаются с 12(%ebp)
. Вы правы в том, что вам следует начинать с индекса 1, поскольку аргумент с индексом 0 - это просто имя программы.
3. Аргументы - это всегда строки
Аргументы в стеке являются только указателями на строки. movl 12(%ebp),%eax
не будет вводить число из командной строки в eax
. Это только поместит адрес памяти в eax, который указывает на последовательность символов, которые составляют первый аргумент.
Чтобы получить число, представленное строкой «123», вам необходимо проанализировать его с помощью такой функции, как atoi . Atoi вернет 123 в eax
.
Вот как выглядит код, когда все исправлено. Я помещаю комментарий рядом с каждой измененной строкой.
.section .data
.section .text
.global _start
_start:
call adder
movl %eax,%ebx
movl $1,%eax
int $0x80
adder:
pushl %ebp
movl %esp,%ebp
movl $0,%eax #eax = return
movl $1,%ebx #ebx = index
movl 8(%ebp),%ecx #number of args
loop:
cmpl %ebx,%ecx
jng exit # quit if ecx is not greater than ebx
pushl %eax # save registers on stack
pushl %ecx # because they will be destroyed soon
pushl 12(%ebp,%ebx,4) # push next argument pointer on stack
call atoi # invoke atoi, this destroys registers eax,ecx,edx
add $4,%esp # restore stack pointer
mov %eax,%edx # atoi returns the value in eax, save that to edx
popl %ecx # restore ecx from stack
popl %eax # restore eax from stack
addl %edx,%eax # add parsed number to accumulator
incl %ebx
jmp loop
exit:
movl %ebp,%esp
popl %ebp
ret
И программа, кажется, теперь работает:
$ gcc -nostartfiles test.S -m32 && ./a.out 1 2 3 4 5 ; echo $?
15
Программа возвращает результат в виде значения выхода, что означает, что он не может считать больше 255 :)
Вероятно, было бы лучше позволить программе выводить результат на стандартный вывод, используя printf
.