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