2014-09-14 4 views
-1

Я читал о замене содержимого переменных без использования временной переменной и, кроме знаменитого алгоритма xor, я узнал о инструкции XCHG из сборки на x86. Поэтому я написал этот код:Обмен значениями с использованием регистров

void swap(int *left, int *right){ 
__asm__ __volatile__(
     "movl %0, %%eax;" 
     "movl %1, %%ebx;" 
     : 
     : "r" (*left), "r" (*right) 
    ); 
__asm__ __volatile__(
     "xchg %eax, %ebx;" 
      ); 
__asm__ __volatile__(
     "movl %%eax, %0;" 
     "movl %%ebx, %1;" 
     : "=r" (*left), "=r" (*right) 
    );} 

Он действительно работает, но потом я понял, что инструкция XCHG вообще не нужна.

void swap(int *left, int *right){ 
__asm__ __volatile__(
     "movl %0, %%eax;" 
     "movl %1, %%ebx;" 
     : 
     : "r" (*left), "r" (*right) 
    ); 
__asm__ __volatile__(
     "movl %%ebx, %0;" 
     "movl %%eax, %1;" 
     : "=r" (*left), "=r" (*right) 
    );} 

Вторая функция тоже работает, но никто, кажется, уже замена переменных с использованием регистров, так как этот код считается неправильным и в действительности это на самом деле не работает должным образом? Я что-то упускаю?

Я понимаю, что это будет работать только для x86, но поскольку большинство людей имеют процессор intel x86, может ли этот код использоваться в любом реальном программировании? Я понимаю, что это, вероятно, не будет быстрее, чем обычный обмен с временной переменной, но я прошу с теоретической точки зрения. Если во время теста или собеседования кто-то просит меня написать функцию в C для обмена значениями для машины x86 без использования временной переменной, будет ли этот код действителен или это будет полный хрен? Спасибо вам.

+0

Это - как вы сказали - дерьмо. Вы эффективно используете _two_ temps: регистры. Если собеседник задает вам этот вопрос, я убегу от этой компании. – Gene

+1

Вы должны больше заботиться о написании чистого и обслуживаемого кода. Пусть компилятор выполнит свою работу, и если производительность _does_ станет профилем проблемы и оптимизируется как _necessary_. Если бы кто-то представил этот тип кода мне в интервью, он был бы направлен к ближайшему выходу. –

+0

Ну, регистры являются временными переменными. –

ответ

5

Действительно, да. По моим критериям вы не можете взять напрокат.

Почему? Стоимость.

std :: swap выполнит эту работу отлично и, вероятно, достаточно быстро. Ваш код будет иметь более высокую стоимость обслуживания.

Конечно, времена для отказа от ассемблера по соображениям производительности.
Это не один из них.

+0

Ну, я думаю, ты прав :) Спасибо за ваш ответ. – azertyuiopml

+0

Добро пожаловать. Я одобряю ваш интерес. Понимание сборки упрощает визуализацию поведения машины. Это заставляет вас понять и понять, почему C и C++ - правильные ответы на большинство проблем. Продолжай учиться. – EvilTeach

0

Во-первых, ваш встроенный ассемблер нарушается во многих отношениях:

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

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

Кроме того, встроенная сборка может быть оптимизирована с очень тщательным взломом, однако она влияет на компилятор таким образом, что это ухудшает способность оптимизатора (распределение регистров, переупорядочение и т. Д.), Что обычно приводит к общему снижению производительности. Я не против встроенной сборки (или встроенного компилятора), но требует очень тщательной обработки, которая делает ее не оправданной в большинстве случаев.

Смежные вопросы