Advertisement

Count Positive and Negative numbers in Array in NASM

Write X86/64 ALP to count number of positive and negative numbers from the array.

                                         

 %macro print 2                            ;Macro for printing

    mov rax, 1                            ;rax = 1 for sys_write    
    mov rdi, 1                            ;unsigned int file descriptor
    mov rsi, %1                            ;Buffer address
    mov rdx, %2                            ;Buffer length
    syscall                                ;Makes system call
%endmacro

%macro input 2                            ;Macro for reading
    mov rax, 0                            ;rax = 0 for sys_read
    mov rdi, 0                            ;unsigned int file descriptor
    mov rsi, %1                            ;Buffer address
    mov rdx, %2                            ;Buffer length
    syscall                                ;Makes system call
%endmacro

section .data                            ;For declaring initialized data
    
    mssg db "Write a X86/64 ALP to count number of positive and negative numbers from the array."
    mssg_len:equ $ - mssg                    
    mssg_name db "AMAN THAKUR 3205"        ;Initialising mssg_name
    mssg_name_len: equ $-mssg_name    
        
    mssg1 db "Enter your number : "
    mssg1_len:equ $ - mssg1    
    mssg_pos_cnt db "Total positive numbers : "
    mssg_pos_cnt_len:equ $ - mssg_pos_cnt
    mssg_neg_cnt db "Total negative numbers : "
    mssg_neg_cnt_len:equ $ - mssg_neg_cnt
    
    cnt_positive db 0                    ;To store count of +ve numbers
    cnt_negative db 0                    ;To store count of -ve numebrs
    
    mssg_error db "Error!!"                
    mssg_error_len:equ $-mssg_error
    space db " "    
    newline db 10                        
    
section .bss                            ;For declaring variables.
    num1 resb 17                        ;Reserving 17 Byte.
    positive resq 5                        ;Reserving 5 quad word for positive array.
    negative resq 5                        ;Reserving 5 quad word for negative array.
    temp resb 16                        ;To store 64 bit result to display
    temp2 resb 2                        ;To store 8 bit result to display
    
section .text                            ;Actual code is present.
    global _start                        ;has to be declared for linker(ld).
    _start:                             ;tells linker entry point.
    
    print mssg, mssg_len                ;Problem Statement.
    print newline, 1                
    print mssg_name, mssg_name_len        ;Name and roll number.
    print newline, 1
    
    mov rsi, positive                     ;Pointing to rsi to first index of positive
    mov rdi, negative                    ;Pointing to rdi to first index of negative
    mov rcx, 5
    
    ;=======Input and counting positive and negative numebers========
    next0 :
        push rcx
        push rsi                        ;Pushing registers in stack to avoid change in values
        push rdi

        print mssg1, mssg1_len
        input num1, 17
        call ascii_hex64
        
        pop rdi
        pop rsi
        
        bt rbx, 63                        ;Copies the value of bit indexed into the carry flag
        jc is_negative
        
        mov [rsi], rbx                    ;In Case number is positive, storing it in positive arr
        add rsi, 8                        ;Making rsi point to next element
        inc byte[cnt_positive]
        jmp Continue
        
        is_negative:
            mov [rdi], rbx                ;In Case number is negative, storing it in negative arr
            add rdi, 8                    ;Making rdi point to next element
            inc byte[cnt_negative]
        
        Continue:    
            pop rcx
            dec rcx
            jnz next0
        
    print newline, 1
    ;=========== Displaying Positive Numbers ==========
    
    print mssg_pos_cnt, mssg_pos_cnt_len
    mov bl, [cnt_positive]                    ;Storing positive count in bl to display
    call display8                            ;To display positive count
    print newline, 1
    
    mov rcx, [cnt_positive]    
    mov rsi, positive                        ;Making rsi point to start of positive arr
    next_pos:
        mov rbx, [rsi]                        ;Storing value in rbx to display
        
        push rsi
        call display64
        print newline, 1
        pop rsi
        
        add rsi, 8                            ;Incrementing rsi to point next index
        dec byte[cnt_positive]    
        jnz next_pos
    
    print newline, 1
    
    ;==============Displaying Negative Numbers ==============
    
    print mssg_neg_cnt, mssg_neg_cnt_len
    mov bl, [cnt_negative]                    ;Storing negative count in bl to display
    call display8                            ;To display negative count
    print newline, 1
    
    mov rcx, [cnt_negative]    
    mov rdi, negative                        ;Making rdi point to start of negative arr
    next_neg:
        mov rbx, [rdi]                        ;Storing value in rbx to display
        
        push rdi
        call display64
        print newline, 1
        pop rdi
        
        add rdi, 8                            ;Incrementing rdi to point next index
        dec byte[cnt_negative]    
        jnz next_neg
    
    
    Exit:
    mov rax, 60                                ;rax = 60 for sys_exit.
    mov rdi, 0
    syscall
    err:
        print mssg_error, mssg_error_len    ;Error mssg for invalid input.
        print newline, 1
        mov rax, 60                
        mov rdi, 0
        syscall
    
ascii_hex64:
    mov rcx, 16                      
    mov rsi, num1                            ;rsi points to num1
    mov rbx, 0                     
    next:                        
        rol rbx, 4                            ;Rotating by 4 bits to left, 0Fh -> F0h
        mov al, [rsi]                        ;Assigning [rsi] to al
        
        cmp al, 2Fh                         ;Checking For Error
        jbe err                                ;Case: al < 30h (0)
        cmp al, 47h    
        jge err                                ;Case: al > 46h  (F)
        cmp al, 39h                
        jle ELSE                            ;Case: al <= 39h (9), No Error
        cmp al, 40h                
        jle err                                ;Case al > 39(9) and al < 41(A)
        
        ELSE:
                            
        cmp al, 39h                            ;Here we convert ascii to hex
        jbe  sub30h                            ;If al <= 39h (9), subtract 30h
        sub al, 7h                            ;Else subtract 37h
        sub30h:
            sub al, 30h                        ;Subtracting 30h from al
        add bl, al                
        inc rsi                
        dec rcx                
    jnz next
    
    ret                                     ;Return


display64:
    mov rcx, 16                    
    mov rsi, temp                            ;rsi points to len
    next1:    
        rol rbx, 4                            ;rotating by 4 bits to left
        mov al, bl                
        and al, 0Fh                            ;To get only last digit, eg. 5Ah & 0Fh = 0Ah
        cmp al, 9h                            ;Case : al <= 9h (9)
        jbe add30h                            ;If True add 30h
        add al, 7h                            ;Else add 37h

        add30h:
            add al, 30h                        ;Adding 30h to al
        mov [rsi], al                        ;Storing al in temp
        inc rsi                
        dec rcx                
    jnz next1
    
    print temp, 16                            ;Printing number in ascii
    ret                                        ;Return
    
display8:
    mov rcx, 2                    
    mov rsi, temp2                            ;rsi points to len
    next2:    
        rol bl, 4                            ;rotating by 4 bits to left
        mov al, bl                
        and al, 0Fh                            ;To get only last digit, eg. 5Ah & 0Fh = 0Ah
        cmp al, 9h                            ;Case : al <= 9h (9)
        jbe add30h2                            ;If True add 30h
        add al, 7h                            ;Else add 37h

        add30h2:
            add al, 30h                        ;Adding 30h to al
        mov [rsi], al                        ;Storing al in temp
        inc rsi                
        dec rcx                
    jnz next2
    
    print temp2, 2                            ;Printing number in ascii
    ret                                        ;Return

Post a Comment

0 Comments