0

I am stuck on the code below. I have the following code for Tracer and SCO Debugger. I am compiling it using Dosbox and I want to add left rotate to the code but I can't find where to I am trying to ad ROL AX, 1 but it is not working.

Let say numbers are

even 2,3,5,7,11

Odd 1,3,5,7,9

Sum 3,6,10,14,20

I want to make it look like

3,5,7,11,2

so the sum will be

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
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

1 Answers1

0

rol ax, 1 works on bits in that register, not bytes in an array. What you're looking for is like C++ std::rotate(first, new_first, last) to rotate array elements.

You can swap two adjacent bytes in memory with rol word [mem], 8, or even do a dword rotate by 8, 16, or 24 bits to re-arrange bytes in a 4-byte chunk, but that's all you can do with one rotate.

So for example you could do this:

        ;; 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

That's GAS .intel_syntax; I don't recognize the syntax you're using. It looks like a hybrid of AT&T and Intel with round parens for addressing modes, but it does seem to be destination on the left.

That's fairly inefficient compared to just loading all 5 bytes and storing them back where you want them. Specifically, you'll get a store-forwarding stall when the word load part of the 2nd ror reads 1 byte that was just stored by the dword store part of the first ror. (A memory-destination instruction decodes to load + ALU + store operations. The first store will still be in the store buffer when the 2nd rotate's load executes. Assuming a modern x86 CPU executing this code natively; but since you're in DOSBox it's actually getting emulated not executed).

The more straightforward way to do this would be:

    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

This is easy to extend for larger array sizes. If needed you can write a loop to copy elements toward the front while you have the original first element saved somewhere else (in a register).

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847