Search code examples
arraysassemblybit-manipulationx86-16tasm

how to check if 2 numbers have reversed bits in assembly?


My code should get 2 arr with the same length(k) and to check how much pairs of numbers have the same index (1 in arr 1 and the other in arr2) and are opposite, which means the first bit in 1 should be the last in the other and the second to first would be the second to first and go on...

Overall, this is my code:

IDEAL
MODEL small
STACK 100h
DATASEG

k dw 2                       ;length of arr1 and arr2
ARR1 dw 2 dup (?)
ARR2 dw 2 dup (?)
CODESEG
start:  
    mov ax,@data
    mov ds,ax
    
    lea si,[ARR1]
    lea di,[ARR2]
    mov cx,k                 ; cx=length of arr
    xor dx,dx
    mov [ARR1],1000000000000001b
    mov [ARR2],1000000000000001b
    mov [ARR1+1],0033h
    mov [ARR2+1],0033h
        xor dx,dx
        L1:                                      ; loops through every index in both arr1, and arr2
            mov bx,k
            sub bx,cx
            push cx
            mov cx,16
            L2:
                xor ax,ax
                shr [si+bx],1
                jnc nc1
                inc al
                nc1:
                clc
                shl [di+bx],1
                jnc nc2
                inc ah
                nc2:
                clc
                cmp al,ah
                jne end_loop2
                
                dec cx
                jnz L2
                
            inc dx
            end_loop2:
            pop cx
            
            dec cx
            jnz L1



exit:
    mov ax, 4c00h
    int 21h
END start

My debugger doesn't give me any errors but when I run the code it doesn't work, when I shift left the number in arr 2 it doesn't change the CF though it should.

Do you know why is that happening?


Solution

  • mov [ARR1],1000000000000001b
    mov [ARR2],1000000000000001b
    mov [ARR1+1],0033h
    mov [ARR2+1],0033h        ; ARR1/ARR2 contain 1, 51, 0, ?
    

    Your program defines 2 arrays that have each 2 word-sized elements. Because a word occupies 2 bytes in memory, assigning a value to the 2nd element must use an offset of +2. Assigning a value to the 3rd element would have to use an offset of +4, and so on.

    mov [ARR1], 8001h
    mov [ARR2], 8001h
    mov [ARR1+2], 0033h
    mov [ARR2+2], 0033h         ; ARR1/ARR2 contain 1, 128, 51, 0
    
    L1:
      mov bx,k
      sub bx,cx
    

    The inner loop (L2) is processing words but the outer loop (L1) advances through the array per byte. On the 1st outer iteration CX is 2 so BX = k - CX becomes 0, and on the 2nd outer iteration CX=1 so BX = k - CX becomes 1 which then will begin processing a word composed of the high byte from the 1st array element together with the low byte from the 2nd array element.
    The good news is that you don't need that convoluted way (using BX) to walk through these arrays. Just add 2 to SI and DI on every iteration of the outer loop.

    Your program contains a number of redundant instructions like xor dx, dx and unnecessary instructions like clc. For clarity you should remove these unproductive lines.


    to check how much pairs of numbers have the same index (1 in arr 1 and the other in arr2) and are opposite

    Knowing that the arrays hold each 2 elements, this means that the final result of your program will have to be a number in the range [0,2].

    Without the forementioned errors your program would have worked fine, except that a solution that wipes out the arrays is not something I would have chosen.
    Below is my implementation. Read the tail comments carefully!

        lea  si, [ARR1]      ; SI is address of 1st array
        mov  [si], 8001h     ; Assign 1st element
        mov  [si+2], 0033h   ; Assign 2nd element
        lea  di, [ARR2]      ; DI is address of 2nd array
        mov  [di], 8001h     ; Assign 1st element
        mov  [di+2], 0033h   ; Assign 2nd element
    
        mov  bp, k           ; Number of array elements
        xor  dx, dx          ; Final result (will be 1 based on the fixed data)
    L1:
        mov  cx, [di]        ; CX is current element from 2nd array
        mov  bx, [si]        ; BX is current element from 1st array
        xor  ax, ax          ; AL is status byte, AH is a convenient 0
    L2:
        shr  bx, 1           ; The bit that comes out of BX
        adc  al, ah          ;   is added to AL (that was zeroed beforehand)
        shl  cx, 1           ; The bit that comes out of CX (at the opposite side)
        sbb  al, ah          ;   is subtracted from AL
        jnz  NOK             ; If both bits matched then AL would still be zero
        test bx, bx          ; Has BX more ON bits ?
        jnz  L2              ; Yes
    
                             ; Early exiting if BX has no more ON bits
                             ; If, at the same time, CX too has no more ON bits
                             ; then an OK pair was found
    
        test cx, cx
        jnz  NOK
    OK:
        inc  dx              ; Found an OK pair
    NOK:
        add  si, 2           ; Next array element is 2 bytes higher in memory
        add  di, 2
        dec  bp              ; Repeat for every element in the array(s)
        jnz  L1