【问题标题】:Left Rotate Problem in Even/Odd Sum using Tracer SCO Debugger Assembly使用 Tracer SCO 调试器程序集的奇数/偶数和左旋转问题
【发布时间】:2020-05-07 00:47:15
【问题描述】:

我被困在下面的代码上。我有 Tracer 和 SCO Debugger 的以下代码。我正在使用 Dosbox 编译它,我想在代码中添加左旋转,但我找不到我要在哪里添加 ROL AX, 1 但它不起作用。

假设数字是

偶数 2,3,5,7,11

奇数 1,3,5,7,9

总和 3,6,10,14,20

我想让它看起来像

3,5,7,11,2

所以总和是

4,8,12,18,11

_EXIT = 1

.SECT .TEXT
start:
MOV BX, 0
MOV CX, 5

sum:
CMP BX, 5
JE done
NOP
MOVB AL,(BX)
ADD BX,odd
MOVB DL,(BX)
SUB BX,odd
ADDB AL,DL
ADD BX,result
MOV (BX),AX 
SUB BX,result
INC BX
LOOP sum

done:
MOV CX,5
MOV BX,result
print:
CMP BX,result + 5
JE exit
MOVB AL,(BX)
INC BX
LOOP print

exit:
PUSH _EXIT
SYS

.SECT .DATA
prime:
.BYTE 2,3,5,7,11
odd:
.BYTE 1,3,5,7,9
result:
.BYTE 0,0,0,0,0
.SECT .BSS

【问题讨论】:

    标签: assembly rotation x86-16 bit-shift dosbox


    【解决方案1】:

    rol ax, 1 作用于该寄存器中的位,而不是数组中的字节。您正在寻找的类似于 C++ std::rotate(first, new_first, last) 来旋转数组元素。

    您可以使用rol word [mem], 8 交换内存中的两个相邻字节,或者甚至执行 dword 旋转 8、16 或 24 位以重新排列 4 字节块中的字节,但这就是您可以做的全部旋转。

    例如,您可以这样做:

            ;; starting with prime = .byte 2,3,5,7,11 
    ror dword ptr [prime], 8             ; 3,5,7,2, 11   ; x86 is little-endian
    ror word ptr  [prime+4], 8           ; 3,5,7, 11,2
    

    那是 GAS .intel_syntax;我不认识您使用的语法。它看起来像是 AT&T 和 Intel 的混合体,带有用于寻址模式的圆括号,但它似乎确实是左侧的目的地。

    与仅加载所有 5 个字节并将它们存储回您想要的位置相比,这相当低效。具体来说,当第二个ror 的字加载部分读取刚刚由第一个ror 的双字存储部分存储的1 个字节时,您将获得存储转发停止。 (内存目标指令解码为加载 + ALU + 存储操作。当第二次旋转的加载执行时,第一个存储仍将在存储缓冲区中。假设现代 x86 CPU 本机执行此代码;但由于您在 DOSBox 中实际上被模拟而不被执行)。

    更直接的方法是:

        mov    eax, [prime+1]         ; dword load: 3,5,7,11
        mov    dl,  [prime]           ; byte load: 2
        mov    [prime], eax
        mov    [prime+4], cl          ; 3,5,7,11,2
    

    这很容易扩展到更大的数组大小。如果需要,您可以编写一个循环来将元素复制到前面,同时将原始的第一个元素保存在其他地方(在寄存器中)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多