простой сумматор не работает - PullRequest
1 голос
/ 25 марта 2011

Я сделал простой аргумент сумматора со сборкой, но он не работает

всегда возвращается 0

    .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
    jg exit
    addl 8(%ebp,%ebx,4),%eax
    incl %ebx
    jmp loop
exit:
    movl %ebp,%esp
    popl %ebp
    ret

1 Ответ

2 голосов
/ 25 марта 2011

Есть несколько проблем с этим кодом, но вы на правильном пути.

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...