aboutsummaryrefslogtreecommitdiffstats
path: root/04-Largest-Palindrome-Product/asm/palindrome.asm
blob: 03cd724a4d8a0a75c605e4a50143b9e7ebfe0484 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
; Find the largest palindrome made from the product of two 3-digit numbers.

extern printf
SECTION .data
flag:   db  "%d",10,0           ; "%d\n\0"

SECTION .text
    global main    
    global is_palindrome

is_palindrome:
; check if the product in rax is a palindrome
        
        push rax                ; save the value
        xor r14, r14            ; using this as a string length counter
.div:   xor rdx, rdx            ; clear operand for div
        div r12                 ; rdx:rax / 10
        add rdx, 0x30           ; digit is in remainder, add ascii 0
        push rdx
        inc r14
        cmp rax, 0
        jnz .div
        
; Cheating a bit here. Highest product of two 3 digit numbers will
; not exceed 6 digits. We assume only three comparisons need to made
; 5 digit numbers are excluded outright

        cmp r14, 6
        jne main.nexti          ; return
        mov rax, [rsp]
        mov rdx, [rbp-0x18]     ; at this point, original rbp, ret and rax are
        cmp rax, rdx            ; on the stack, so skip three qwords (64bits)
        jne main.nexti
        mov rax, [rsp+8]
        mov rdx, [rbp-0x20]
        cmp rax, rdx 
        jne main.nexti
        mov rax, [rsp+16]
        mov rdx, [rbp-0x28]
        cmp rax, rdx 
        jne main.nexti
        ; if you made it here, rax is a palindrome!
        mov rsp, rbp            ; reset stack back to the first variable
        sub rsp, 16             ; first 8 bytes is the return call
        pop rax
        ret

main:
        push rbp                ; set up stack
        mov rbp, rsp
        mov r11, 0x3E7          ; j=999
        mov r12, 0xA            ; for division testing later
        xor r13, r13            ; current max palindrome (0)
; check products for three digit numbers (starting with highest)
.loopj  mov rcx, 0x3E7          ; setup counter two (i=999)

.loopi  xor rdx, rdx            ; clear operand for mul
        mov rax, r11            ; operand for mul 
        mul rcx                 ; rdx:rax = rax * rcx (j * i)
                                ; hint this won't overflow
        call is_palindrome
        ; if you made it here, rax is a palindrome!
        cmp rax, r13            ; if rax is not bigger than the current max
        jl .nexti               ; next loop
        mov r13, rax            ; otherwise, update value 

.nexti: mov rsp, rbp            ; reset stack (if needed)
        loopnz .loopi           ; i = 0, decrement j and restart
        
        dec r11                 ; j--
        jnz .loopj

.print  mov rdi, flag           ; arg 1 (format)
        mov rsi, r13            ; arg 2
        mov rax, 0		; no xmm registers
        call printf wrt ..plt

        mov rsp, rbp            ; reset to the top of the stack
        pop rbp

        mov rax, 0
        ret