Я пытаюсь ознакомиться со сборкой x86, используя встроенный ассемблер GCC. Я пытаюсь добавить два числа (a
и b
) и сохранить результат в c
. У меня есть четыре слегка отличающиеся попытки, три из которых работают; последнее не дает ожидаемого результата.
Первые два примера используют промежуточный регистр, и оба работают нормально. Третий и четвертый примеры пытаются добавить два значения напрямую без промежуточного регистра, но результаты варьируются в зависимости от уровня оптимизации и порядка, в котором я добавляю входные значения. Что я не так делаю?
Окружающая среда:
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Сначала переменные объявляются следующим образом:
int a = 4;
int b = 7;
int c;
Пример 1:
asm(" movl %1,%%eax;"
" addl %2,%%eax;"
" movl %%eax,%0;"
: "=r" (c)
: "r" (a), "r" (b)
: "%eax"
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output: a=4, b=7, c=11
Пример 2:
asm(" movl %2,%%eax;"
" addl %1,%%eax;"
" movl %%eax,%0;"
: "=r" (c)
: "r" (a), "r" (b)
: "%eax"
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output: a=4, b=7, c=11
Пример 3:
asm(" movl %2,%0;"
" addl %1,%0;"
: "=r" (c)
: "r" (a), "r" (b)
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output with -O0: a=4, b=7, c=11
// output with -O3: a=4, b=7, c=14
Пример 4:
// this one appears to calculate a+a instead of a+b
asm(" movl %1,%0;"
" addl %2,%0;"
: "=r" (c)
: "r" (a), "r" (b)
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output with -O0: a=4, b=7, c=8
// output with -O3: a=4, b=7, c=11
решено. ответ Мэтью Слэттери правильный. Раньше он пытался повторно использовать eax
для b
и c
:
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %eax
addl %eax, %eax
С предложенным Мэтью исправлением теперь он использует ecx
для удержания c
отдельно.
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %ecx
addl %eax, %ecx