Машинный код x86-64, 7 байт
31 C0
01 C8
E2 FC
C3
Вышеуказанные байты определяют функцию, которая принимает один параметр n
и возвращает значение, содержащее сумму всех целых чисел от 1 до n
.
Он записывается в соглашение о вызовах Microsoft x64 , которое передает параметр в ECX
регистр. Возвращаемое значение сохраняется EAX
, как и все соглашения о вызовах x86 / x86-64.
Неуправляемая сборка мнемоники:
xor eax, eax ; zero out EAX
Next: add eax, ecx ; add ECX to EAX
loop Next ; decrement ECX by 1, and loop as long as ECX != 0
ret ; return, with result in EAX
Попробуйте онлайн!
(Вызов функции C там помечен атрибутом, который заставляет GCC вызывать его, используя соглашение о вызовах Microsoft, которое использует мой ассемблерный код. Если бы TIO предоставил MSVC, в этом не было бы необходимости.)
По необычным стандартам кода гольфа вы видите, что этот итеративный циклический подход предпочтительнее подходов, использующих более разумную математическую формулу ( n(n+1) / 2
), хотя он, очевидно, значительно менее эффективен с точки зрения скорости выполнения.
Используя теорию чисел, реализация потолочной системы все еще может быть побита одним байтом. Каждая из этих инструкций важна, но есть немного более короткая кодировка, в IMUL
которой EAX
неявно используется операнд-адресат (фактически, он использует EDX:EAX
, но мы можем просто игнорировать старшие 32 бита результата). Это только 2 байта для кодирования, по сравнению с 3.
LEA
также занимает три байта, но на самом деле нет никакого способа обойти это, потому что нам нужно увеличивать при сохранении исходного значения. Если бы мы сделали MOV
копию, то INC
у нас было бы 4 байта. (В x86-32, где INC
только 1 байт, мы будем с теми же 3 байтами, что и LEA
.)
Окончательное смещение вправо необходимо, чтобы разделить результат пополам, и оно, безусловно, более компактно (и более эффективно), чем умножение. Однако код должен действительно использоваться shr
вместо sar
, поскольку предполагается, что входное значение n
является целым числом без знака . (Конечно, это допущение является действительным в соответствии с правилами, но если вы знаете, что входные данные являются беззнаковыми, то вам не следует делать арифметическое смещение со знаком, поскольку старший бит, установленный в большом значении без знака, приведет к результату. быть неверным.)
8D 41 01 lea eax, [rcx+1]
F7 E9 imul ecx
D1 E8 shr eax, 1
C3 ret
Сейчас всего 8 байтов (спасибо Петру Кордесу). Тем не менее, 8> 7.