0

I'm attempting to write a small program using the x86 Intel Assembly Language (NASM) capable of taking in a number (hard-coded in the program text file) and checking whether that number is prime or not, by beginning with a divisor of 2 and incrementing if needed along the way using a while loop. Depending on if the number is prime or not, a specific message will display and the the value of 0 will be written into the memory location 'answer' if the number is not prime. Otherwise, the initial value of '1' will be left unmodified, thus indicating that the number is prime.

I believe I have incremented the value of the divisor 'bl' correctly, but using jl loopy to make the program go through the loop once again seems to fail because it produces incorrect results e.g. 5 is prime, 10 is not prime, but 15 is prime.

This is my code:

section .data
    primeMsg db "This is a prime number!", 0xa
    lenPrimeMsg equ $-primeMsg
    noPrimeMsg db "This is not a prime number.", 0xa
    lenNoPrimeMsg equ $-noPrimeMsg

number db 5
answer db 1         ;1 means number is prime, 0 means number is not prime
section .bss

section .text
    global start

start:  
    mov esi, number     ;get the offset of number into esi
   keith: mov eax, 0        ;clear the entire eax register
    mov al, [esi]       ;get the number from memory into al 
    mov dl, al      ;put it inside dl as well
    mov bl, 2       ;bl holds each divisor starting from 2
loopy: div bl           ;ax/bl with quot in al and rem in ah
   and ax, 1111111100000000b    ;isolate the rem in ah with a AND mask to     determine whether the remainder is 0

    jz not_prime        ;if jump zero, goto not_prime
    inc bl          ;increment bl operand by one
    cmp bl, dl      ;compare bl and dl when bl is substracted from dl for result to be used in conditional jump
    jl loopy        ;loop continues if divisor is less than number

; message if number is prime
    push dword lenPrimeMsg
    push dword primeMsg
    push dword 1

    mov eax, 0x4
    sub esp, 4
    int 0x80

    add esp, 16

    push dword 1

    mov eax, 0x1
    sub esp, 4
    int 0x80

not_prime:
    mov eax, answer     
    mov eax,0       ;store 0 in answer if number is not prime

 ; message if number is NOT prime
    push dword lenNoPrimeMsg
    push dword noPrimeMsg
    push dword 1

    mov eax, 0x4
    sub esp, 4
    int 0x80

    add esp, 16

    push dword 1

    mov eax, 0x1
    sub esp, 4
    int 0x80
glowstarraw
  • 25
  • 1
  • 5
  • Your algorithm will fail already for number 2 (use debugger to see it in action). `(2 mod 2) = 0`. Also `jl loopy` => `jl` is for signed compare, so your operational range is only 0..+127 then (and -128..0 too, but that's not interesting for this algorithm). By using `jb` you would extend it to `0..+255` range. Move code duplicity to subroutines... And it's not clear what platform this is, the `int 0x80` calls and service numbers in `eax` resemble linux, but linux needs arguments in registers, not at stack, so this is probably something else, probably some obsolete OS. – Ped7g Apr 12 '17 at 13:49
  • 1
    Of course the best way to test `ah` for zero value is [`test ah,ah`](http://stackoverflow.com/a/41175294/4271923), your `and ax,...` is a bit cumbersome and slower, but correct, so this is just advice how "pros" do it, not a bug, that part is correct. But then you loop to `loopy:`, and expect the `ax` to contain "number", which is not true in second iteration, so you have to redesign it all... really, check it in debugger, it will give you much better understanding what happens. – Ped7g Apr 12 '17 at 13:52

0 Answers0