# GNU Assembler (GAS) for Linux x64
sys_read = 0
sys_write = 1
sys_exit = 60
.globl main
.data
N: .long 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
.long 34, 72, 81, 100, 168, 216, 324, 330, 432, 648, 1000
.long 2520, 4212, 7350, 11155, 21600, 30240, 1000000
.long -1 # list end marker
.text
main:
cld
mov $N, %rsi
1:
lodsl
test %eax, %eax
js 2f # jump if EAX < 0
push %rsi
push %rax
call writei64 # output source number
mov $':', %al
call writechar
mov $' ', %al
call writechar
pop %rax
call MulOfDigits # calculate
call writei64 # output result
mov $10, %al
call writechar
pop %rsi
jmp 1b
2:
ret # return
################################################################################
# Find minimal natural number for which product of digits = EAX
# Return -1 if no such number
MulOfDigits:
cmp $10, %eax
jl .small # jump if N < 10
xor %ecx, %ecx # result = 0
mov $1, %r9d # multiplier = 1
mov $9, %r8d # divisor = 9..2
.nextdiv:
mov %eax, %r10d
xor %edx, %edx
div %r8d # N /= divisor, edx = N % divisor
test %edx, %edx
jnz .skip # skip if N % divisor <> 0
mov %r8d, %edx
imul %r9, %rdx # rdx = divisor * mul
add %rdx, %rcx # result += rdx (result += divisor * mul)
imul $10, %r9 # mul *= 10
jmp .nextdiv
.skip:
mov %r10d, %eax # restore N
dec %r8d # --divisor
cmp $1, %r8d
ja .nextdiv # repeat if divisor > 1
cmp $1, %eax
ja .noresult # no result if N > 1
mov %rcx, %rax # store result into rax
.exit:
ret
.small:
test %eax, %eax
jg .exit # return N if N > 0 (and < 10)
.noresult:
or $-1, %rax # return -1
jmp .exit
# Output signed RAX to console
writei64:
test %eax, %eax
jns 1f
mov %rax, %r8
mov $'-', %al
call writechar
mov %r8, %rax
neg %eax
1:
xor %r8, %r8
2:
call div10
push %rdx
inc %ebx
test %rax, %rax
jnz 2b
3:
pop %rax
add $'0', %al
call writechar
dec %ebx
jnz 3b
ret
# Write char AL to console
writechar:
mov %al, -1(%rsp)
mov $sys_write, %eax
mov $1, %edi # stdout file descriptor
lea -1(%rsp), %rsi # address
mov $1, %edx # count
syscall
ret
# RAX = RAX / 10, RDX = RAX % 10
div10:
mov %rax, %rcx
mov $0xCCCCCCCCCCCCCCCD, %rdx
mul %rdx
shr $3, %rdx
mov %rdx, %rax # RAX = quotient
lea (%rdx,%rdx,4), %rdx
shl $1, %rdx
sub %rcx, %rdx
neg %rdx # RDX = reminder
ret