如何检查2个数字是否在汇编中颠倒了位?



我的代码应该得到2个长度相同的arr (k),并检查有多少对数字具有相同的索引(arr1中的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,尽管它应该。

你知道为什么会这样吗?

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

程序定义了两个数组,每个数组有两个单词大小的元素。因为一个字在内存中占用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。为了清晰起见,你应该删除这些无效的行。


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

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

如果没有前面提到的错误,您的程序就可以正常工作,只是我不会选择清除数组的解决方案。
下面是我的实现。仔细阅读尾部评论!

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

如果串行实现,则内部循环至少可以压缩到

again:
add ax,ax  ; shift ax, while moving MSB to carry
sbb bx, 0  ; subtract carry (i.e 0 or 1) from bx
; here the LSB of bx will be 0 afterwards,
; iff the top bit of ax == lsb of bx
; in this case the top 15 bits of bx will
; be preserved for further iterations
shr bx, 1  ; now we shift out the LSB, setting CF on failure
jc not_ok 
jnz again  ; there are further bits on bx to check
;
test ax,ax ; we need to check that ax == 0, when bx == 0
jnz not_ok ;
ok:            ; there was full match

我认为在AX上单独的早期出口没有多大意义,但是可以对输入进行排序,放置BX <= AX,因此BX将更快地耗尽比特。

使用奇偶校验标志,就像在how-to-exchange- two -bit -in-a- byte-number中一样,可以大大简化内部循环:

ok = (bitreverse(al) == bh) && (bitreverse(bl) == ah)

使用下面的实现,除了ax = input0, bx = input1,甚至不需要任何其他寄存器。

test al, 0x81
jpe 1f          // parity even IFF al == 0x81 OR al == 0
xor  al, 0x81   // toggle bits 0x80 and 0x01, if there was only 1 bit
1:  test al, 0x42
jpe 2f
2:  xor  al, 0x42
test al, 0x24
jpe 3f
3:  xor  al, 0x24
test al, 0x18
jpe 4f
xor  al, 0x18
4:  cmp  al, bh
jnz  NOT_OK

// and same for the pair bl, ah

最新更新