2015-05-08 5 views
2

Я пытаюсь связать c-код с asm. Но он работает неправильно, и я не могу найти проблему.Почему этот код asm не удваивает значение указательных точек

program.c

#include<stdio.h> 
int *asm_multi(int *ptr); 

int main() 
{ 
    int i=10; 
    int *p=&i; 
    asm_multi(p); 
    printf("%d\n",*p); 
    return 0; 
} 

code.asm

.section .text 
.global asm_multi 
.type asm_multi,@function 
asm_multi: 
    pushl %ebp 
    movl %esp,%ebp 
    movl 8(%ebp),%eax 
    movl %eax,%edx 
    leal (%edx,%edx,1),%edx 
    movl %edx,%eax 
    movl %ebp,%esp 
    popl %ebp 
    ret 

Я создаю конечный исполняемый файл по

as code.asm -o code.o 
gcc program.c code.o -o output 
./output 

Вывод, который он печатает, составляет: 10, в то время как я ожидаю: 20

В чем проблема с кодом? Не учитывайте эффективность программы. Я только что начал программирование asm.

Я создал над кодом после чтения из более сложного примера, хранящегося в this link. Это прекрасно работает.

+1

Unrelated, если вы только начали ассемблера программирования и знать C, тратить время заливки на * простые * функции, посланные через компилятор C с ASM-поколения включен ('-S') при различных вкусы оптимизации (в том числе нет) могут быть * очень * информативными, и я настоятельно рекомендую его. Эта функция была бы * превосходным * кандидатом для этой техники. – WhozCraig

+0

@WhozCraig: Это действительно полезно :) – InQusitive

ответ

4

Вы должны научиться использовать отладчик как можно скорее. Это не только помогает вам находить ошибки, но также позволяет точно видеть, что процессор делает в каждой инструкции, и вы можете сравнить это с вашими намерениями.

Также прокомментируйте свой код, особенно при обращении за помощью, чтобы мы могли рассказать вам, где инструкции не соответствуют вашим намерениям, если вы не смогли сделать это самостоятельно.

Давайте комментировать свой код, то:

asm_multi: 
    pushl %ebp 
    movl %esp,%ebp 
    movl 8(%ebp),%eax  # fetch first argument, that is p into eax 
    movl %eax,%edx   # edx = p too 
    leal (%edx,%edx,1),%edx # edx = eax + edx = 2 * p 
    movl %edx,%eax   # eax = edx = 2 * p 
    movl %ebp,%esp 
    popl %ebp 
    ret 

Как вы можете видеть, есть две проблемы:

  1. Вы удваивая указатель не значение, которое указывает на
  2. Вы не записывая его обратно в память, просто возвращая его в eax, который затем игнорируется кодом C

Возможное исправление:

asm_multi: 
    pushl %ebp 
    movl %esp,%ebp 
    movl 8(%ebp),%eax  # fetch p 
    shll $1, (%eax)   # double *p by shifting 1 bit to the left 
# alternatively 
# movl (%eax), %edx  # fetch *p 
# addl %edx, (%eax)  # add *p to *p, doubling it 
    movl %ebp,%esp 
    popl %ebp 
    ret 
+0

сейчас, это выглядит так просто :) – InQusitive