Monday, February 13, 2012

NASM Example 2: Input an array and search for an element

; See the first example if you have doubts in the undocumented parts of this example.

section .data
welcome:        db      "Input the size of the array; Input q to quit"
w_len:          equ     $ - welcome
in_msg:         db      0xa, "Enter N: "
im_len:         equ     $ - in_msg
num_msg:        db      "Enter the numbers", 0xa
nm_len:         equ     $ - num_msg
srch_msg:       db      "Enter the number to search: "
sm_len:         equ     $ - srch_msg
out_msg0:       db      "Number was not found!"
om0_len:        equ     $ - out_msg0
out_msg1:       db      "Number was found at ",0,0,0,0 ;these last 4 bytes will be used to store the index
om1_len:        equ     $ - out_msg1

section .bss
n_str:          resb    4
num_str:        resb    4
num_arr:        resd    64

section .text
        global _start
print:
        push    ebx
        push    eax
        mov     eax,4
        mov     ebx,1
        int     0x80
        pop     eax
        pop     ebx
        ret

scan:
        push    ebx
        push    eax
        mov     eax,3
        mov     ebx,0
        int     0x80
        pop     eax
        pop     ebx
        ret

xTen:
        push    ebx
        mov     ebx,eax
        shl     eax,2
        add     eax,ebx
        shl     eax,1
        pop     ebx
        ret

byTen:
        push    edx
        push    ecx
        mov     edx,0
        mov     ecx,10
        div     ecx
        mov     ebx,edx
        pop     ecx
        pop     edx
        ret

toInt:
        push    ebx
        mov     eax,0
        mov     ebx,0
    .loopStr:
        call    xTen
        push    edx
        mov     edx,0
        mov     dl,byte[ecx+ebx]
        sub     dl,0x30
        add     eax,edx
        pop     edx
        inc     ebx
        cmp     byte[ecx+ebx],0xa
        jle     .return
        cmp     ebx,edx
        jge     .return
        jmp     .loopStr
    .return:
        pop     ebx
        ret

toStr:
        push    ebx
        push    eax
        mov     ebx,0
        push    0
    .loopDiv:
        call    byTen
        add     ebx,0x30
        push    ebx
        cmp     eax,0
        jg      .loopDiv
        mov     ebx,0
    .loopStr:
        pop     eax
        cmp     eax,0
        je      .loopFill
        cmp     ebx,edx
        je      .loopStr
        mov     byte[ecx+ebx],al
        inc     ebx
        jmp     .loopStr
    .loopFill:
        cmp     ebx,edx
        je      .return
        mov     byte[ecx+ebx],0
        inc     ebx
        jmp     .loopFill
    .return:
        pop     eax
        pop     ebx
        ret

searchN:        ;eax=number to be searched, ebx=address of num_arr, ecx=arr_size(>0)
                ;Result: ecx=index of the find (-1 => not found)
        push    edx
    .loopN:
        dec     ecx
        mov     edx,ecx
        shl     edx,2
        cmp     eax,dword[ebx+edx]
        je      .found
        cmp     ecx,0
        jne     .loopN
        mov     ecx,-1

    .found:
        pop     edx
        ret

_start:
        mov     ecx,welcome
        mov     edx,w_len
        call    print
    .main_loop:
        mov     ecx,in_msg ;Ask the user for N
        mov     edx,im_len
        call    print

        mov     ecx,n_str ;Input N
        mov     edx,4
        call    scan

        cmp     byte[n_str],0x71 ;If 'q', quit
        je      .quit

        call    toInt ;get the integer N, push it, and move it to ebx
        push    eax
        mov     ebx,eax

        mov     ecx,num_msg ;Ask the user to input all numbers
        mov     edx,nm_len
        call    print

    .loopN: ;Input the numbers
        dec     ebx
        mov     ecx,num_str ;get the number and store it in [num_arr+ebx*4]
        mov     edx,4
        call    scan
        call    toInt
        mov     edx,ebx
        shl     edx,2 ;edx = edx*4
        mov     dword[num_arr+edx], eax
        cmp     ebx,0
        jne     .loopN ;Note: The numbers will be stored in reverse order of input

        mov     ecx,srch_msg ;Ask for the number to search
        mov     edx,sm_len
        call    print

        mov     ecx,num_str ;get the number to search
        mov     edx,4
        call    scan
        call    toInt

        mov     ebx,num_arr
        pop     ecx ;pop N to ecx
        push    ecx ;push N
        call    searchN ;search for eax in num_arr
        cmp     ecx,-1
        je      .not_found

        pop     eax ;pop N
        sub     eax,ecx ;eax = N - ecx ;Since the numbers were stored in reverse order
                        ;If inputs are 1,2,3,4,5; numbers={5,4,3,2,1}; searchN(4,numbers) will give 1; We want 5-1 = 4
        mov     ecx,out_msg1 ;last 4 bytes of out_msg1 = toStr(eax)
        add     ecx,om1_len
        sub     ecx,4
        mov     edx,4
        call    toStr
        mov     ecx,out_msg1 ;print the whole out_msg1
        mov     edx,om1_len
        call    print
        jmp     .main_loop

    .not_found:
        mov     ecx,out_msg0
        mov     edx,om0_len
        call    print
        jmp     .main_loop

    .quit:
        mov     ebx,0
        mov     eax,1
        int     0x80

No comments:

Post a Comment