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` ```