1. Pascal / Говнокод #3143

    +102

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    // тут обычный паскалевский код...
    if x > y then asm // если икс больше игрека
      mov eax, x  // то меняем их значения местами
      mov edx, y
      mov x, edx
      mov y, eax
    end;

    Как поменять значения двух целочисленных переменных, не заводя третью? Года 3 назад я делал примерно так.

    Запостил: TarasB, 01 Мая 2010

    Комментарии (83) RSS

    • А как ты делаешь сейчас?
      Ответить
      • Завожу 3ю переменную.
        Ответить
        • void swap(int& x, int& y) {
          x += y;
          y = x - y;
          x -= y;
          }
          Ответить
          • И обламываемся, если обе ссылки указывают на одну и ту же переменную. Знаю я про это извращение, и про ксоры тоже, но, во-первых, это извращение, а во-вторых, заточено под конкретный тип.
            Ответить
            • Я специально для каждого типа перегружаю +, - и xor.
              Ответить
          • integer overfull
            Ответить
          • Не.
            xor
            Ответить
          • Я, конечно, не знаю delphi, но, IMHO, правильно было бы использовать "xchg", если уж имеется ассмовая вставка.
            Ответить
            • Когда мне нужно было обменять две переменные и было не лениво делать вставку, я писал именно с xchg. Быстро, хорошо, удобно.
              Хотя, на деле, ересь ещё та.
              Ответить
              • xchg - медленее обмена через регистры.
                Ответить
                • Простите, я наверное опять не очень понимаю некоторых местных guest-ов. А xchg не с регистрами работает?

                  Провёл наглядный эксперимент. В цикле 100000000 раз выполнил по 32 раза раза обмен значениями.
                  С помощью xchg это выполнялось real 0m7.318s,
                  А с помощью тройного xor это выполнялось real 0m11.239s.
                  Ответить
            • 2xaionaro
              я минуснул, хотя хотел +1, сори
              если asm - то xchg, а в SSE есть еще и shuffle
              если delphi/pascal - то xor
              Ответить
              • Да, из-за непривычного порядка "+" и "-" на этом ресурсе, я тоже тут иногда ошибаюсь. Особенно если сразу после opennet.ru сюда зайти :)
                Ответить
          • О да! Здесь С++! Наконец-то! :)
            хотя нет проблем и на Паскале:
            begin
            inc(x,y);
            y:=x-y;
            dec(x,y);
            end;
            Ответить
    • дебилизм, экономить 4 байта в стеке

      вроде микроконтроллеры на дельфи не программируют...
      Ответить
      • Тот же С++ сделает, даже с введением третей переменной примерно так:
        mov eax, x
        mov edx, y
        mov x, edx
        mov y, eax
        Не в языке дело, конечно, а в хороших оптимизаторах.
        Ответить
        • Вон отсюдово ГдеЗдесьСиПлюсПлюсовец!!!!!!111111
          Надоел уже со своим С++ - то, С++ - это...
          Ответить
        • показать все, что скрытоDelphi - самый класный язык программирования и уж точно круче С++, с их долбанутыми программистами, ищущими везде С++. Им, видете ли, его не хватает...
          Ответить
        • >Тот же С++ сделает, даже с введением третей переменной
          )) интересно где здесь третья переменная
          Ответить
          • Что-нибудь про оптимизатор слышал? Он старается располагать переменные в регистрах. Это типичный пример. Зачем-что-то класть в стек, если это поместится в регистрах.
            Ответить
          • Если ты на дельфи программируешь, то тот честно заведёт дополнительную переменную. На регистры ему плювать.
            Ответить
      • С каких пор экономия (при прочих равных) считается дебилизмом?
        Другое дело, что даже дельфовый компилятор соптимизирует обмен с третьей переменной.
        Ответить
        • экономия как идея не дебилизм

          но экономия 4 байтов при стеке в ~1 миллион байтов (в Win по дефолту, а можно увеличить) - это дебилизм.

          Есть такое правило - не оптимизируй, пока не приспичит. А Дельфи вроде бы не функциональный язык, чтобы половину данных в стеке хранить (через рекурсии всякие). Если бы этим занимался оптимизацтор Хаскеля - то нет проблем.
          Ответить
          • Я к тому, что правильнее так сказать: извращаться ради экономии, которая и так будет - дебилизм.

            На самом деле это я так делал в ТП, вместо eax был ax, естественно. И там экономить
            приходилось на всём.
            Ответить
            • Мне одному показалось это сделано ради скорости? Как я понимаю операций обмена переменных местами много, сортировка или еще что. Через стек дольше чем через регистры если уж на то пошло)
              Ответить
          • А если к приложению (в частности к веб) одновоременно подключены несколько тысяч чеолвек, тогда не думать о оптимизации не логично.
            Ответить
      • было бы интересно посмотреть на x86-совместимый контроллер
        Ответить
    • показать все, что скрытоОсторожно! Кто проминусует этот коммент - тот хуй. Берегитесь. Не становитесь хуями.
      Ответить
    • Ну вот! Профилактическая неделя закончилась! Может сделать проф месяц?
      Ответить
    • показать все, что скрытопиздуйте в школу, нехера в камментах срать
      Ответить
    • Я бы убил за такой код, компилятор не будет проверять eax/edx перед тем, как их использовать дальше в программе, программа навернётся через пару шагов.

      1. push eax
      2. mov eax, x
      3. mov x,y
      4. mov y,eax
      5. pop eax
      6. ?????
      7. PROFIT
      Ответить
      • Не согласен, вот что говорит справка Delphi по этому поводу:
        An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers, but can freely modify the EAX, ECX, and EDX registers.
        Да и п. 3 невозможен, т.к. в x86 нет пересылок память-память, по-моему.
        Ответить
      • тебя бы тоже повесили
        Ответить
      • mov x,y
        100% не прокатит нельзя память-память можно регистр-память или регистр-регистр
        Ответить
    • > 3. mov x,y

      Так можно что ли?
      Ответить
      • > 3. mov x,y
        Ёбаный стыд. Конечно же нет. Я пошёл убивать себя
        Ответить
      • Мне так никто внятно и не объяснил, чем плох xchg.
        Ответить
        • Он медленее на современных CPU.
          Ответить
          • Чем что?

            На моём eeepc900, как показывает опыт, xchg работает быстрее, чем тройной xor.
            Ответить
        • (некрофилия):
          - тем, что xchg придётся использовать так:
          mov ax, x
          mov bx, y
          xchg ax, bx
          mov x, ax
          mov y, bx
          (xchg работает только с регистрами, а тебе нужно сохранять переменные в памяти)
          Ответить
          • > xchg работает только с регистрами
            Не совсем верно. Кроме всем известной формы с опкодом 90H-97H (xchg ax, reg, где 90H=xchg ax, ax=NOP — частный случай), есть ещё
            86H — xchg r/m 8bit, reg 8bit
            и 87H — xchg r/m, reg (16bit либо 32bit [либо даже 64bit на x86_64]).
            Здесь r/m — либо регистр, либо ссылка на память, то есть в точности, как у инструкции mov.
            Поэтому
            mov ax, y
            xchg x, ax
            mov y, ax

            Операции память-память, увы, не предусмотрено, так что один регистр придётся потратить.
            Альтернативный вариант:
            push y
            push x
            pop y
            pop x

            Ни одного регистра не занято, зато занят стек.
            Ответить
    • Не заводя третью? :)
      а что 2 регистра используешь, это вообще не считается? :))) Ты тут 2 переменные заводишь вместо одной!
      Да ещё и не заботишься о сохранении регистров
      Ответить
      • Регистр - это не переменная. Не путайте.
        Ответить
        • С другой стороны, хоть я сейчас и скажу и так почти всем очевидную вещь.., но в любом случае, высокоуровневая переменная вынуждена размещаться либо в ОЗУ, либо в регистрах, поэтому будет либо использовать много регистров, либо операция будет очень медленной. :)
          Ответить
        • почему? регистр переменная!
          Ответить
    • Во как нодо:
      x:=x xor y;
      y:=y xor x;
      x:=x xor y;
      Ответить
    • в питоне можно просто сделать так:
      a, b = b, a
      Ответить

    Добавить комментарий