- 1
[code]main[]__attribute__((section(".text"))) = {0xC0FFC031,0x7401FF83,0xFFE7F706,0xC3F5EBCF};[/code]
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+5
[code]main[]__attribute__((section(".text"))) = {0xC0FFC031,0x7401FF83,0xFFE7F706,0xC3F5EBCF};[/code]
Печатает факториал, от числа аргументов.
капча: t4ar
3.14159265 18.07.2020 23:35 # 0
gost 18.07.2020 23:36 # 0
gostinho 18.07.2020 23:37 # +1
> [code]
действительно
gost 18.07.2020 23:38 # 0
Какой анскилл )))
3.14159265 18.07.2020 23:38 # +1
Кстати компиляторы — говно.
Пишу gcc -Os /clang -Os. Подразумевается компактный код.
Они генерят
Или умножение
bormand 19.07.2020 02:25 # +1
TEH3OPHblu_nemyx 19.07.2020 00:44 # +2
Листинг:
Пояснение: в 32-битном режиме Кол Конвеншин «cdecl». Аргументы пушатся справа налево, поэтому argc лежит в [esp+4] (т. к. в [esp+0] лежит адрес разврата). Однако, CRT перед тем, как занести argc в стек, временно вносит его в eax. Этим можно воспользоваться (правда, можно обломаться в некоторых версиях компилятора).
Инструкция loop уменьшает ecx и проверяет ecx на ноль.
А ещё в 32-битном режиме есть однобайтовые инкременты и декременты.
3.14159265 19.07.2020 01:06 # 0
Вот здесь я удивился. Т.к. нет привычных esp.
Сам хотел написать в x32, т.к. верно подмечено что incи на байт короче.
И к тому же баш из кода разврата выводит только младшие 8 бит.
./hex 1 1 1 1 1
➤ 208
720 & 255 = 208
TEH3OPHblu_nemyx 19.07.2020 01:19 # +1
Написав mov ecx, eax, я положился на то, что код инициализации копирует в стек значение argc в последнюю очередь (argv и указатель на окружение копирует раньше), а в качестве промежуточного регистра использует eax (он не пушит, а использует мув, а поскольку мув из памяти в память нельзя, он использует регистр как временное хранилище).
gost 19.07.2020 00:52 # +2
x64, 11 бат, кто меньше?
TEH3OPHblu_nemyx 19.07.2020 01:11 # 0
Пробовал mov al, 1; cbw; cwde — получается длиннее.
stc; setc al; cbw; cwde — будет ещё длиннее.
Ещё вариант div eax — всего два байта для получения единицы в eax. Но если в eax изначально ноль, будет плохо (division by zero). Нужно смотреть код CRT, что там вносится в eax перед call _main.
3.14159265 19.07.2020 01:14 # 0
Чтобы как в прошлом топике N единичек передать и проверить N.
3.14159265 19.07.2020 01:32 # +2
Ну удивление код получился очень «ровный», двухбайтных.
Как в «RISC».
3.14159265 19.07.2020 01:39 # +1
Лишний багор )))
3.14159265 19.07.2020 02:20 # +1
Заодно поменял порядок итерации чтобы начинало проверять с 2, а не N-1.
gost 19.07.2020 04:03 # +2
Тестовый полигон:
bormand 19.07.2020 06:45 # +1
А тьфу, для деления же. Понаделают говноинструкций с неявными аргументами.
3.14159265 19.07.2020 10:11 # +1
Проверил эффективность унарного кодирования.
Где-то за секунду оно факторизует числа около миллиона.
Таким образом код вполне даже практичен.
Дальше баш упирается в длину списка: bash: ./prime: Argument list too long
3.14159265 19.07.2020 10:20 # +1
Так оно для 1 и 2 тоже правильно работает!
Заодно считает количество нетривиальных делителей числа. Круто.
3.14159265 19.07.2020 10:29 # +1
0 - простое
1 - квадрат простого
2 - произведение простых
Нечетное - квадрат числа.
3.14159265 19.07.2020 11:30 # +1
Можно использовать трёхбайтовую sete.
А если заменить 5-байтовую загрузку -2 на xor, то код будет считать хорошо известную в теории чисел «функцию делителей».
https://en.wikipedia.org/wiki/Divisor_function
TEH3OPHblu_nemyx 19.07.2020 11:38 # +2
Какой математик )))
gost 19.07.2020 11:56 # 0
gost 19.07.2020 11:55 # +1
«sete» три бата занимает, поэтому баты по сравнению с примитивным «jne» не экономятся. Багор (((
3.14159265 19.07.2020 12:28 # 0
Код будет короче на джва бата. Но тогда потеряется полезность функции делителей.
Впрочем нет. bsf в x64 тоже трёхбатная.
3.14159265 19.07.2020 12:41 # 0
3.14159265 19.07.2020 13:10 # +1
gost 19.07.2020 13:18 # 0
3.14159265 19.07.2020 13:23 # +1
xor ebx, ebx
mov ebx, edi
adc bl,bh
sbb bl,0
И заменив обратно джвухбатный sub eax,ebx на xchg.
Но тогда я не знаю где взять 8-битный регистр с нулём.
bh работает, т.к. число делителей даже на больших числах меньше 255.
И результат всегда влазит в bl.
XYPO3BO3 19.07.2020 20:57 # 0
Что я буду делать? ЫЫЫЫЫ!
Ы, ку, Ы, ку, Ы, ку, Ы!
gost 19.07.2020 21:02 # 0
gost 19.07.2020 01:52 # +2
Спасибо за идею! Только для «div eax» надо ещё edx очищать, иначе бо-бо.
x64, 10 бат!
3.14159265 19.07.2020 02:19 # 0
gost 19.07.2020 01:15 # +1
x64, 11 бат, другой подход.
gost 19.07.2020 02:03 # 0
gostinho 19.07.2020 09:55 # 0
Какой анскилл )))
На стеке слабо оставить?
TEH3OPHblu_nemyx 19.07.2020 11:16 # 0
TEH3OPHblu_nemyx 19.07.2020 11:20 # +1
mittorn 30.04.2021 14:33 # 0