1. Assembler / Говнокод #11302

    +184

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    __declspec (naked) INT16U getWordOfCPUFlags(void)
    {
    	_asm
    	{
    		pushf;
    		xor eax, eax;
    		pop ax;
    		ret;
    	}
    }
    
    void setWordOfCPUFlags(const INT16U WordOfCPUFlag)
    {
    	_asm
    	{
    		push WordOfCPUFlag;
    		popf;
    	}
    }
    
    bool getCPUTraceFlag(void)
    {
    	return 0 != (getWordOfCPUFlags() & 0x100);
    }
    
    void setCPUTraceFlag(const bool CPUTraceFlag)
    {
    	const INT16U MaskOfTraceFlag=((INT16U)CPUTraceFlag)<<8;
    	//setWordOfCPUFlags( (getWordOfCPUFlags() and ~MaskOfTraceFlag) ^ MaskOfTraceFlag);
    	if(CPUTraceFlag)
    		setWordOfCPUFlags( getWordOfCPUFlags() | MaskOfTraceFlag);
    	else
    		setWordOfCPUFlags( getWordOfCPUFlags() & ~MaskOfTraceFlag);
    }

    Видимо автору кода строка 29 показалась слишком сложной.

    Запостил: HaskellGovno, 26 Июня 2012

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

    • > getWordOfCPUFlags() and ~MaskOfTraceFlag
      WHAT!?
      Ответить
      • #define and &&
        Ответить
        • Вообще-то, я так понимаю, должно быть:
          #define and &

          Только я боюсь, что после этого будет где-нибудь:
          & eax, ebx
          Ответить
          • Конечно. Не посмотрел, что установка флага, а не сравнение. "if(CPUTraceFlag)" чуть ниже отвлекло.
            Ответить
      • Может дельфин какой писал... Потому и закомментировал?
        Ответить
      • Я, кстати, пока суда не вставил - тоже этого не заметил. Тут and подсветился. Не знаю, что автор курил.
        Ответить
      • >WHAT!?

        2.5 Alternative tokens
        Ответить
        • Блин, вот уж не знал что этот богомерзкий and есть в моих плюсиках. Оно еще и компилируется :(

          P.S. Только это && а не &, & судя по ману доступен как bitand.
          Ответить
          • Недавно я их даже в дикой природе увидел:
            if (not procdata->config.solaris_mode)

            http://git.gnome.org/browse/gnome-system-monitor/tree/src/proctable.cpp
            Ответить
            • Гномы предали нас. Вся надежда на эльфов.
              Ответить
              • Это какой-то диверсант закоммитил, гномеры не любят C++
                Ответить
    • Кстати, я в этом коде видел много:
      xor eax, eax;
      mov ax, ...
      Толк от этой первой строки вообще есть какой?
      Ответить
      • Есть. Должно оптимизировать исполнение команд процессором.

        xor eax, eax устранит зависимость eax от состояния, в котором он находился в предыдущих командах. Поэтому процессор сможет выполнить эти 2 команды, и ,возможно, следующую, не дожидаясь выполнения предыдущих команд, юзавших eax.
        Ответить
        • >xor eax, eax устранит зависимость eax от состояния
          mov eax, 0;
          mov ax, ...
          А так устраняется?
          Ответить
          • По идее да, но это 5 байт. xor короче.
            UPD: а зачем? Тогда уж лучше один mov eax, ... оставить.
            Ответить
        • >xor eax, eax устранит зависимость eax от состояния
          Откуда зависимость появляется в mov ax, ... ? После mov ax, ... старшая часть eax вроде же все равно обнуляется?
          Ответить
          • Вот в том и прикол, что не обнуляется.
            Ответить
          • Пруф:
            $ cat 1.c
            #include <stdio.h>
            int result;
            int main() {
                asm("movl $0xDEADBEEF, %eax");
                asm("movw $0x1234, %ax");
                asm("movl %eax, result");
                printf("%08X\n", result);
                return 0;
            }
            $ gcc -Wall -Wextra 1.c
            $ ./a.out 
            DEAD1234
            Ответить
          • Для этой цели, ЕМНИП, есть милое семейство команд movz*. Z, кажется, означает "занулить неиспользуемое".
            Ответить
            • Z в movzx вроде как zero расширение. А еще есть знакововое расширение movsx. Вот не помню, почему тогда используют трюк с xor перед mov. Видимо для совместимости с древними процами...
              Ответить
    • Кстати, короче, чем от автора написать можно?
      void setCPUTraceFlag(const bool CPUTraceFlag)
      {
      	const INT16U MaskOfTraceFlag=((INT16U)CPUTraceFlag)<<8;
      	setWordOfCPUFlags( (getWordOfCPUFlags() & ~MaskOfTraceFlag) ^ MaskOfTraceFlag);	
      }
      Ответить
      • > const bool
        Фу.

        Походу нет. Смотри:
        Если CPUTraceFlag == 0, то получаем set(get() & ~0) ^ 0 - т.е. ничего не изменится.
        Если же CPUTraceFlag == 1, то получаем set(get() & ~(1 << 8)) ^ (1 << 8), что установит бит.
        Ответить
      • Как-то так:
        void setCPUTraceFlag(const bool CPUTraceFlag)
        {
        	const INT16U MaskOfTraceFlag = 1 << 8;
        	if (CPUTraceFlag)
        		setWordOfCPUFlags(getWordOfCPUFlags() | MaskOfTraceFlag);
        	else
        		setWordOfCPUFlags(getWordOfCPUFlags() & ~MaskOfTraceFlag);
        }
        Ответить
    • alternative primary | alternative primary | alternative primary
      --------------------+---------------------+--------------------
         <%          {    |    and         &&   |    and_eq      &= 
         %>          }    |    bitor       |    |    or_eq       |= 
         <:          [    |    or          ||   |    xor_eq      ^=
         :>          ]    |    xor         ^    |    not         !
         %:          #    |    compl       ~    |    not_eq      !=
         %:%:        ##   |    bitand      &    |

      Дельфины какие-то приняли это в стандарт. :(
      Ответить
    • Вообще, когда я увидел этот код первый раз, то первая же мысль была: Автор кода считает AssemberGovno, боится его как огня и поэтому пишет достаточно низкоуровневые конструкции, удобно и кратко выражающиеся на ассемблере, на языке высокого уровня. Хорошо, что хоть не в ООП оформил это...
      Ответить
      • На самом деле вынос только необходимого минимума в ассемблерные функции, и реализация более высокоуровневого функционала уже на С имеет смысл.

        Но т.к. я не думаю, что автор кода будет менять какие-то биты кроме трейс флага, то вполне можно было сделать что-то типа
        void setTraceFlag(bool flag) {
            if (flag) {
                _asm {
                    pushf
                    or word ptr [esp], 0x0100
                    popf
                }
            } else {
                _asm {
                    pushf
                    and word ptr [esp], 0xFEFF
                    popf
                }
            }
        }
        Ответить
        • void setTraceFlag(bool flag) 
          {
              static const unsigned TraceFlagMask=0x100;
              __asm pushf;
              if (flag)
                  __asm or word ptr [esp], TraceFlagMask;
              else
                  __asm and word ptr [esp], ~TraceFlagMask;
              __asm popf;
          }
          Примерно так можно.
          Ответить
          • Ну, поскольку переменных между pushf и popf не объявлено - то можно.
            Ответить
            • А мне таки кажется, это достойно отдельного говнокода.
              Ответить
              • Кстати надо бы покопать - нет ли intrinsic'ов для pushf и popf в библиотеках того компилятора (MSVC?).
                Ответить
              • Вот. Нашел вот пару интринсиков - __readeflags() и __writeeflags().
                http://msdn.microsoft.com/en-us/library/aa983406(v=vs.80).aspx
                http://msdn.microsoft.com/en-US/library/aa983392(v=vs.80)
                void setCPUTraceFlag(bool flag)
                {
                    unsigned int mask = 1 << 8;
                    if (flag)
                        __writeeflags(__readeflags() | mask);
                    else
                        __writeeflags(__readeflags() & ~mask);
                }

                И никакого ассемблера ;)
                Ответить
    • - Руслан, у меня проблемы. Нас, похоже, нашли.
      Ответить

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