【问题标题】:how to check if 2 numbers have reversed bits in assembly?如何检查 2 个数字在汇编中是否有反转位?
【发布时间】:2022-12-10 08:04:14
【问题描述】:

我的代码应该得到 2 个具有相同长度 (k) 的 arr,并检查有多少对数字具有相同的索引(1 在 arr 1 中,另一个在 arr2 中)并且相反,这意味着 1 中的第一位应该是最后一个和第二个到第一个将是第二个到第一个然后继续......

总的来说,这是我的代码:

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

我的调试器没有给我任何错误,但是当我运行代码时它不起作用,当我左移 arr 2 中的数字时它不会更改 CF 尽管它应该。

你知道为什么会这样吗?

【问题讨论】:

  • 如果我理解正确的话,你是将0x81 存储到ARR2 并将0x33 存储到ARR2+1,对吗?然后用shr [di+bx],1按字长移动这对?请记住,x86 是小尾数法,这意味着 CPU 将您的 ARR2 视为 0x3381,因此您不会立即看到进位标志设置。它会在大约 5 个班次后发生。如果您以其他方式存储字节,您会在移动一次后立即看到一个进位集。
  • 要么是那个,要么是汇编器对你的意图感到困惑,并用 0033h 中的 33 破坏了你的 1000000000000001b。如果你做了mov [ARR2],8133h.,你可能会有更好的运气
  • mov [ARR1+1],0033h 表示 16 位操作数大小,因为 ARR1 使用 dw。但是你只使用了+1的字节偏移量,所以它与之前的单词存储重叠。在这些初始存储之后,使用调试器检查内存中的内容。
  • @PeterCordes 啊,我错过了那部分。我认为出于某种原因它们被声明为db。是的,您需要使用 [ARR1+2] 因为数组的每个“插槽”占用两个字节。您也可以将 jnc nc1 inc al 替换为单个 adc al, 0 并获得相同的结果。我发现跳转次数较少的代码更容易调试,因此这也可能对您有所帮助。
  • @puppydrum64:是的,有很多方法可以简化或优化它,并且同意无分支代码更容易遵循,除非它需要更多的复杂性。在这里,我可能会 mov al, [si+bx] / and al, 1 然后转移到那个位。或者根据 CF 使用 salcsbb al,al 实现 0 或 -1。 (这本身有点棘手,但是一旦你学会了就可以使用它。sbb ah,ah 可以获得高位。)或者只是 shr / adc al, 0 / shl / sbb al, 0 / jz equal_bits 而不是具体化单独的布尔值进行比较。

标签: assembly tasm


【解决方案1】:
mov [ARR1],1000000000000001b
mov [ARR2],1000000000000001b
mov [ARR1+1],0033h
mov [ARR2+1],0033h        ; ARR1/ARR2 contain 1, 51, 0, ?

您的程序定义了 2 个数组,每个数组具有 2 个字大小的元素。因为一个字在内存中占2个字节,所以给第2个元素赋值必须使用+2的偏移量。为第三个元素赋值必须使用 +4 的偏移量,依此类推。

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

内循环(L2) 正在处理单词,但外循环 (L1) 按字节推进数组。第一次外部迭代 CX 为 2,因此 BX = k - CX 变为 0,而在第二次外部迭代 CX=1,因此 BX = k - CX 变为 1,然后将开始处理由第一个数组的高字节组成的字元素连同第二个数组元素的低字节。
好消息是您不需要那种复杂的方式(使用 BX)来遍历这些数组。只需在外循环的每次迭代中将 SI 和 DI 加 2。

您的程序包含许多冗余指令,如 xor dx, dx 和不必要的指令,如 clc。为清楚起见,您应该删除这些无效的行。


检查有多少对数字具有相同的索引(1 在 arr 1 中,另一个在 arr2 中)并且相反

知道数组包含每 2 个元素,这意味着程序的最终结果必须是 [0,2] 范围内的数字。

如果没有上述错误,您的程序会运行良好,只是我不会选择清除数组的解决方案。
下面是我的实现。仔细阅读尾部cmets!

    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

【讨论】:

    猜你喜欢
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多