← Zurück zum Blog
Code Snippets Low-Level #NASM #Primzahlen #x86

Prime-Checker in x86 ASM

An interactive x86 assembly example that checks whether entered numbers are prime.

Veröffentlicht am 22.01.2026

Prime Checker x86 ASM

This program checks whether an entered number is a prime number:

global _start
default rel

section .text
_start:
    ; Program entry point

    call    welcome                         ; Print welcome message

primeloop:
    push    rbp                             ; Save base pointer
    mov     rbp, rsp                        ; Set new base pointer
    sub     rsp, 16                         ; Reserve 16 bytes for local variables

    call    read                            ; Wait for user input

    ; Check if input is 'q' (quit)
    cmp     byte [usrinput], "q"            ; Compare first character to 'q'
    je      exit_0                          ; If 'q', exit program

    call    parse_input                     ; Parse decimal input into RAX

    ; Prime check logic:
    ; If n < 2 -> not prime
    ; If n == 2 -> prime
    ; If n is even -> not prime

    ; Check if n < 2, n == 2, or n is even
    cmp     rax, 2
    jl      printnoprime                    ; n < 2 (not prime)
    je      printprime                      ; n == 2 (prime)
    test    rax, 1                          ; Check whether n is odd
    jz      printnoprime                    ; n is even (not prime)

    ; Odd number prime check
    ; Algorithm:
    ;   i = 3
    ;   while i * i <= n (only odd i):
    ;       if n % i == 0 then not prime
    ;       else i += 2
    ;   if loop ends, n is prime

    mov     [rbp - 8], rax                  ; Persist n for repeated use
    mov     rcx, 3                          ; Start with smallest odd divisor
.1:
    mov     [rbp - 16], rcx                 ; Cache current divisor

    mov     rax, [rbp-8]                    ; Reload n for quotient comparison
    xor     rdx, rdx                        ; Zero high word before division
    div     rcx                             ; Divide n by i (quotient in RAX)
    cmp     rcx, rax                        ; Compare i to n / i threshold
    jg      printprime                      ; If i > n / i, no divisors remain

    xor     rdx, rdx                        ; Zero high word before division
    mov     rax, [rbp - 8]                  ; Reload n for modulus check
    mov     rcx, [rbp - 16]                 ; Restore i
    div     rcx                             ; Compute quotient and remainder
    cmp     rdx, 0                          ; Test remainder
    je      printnoprime                    ; If n % i == 0, not prime
    mov     rcx, [rbp - 16]                 ; Reload i for next iteration
    add     rcx, 2                          ; Move to next odd divisor
    jmp     .1                              ; Repeat loop

welcome:
    ; Prints the welcome message
    mov     rsi, welcomemsg                 ; Load welcome message address
    mov     rdx, welcomemsg_len             ; Load welcome message length
    call    print                           ; Print welcome message
    ret

read:
    ; Reads user input
    mov     rsi, prompt                     ; Load prompt message address
    mov     rdx, prompt_len                 ; Load prompt message length
    call    print                           ; Print prompt

    mov     rax, 0                          ; Syscall number: read
    xor     rdi, rdi                        ; File descriptor 0 (stdin)
    mov     rsi, usrinput                   ; Buffer for input
    mov     rdx, usrinput_len               ; Input buffer size
    syscall                                 ; Perform read syscall
    dec     rax                             ; Exclude newline from byte count
    mov     [net_char_len], rax             ; Persist input length (no newline)
    mov     byte [usrinput + rax], 0        ; Null-terminate input string
    ret

; Convert decimal string in usrinput -> integer in RAX
; net_char_len = number of chars without newline
; Destroys RCX, RDX, RSI
parse_input:
    xor     rax, rax                        ; Result accumulator
    mov     rcx, [net_char_len]             ; Loop count
    mov     rsi, usrinput                   ; Pointer to string
.convert_loop:
    test    rcx, rcx                        ; Stop when no characters remain
    jz      .done                           ; If zero, done

    movzx   rdx, byte [rsi]                 ; Load next ASCII digit
    sub     rdx, '0'                        ; Convert ASCII to digit (0..9)
    imul    rax, rax, 10                    ; Shift accumulated value by base 10
    add     rax, rdx                        ; Add digit to result

    inc     rsi                             ; Move to next char
    dec     rcx                             ; Decrement loop count
    jmp     .convert_loop                   ; Repeat loop
.done:
    ret


printnum:
    mov     rsi, usrinput                   ; Point RSI at input string
    mov     rdx, [net_char_len]             ; Load input string length
    call    print                           ; Print input string
    ret

printnoprime:
    ; Print: not a prime
    call    printnum                        ; Print input number
    mov     rsi, noprime                    ; Load 'not prime' message address
    mov     rdx, noprime_len                ; Load message length
    call    print                           ; Print message
    mov     rsp, rbp                        ; Restore stack pointer
    pop     rbp                             ; Restore base pointer
    jmp     primeloop                       ; Repeat loop


printprime:
    ; Print: is a prime
    call    printnum                        ; Print input number
    mov     rsi, isprime                    ; Load 'is prime' message address
    mov     rdx, isprime_len                ; Load message length
    call    print                           ; Print message
    mov     rsp, rbp                        ; Restore stack pointer
    pop     rbp                             ; Restore base pointer
    jmp     primeloop                       ; Repeat loop

print:
    mov     rax, 1                          ; Syscall number: write
    mov     rdi, 1                          ; File descriptor 1 (stdout)
    syscall                                 ; Perform write syscall
    ret

exit_0:
    xor     rdi, rdi                        ; Exit status 0
exit:
    mov     rax, 60                         ; Syscall number: exit
    syscall                                 ; Invoke exit

section .bss
    usrinput    resq 1                      ; Reserve memory for user input
    usrinput_len equ $ - usrinput           ; Length of input buffer

    net_char_len resq 1                     ; Actual length of user input

section .data
    welcomemsg  db "This program checks whether a number is a prime number.", 10, "To quit enter ", 0x22, "q", 0x22, ".", 10, 0
    welcomemsg_len equ $ - welcomemsg

    prompt      db 10, "Please enter a number: ", 0
    prompt_len  equ $ - prompt

    noprime     db " is not a prime number", 10, 0
    noprime_len equ $ - noprime

    isprime     db " is a prime number", 10, 0
    isprime_len equ $ - isprime