Search code examples
linuxassemblyx86nasm

Finding number is Even/Odd in assembly


I'm trying to find whether a given number (Input by user) is even or odd.

I'm simply applying AND operation on binary digits of a no. with 1, If the number is odd then operation will result 0 and we will Output Number is odd, otherwise we will output Number is even.

Although logic seems simple, But it's not working in the below code. I'm not getting where is the problem in the code. Can anybody tell me where is the problem

section .data
    userMsg db 'Please enter a number'
    lenuserMsg equ $ - userMsg  
    even_msg db 'Even Number!'
    len1 equ $ - even_msg
    odd_msg db 'Odd Number!'
    len2 equ $ - odd_msg

section .bss
    num resb 5    ;Reserved 5 Bytes for Input

section .text

global _start     ;must be declared for linker (gcc)

_start:
    ;User Prompt
    mov ebx, 1           ;file descriptor (stdout)
    mov ecx, userMsg     ;message to write 'Please enter a number'
    mov edx, lenuserMsg  ;message length
    mov eax, 4           ;system call number (sys_write)
    int 0x80             ;call kernel

    ;Taking user input
    mov ebx, 0           ;(stdin)
    mov ecx, num 
    mov edx, 5           ;i/p length
    mov eax, 3           ;system call number (sys_read)
    int 0x80             ;call kernel

    mov ax, [num]
    and ax, 1
    jz evnn              ;Jump on Even

    ;Printing No. is Odd
    mov ebx, 1           ;file descriptor (stdout) 
    mov ecx, odd_msg     ;message to write 'Odd Number!'
    mov edx, len2        ;message length
    mov eax, 4           ;system call number (sys_write)
    int 0x80             ;call kernel
    jmp outprog          ;Jump to exit

    ;Printing No. is Even
    evnn:
    mov ebx, 1           ;file descriptor (stdout) 
    mov ecx, even_msg    ;message to write 'Even Number!'
    mov edx, len1        ;message length  
    mov eax, 4           ;system call number (sys_write)
    int 0x80             ;call kernel

    ;Exit
    outprog: 
    mov eax, 1           ;system call number (sys_exit)
    int 0x80             ;call kernel

Solution

  • Your code does not work because when you ask the user for a number, you read in an ASCII encoded string. You will need to call atoi (ASCII to INT) first to convert the string to a "real" number as computers see it. atoi is included in glibc.

    extern atoi
    push eax ; pointer to your string to be converted, eg '123'
    call atoi
    ; now eax contains your number, 123
    

    You can also do a bit test on the least significant bit (bit 0) to find out if it is even or odd:

    mov al, 01000_1101b
    bt al, 0 ; copies the bit to the Carry Flag
    jc its_odd ; jump if CF==1
    ; else - it's even (CF==0)
    

    What BT does, it copies the bit to CF and you can do conditional jumps based on that.