使用Tracer SCO调试器汇编的偶数和奇数中的左旋问题。

问题描述 投票:0回答:1

我被下面的代码卡住了。我有以下代码的Tracer和SCO调试器。我编译它使用Dosbox,我想添加左旋转的代码,但我不能找到在哪里,我试图广告ROL AX,1,但它是行不通的。

让我们说数字是

偶数

奇数 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个回答
0
投票

rol ax, 1 工作在该寄存器中的位,而不是数组中的字节。 你要找的是像C++ std::rotate(first, new_first, last) 来旋转数组元素。

你可以在内存中用 rol word [mem], 8或者甚至做一个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个字节并将它们存储回你想要的地方相比,这是相当低效的。 具体来说,当第2个字加载部分的时候,你会得到一个存储转发的停顿。ror 读取刚才由第一段的dword存储部分存储的1个字节。ror. (一条内存定位指令解码为加载+ALU+存储操作。 当第2次旋转的加载执行时,第一个存储仍将在存储缓冲区中。 假设一个现代的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

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

© www.soinside.com 2019 - 2024. All rights reserved.