1. Си / Говнокод #13546

    +140

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    #include <stdio.h>
    
    int main()
    {
      printf("test\n");
      
      __asm volatile (".rept 10\n");
      printf("test\n");
      __asm volatile (".endr");
      
      return 0;
    }

    Еще немного поиздевался над GCC. Через ассемблерные вставки, точнее через вставку директивы .rept иногда можно повторить некоторый кусок кода несколько раз. Работает это далеко не всегда
    http://sourceware.org/binutils/docs/as/Rept.html
    Этот .rept по сути просто копипастит кусок кода

    Запостил: j123123, 04 Августа 2013

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

    • показать все, что скрыто__asm volatile (".rept 2\n");
      foo(1);
      __asm volatile (".endr");

      превратится в законное:
      push 1
      call foo
      push 1
      call foo

      или в распидарасиваемое:
      push 1
      call foo
      call foo

      при условии что функция foo stdcall конечно
      Ответить
      • показать все, что скрытоGCC не использует push для записи в стек. Там вот такая картина получается:
        .rept 10
        	movl	$.LC0, %edi
        	call	puts
        	.endr

        Кроме того, просматривая ассемблерные выхлопы GCC я в свое время обнаружил то, что он неоптимальным образом записывает в стек даннные, если они объявлены таким вот образом
        char a[] = {'s', 'o', 'm', 'e', ' ', 't', 'e', 'x', 't'}

        По поводу этого я даже в мейл лист GCC писал, http://gcc.1065356.n5.nabble.com/Ways-to-fill-the-stack-td912561.html
        Ответить
        • показать все, что скрыто> http://gcc.1065356.n5.nabble.com/Ways-to-fill-the-stack-td912561.html
          Ну в первом случае да, херня какая-то получилась с шестью movb. А во втором - все норм, т.к. пара mov'ов эффективней, чем пара push'ей.
          Ответить
          • показать все, что скрытоЯ там говорил про длины опкодов, если внимательно читать. С точки зрения скорости выполнения, может комплиятор и прав. Надо документацию на процессоры читнуть, или сделать бенчмарк
            As you can see, mov %r8,(%rsp) produse 4 bytes: 4c 89 04 24 and mov %rdi,0x8(%rsp) produces 5 bytes: 48 89 7c 24 08 push %r8 produces only 2 byte 41 50 and push %rax (or %rcx %rdx ...) produces one byte You can check other instruction length, for example movq %rax, (%rsp) etc.
            Ответить
            • показать все, что скрыто> длины опкодов
              А нет особого смысла слишком уменьшать длину опкодов. Декодер в проце, емнип, захлебывается на 6 командах на 16 байт. Так что уменьшение длины кода, имхо, имеет смысл разве что на оптимизации под минимальный размер (контроллеры и т.п.), но никак не на скорость (которая и происходит на -O2/-O3).
              Ответить
              • показать все, что скрытоЯ уже где-то приводил пруф, что INC, MOVSB, LOOP на старых Пентиумах летают по сравнению с предыдущими поколениями процессора, но невыносимо тормозят на современных процессорах. Так что сейчас для Интела выгоднее мелкие опкоды разбавлять длинными или вообще не использовать, а если критична длина, то сжимать экзешник UPX'ом.
                Ответить
          • показать все, что скрытопричем этот идиот продолжает городить херню из movb на O2 и O3
            Ответить
        • показать все, что скрытодействительно, через mov [esp+X],XXX аргументы заносит. Насчет записи в стек интересно,видимо gcc видя заветные " " радостно решает что там строчка и режет ее по 4 байта, а массив при его типе char почему то заносится поэлементно, а при 2-ух или 4-ех байтовых типах помещается в секцию данных. Занятно однако...
          Ответить

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