Skip to content

Instantly share code, notes, and snippets.

@armut
Last active March 15, 2017 21:24
Show Gist options
  • Save armut/9ec700b43e9890e401b4ccd1facf4415 to your computer and use it in GitHub Desktop.
Save armut/9ec700b43e9890e401b4ccd1facf4415 to your computer and use it in GitHub Desktop.
Kaprekar number finder in (linux) assembly.
section .text
global _start
_start:
MOV CX, 999 ; The program will find first 1000 kaprekar numbers starting from 999.
MAIN: MOV DX, 0 ; Empty the DX at start just for safety.
MOV AX, CX ; Get the current number to AX.
MOV BX, 10 ; Load 10 to BX to use in divisions.
COUNTER: DIV BL ; Perform the division.
MOV AH, 0 ; Empty AH for the next time.
INC DX ; Count the digit.
CMP AL, 0 ; Check if the division yielded a zero which means that we must stop dividing it by 10.
JE ISKAPR ; So, we got the digit count. All set to go.
JMP COUNTER ; Else, continue dividing and counting.
ISKAPR: MOV AX, 10 ; Load 10 to AX in order it to exponentiate.
PUSH CX ; Backup the original number which we are testing if it is Kaprekar or not.
SUB DX, 1 ; Decrease digit count by 1. (For loop to exponentiate AX truly. Otherwise it will yield one unnecessary 0.)
MOV CX, DX ; Set counter to the digit count.
CMP CX, 0 ; Check if the digit count 0 or not.
JE CONT ; If it is, then this number is one-digit. No need to the loop. 10 is enough.
POW: MUL BX ; Perform AX * BX. (BX is 10, remember.)
LOOP POW ; Loop digit count times.
; At the end of this loop, we have got 10^DX in the register AX.
CONT: POP CX ; Restore CX to its original value. (This is the number which we are looking for its Kaprekar-ity.
PUSH AX ; Backup AX which we evaluated in the POW loop. (If the branch was taken at JE CONT line, AX would be 10.)
MOV AX, CX ; Load CX to AX. In order to take its square.
MUL AX ; Now perform AX * AX. The result is stored in (DX AX) which is equal to AX^2.
POP BX ; Pop the once restored number. (Which was the result of the POW loop or 10 without the loop.)
DIV BX ; Perform AX / BX. Which will yield a result in modulus in DX and divident in AX which we need to sum.
ADD AX, DX ; Sum them up into AX.
SUB AX, CX ; Now, the most breathtaking part. Compare the sum with the original number by subtracting them.
JZ KAPR ; If the result is 0, which means AX = CX, this number is a Kaprekar number. Jump to Kaprekar.
LOOP MAIN ; Else, it is not. Start over again with the next number.
KAPR: PUSH CX ; Store the Kaprekar number in the stack.
LOOP MAIN ; Start over again with the next number.
MOV AX, 1 ; 'exit' system call.
MOV BX, 0 ; Return 0.
INT 80H ; Call the kernel.
OBJS = kaprekar.s
ASM = nasm
FLAGS = -f elf -g
OBJ_NAME = kaprekar.o
EXE_NAME = kaprekar
LINK = ld -m elf_i386 -o $(EXE_NAME) $(OBJ_NAME)
all:
$(ASM) $(FLAGS) $(OBJS)
link:
$(LINK)
clean:
rm $(OBJ_NAME)
rm $(EXE_NAME)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment