Skip to main content
4 of 5
added 1522 characters in body
qwr
  • 12.3k
  • 6
  • 48
  • 80

#x86, 41 bytes

Mostly straightforward implementation of the formula with input in ecx and output on the stack.

The interesting thing is that I used a cubing function, but since call label is 5 bytes, I store the label's address and use the 2 byte call reg. Also, since I'm pushing values in my function, I use a jmp instead of ret. It's very possible that being clever with a loop and the stack can avoid calling entirely.

I did not do any fancy tricks with cubing, like using (k+1)^3 = k^3 + 3k^2 + 3k + 1.

Edit: Fix byte count using not instead of neg/dec.

.section .text
.globl main

main:
        mov     $10, %ecx   # n = 10

start:
        lea     (cube),%edi # save function pointer
        call    *%edi       # output n^3
        
        sub     %ecx, %eax  # n^3 - n
        xor     %edx, %edx
        push    $6
        pop     %ebx        # const 6        
        idiv    %ebx        # k = (n^3 - n)/6
        mov     %eax, %ecx  # save k
        
        call    *%edi       # output k^3
        push    %eax        # output k^3
        
        not     %ecx        # -k-1        
        call    *%edi       # output (-k-1)^3
      
        inc     %ecx        
        inc     %ecx        # -k+1
        call    *%edi       # output (-k+1)^3

        ret

cube:                       # eax = ecx^3
        pop     %esi 
        mov     %ecx, %eax
        imul    %ecx
        imul    %ecx

        push    %eax        # output cube
        jmp     *%esi       # ret

Objdump:

00000005 <start>:
   5:   8d 3d 24 00 00 00       lea    0x24,%edi
   b:   ff d7                   call   *%edi
   d:   29 c8                   sub    %ecx,%eax
   f:   31 d2                   xor    %edx,%edx
  11:   6a 06                   push   $0x6
  13:   5b                      pop    %ebx
  14:   f7 fb                   idiv   %ebx
  16:   89 c1                   mov    %eax,%ecx
  18:   ff d7                   call   *%edi
  1a:   50                      push   %eax
  1b:   f7 d1                   not    %ecx
  1d:   ff d7                   call   *%edi
  1f:   41                      inc    %ecx
  20:   41                      inc    %ecx
  21:   ff d7                   call   *%edi
  23:   c3                      ret    

00000024 <cube>:
  24:   5e                      pop    %esi
  25:   89 c8                   mov    %ecx,%eax
  27:   f7 e9                   imul   %ecx
  29:   f7 e9                   imul   %ecx
  2b:   50                      push   %eax
  2c:   ff e6                   jmp    *%esi

Here is my testing version that does all the cubing at the end. After the values are pushed on the stack, the cube loop overwrites stack values. It's currently 42 bytes but there should be some improvements somewhere.

.section .text
.globl main

main:
        mov     $10, %ecx       # n = 10

start:
        push    %ecx            # output n
        
        mov     %ecx, %eax
        imul    %ecx
        imul    %ecx
        sub     %ecx, %eax      # n^3 - n
        xor     %edx, %edx
        push    $6
        pop     %ecx            # const 6        
        idiv    %ecx            # k = (n^3 - n)/6
        
        push    %eax            # output k
        push    %eax            # output k

        not     %eax            # -k-1        
        push    %eax            # output -k-1
      
        inc     %eax            
        inc     %eax            # -k+1
        push    %eax            # output -k+1

        dec     %ecx            # count = 5
        add     $20, %esp
cube:           
        mov     -4(%esp),%ebx   # load num from stack
        mov     %ebx, %eax
        imul    %ebx
        imul    %ebx            # cube 
        push    %eax            # output cube
        loop    cube            # --count; while (count)

        ret
                
qwr
  • 12.3k
  • 6
  • 48
  • 80