Skip to main content
added 308 characters in body
Source Link
Peter Cordes
  • 5.1k
  • 1
  • 24
  • 35

Same machine code does the same thing in 32-bit mode, and for 16-bit integers in 16-bit mode.

This is a function, callable with args n=RCX, k=ESI. 32-bit return value in EAX.

0xc = 12 bytes


Or 10 bytes if we didn't need to handle the n=0 special case, leaving out the jrcxz.

For standard factorial you'd use loop instead of sub/ja to save 2 bytes, but otherwise the exact same code.

This is a function, callable with args n=RCX, k=ESI. 32-bit return value in EAX.

0xc = 12 bytes

Same machine code does the same thing in 32-bit mode, and for 16-bit integers in 16-bit mode.

This is a function, callable with args n=RCX, k=ESI. 32-bit return value in EAX.

0xc = 12 bytes


Or 10 bytes if we didn't need to handle the n=0 special case, leaving out the jrcxz.

For standard factorial you'd use loop instead of sub/ja to save 2 bytes, but otherwise the exact same code.

Source Link
Peter Cordes
  • 5.1k
  • 1
  • 24
  • 35

x86-64 machine code, 12 bytes

This is a function, callable with args n=RCX, k=ESI. 32-bit return value in EAX.

Callable from C with the x86-64 System V calling convention with dummy args to get the real args into the right registers. uint32_t factk(int, uint32_t k, int, uint64_t n); I couldn't just use Windows x64 because 1-operand mul clobbers RDX, and we don't want REX prefixes to access R8/R9. n must not have any garbage in the high 32 bits so JRCXZ works, but other than that it's all 32-bit.

NASM listing (relative address, machine code, source)

 1 factk: 2 00000000 6A01 push 1 3 00000002 58 pop rax ; retval = 1 4 00000003 E306 jrcxz .n_zero ; if (n==0) return 5 .loop: ; do { 6 00000005 F7E1 mul ecx ; retval *= n (clobbering RDX) 7 00000007 29F1 sub ecx, esi ; n -= k 8 00000009 77FA ja .loop ; }while(sub didn't wrap or give zero) 9 .n_zero: 10 0000000B C3 ret 

0xc = 12 bytes


Test caller that passes argc as k, with n hard-coded.

align 16 global _start _start: mov esi, [rsp] ;main: mov ecx, 9 call factk mov esi, eax mov edx, eax lea rdi, [rel print_format] xor eax, eax extern printf call printf extern exit call exit section .rodata print_format: db `%#x\t%u\n` ```