Rosalyo
Rosalyo

Reputation: 37

Intel 8086 - Reverse an array or loop backwards over it

I've been trying to write a code that reverses the content of an array two ways. I've done it right using push and pop method, but I don't know how to do it the pointer way.

I'm asking for any clarifications that could help.

.model small
.data
    tab db '12345' ,13,10,'$'
.code
main proc
    mov ax,@data
    mov ds,ax
    mov si,offset tab
    mov di,offset tab+5
    mov cx,5

    
    etiq1:  
    mov bx,[si]
    push bx
    inc si
    loop etiq1
    
    mov cx,5
    
    etiq2:
    pop dx
    mov ah,02h
    int 21h
    loop etiq2

main endp
end main

Upvotes: 1

Views: 1868

Answers (1)

Sep Roland
Sep Roland

Reputation: 39190

Reversing the string array via the stack and using string primitives lodsb and stosb.

Both the push-loop and the pop-loop end when they encounter the carriage return that terminates the string.
The CLD instruction is required to make lodsb and stosb go upwards in memory.
The code will print the result in one go with the DOS.PrintString function 09h.

  mov  ax, @data
  mov  ds, ax
  mov  di, offset tab
  mov  si, di
  mov  dx, di
  cld

etiq1:  
  lodsb
  push ax
  cmp  byte ptr [si], 13
  jne  etiq1

etiq2:
  pop  ax
  stosb
  cmp  byte ptr [di], 13
  jne  etiq2

  mov  ah, 09h        ; DOS.PrintString
  int  21h

  mov  ax, 4C00h      ; DOS.Terminate
  int  21h

Alternative way to reverse your array using a pointer.

The element on the left is read/written using the SI pointer, and the element on the right is read/written using the same pointer but offsetted by a suitable amount.
The loop can continue for as long as this offset remains greater than zero. The offset must be at least 1 for both addresses to talk to a different byte in memory.

  mov  ax, @data
  mov  ds, ax
  mov  si, offset tab
  mov  bx, 4          ; 5 elements : last element is at offset 4 from the first element
More:
  mov  al, [si]       ; Read on left side
  mov  dl, [si+bx]    ; Read on right side
  mov  [si], dl       ; Write on left side
  mov  [si+bx], al    ; Write on right side
  inc  si             ; Move to the right
  sub  bx, 2          ; Next couple of elements is 2 bytes closer to each other
  ja   More           ; Must stay above 0 to address different elements

  ; Here BX is -1, or 0 for remaining 0, or 1 element

  mov  dx, offset tab
  mov  ah, 09h        ; DOS.PrintString
  int  21h

  mov  ax, 4C00h      ; DOS.Terminate
  int  21h

Next is an optimization that reads and writes 2 elements at once.

This is of course only important when working with an array of some length, so not in your limited 5 byte array! This time, the offset must be at least 3 for both addresses to talk to a different word in memory.

  mov  ax, @data
  mov  ds, ax
  mov  si, offset tab
  mov  bx, NumberOfByteSizedElementsMinusOne
  jmp  Begin
More:
  mov  ax, [si]       ; Read pair on left side
  mov  dx, [si+bx-1]  ; Read pair on right side
  xchg al, ah
  xchg dl, dh
  mov  [si], dx       ; Write pair on left side
  mov  [si+bx-1], ax  ; Write pair on right side
  add  si, 2          ; Move to the right
  sub  bx, 4          ; Next couple of paired elements is 4 bytes closer to each other
Begin:
  cmp  bx, 3
  jge  More           ; Must stay above 2 to address different paired elements

  ; Here BX is -1, 0, 1, or 2 for remaining 0, 1, 2, or 3 elements

  cmp  bx, 0
  jle  Done
  mov  al, [si]       ; Read on left side
  mov  dl, [si+bx]    ; Read on right side
  mov  [si], dl       ; Write on left side
  mov  [si+bx], al    ; Write on right side
Done:

  mov  dx, offset tab
  mov  ah, 09h        ; DOS.PrintString
  int  21h

  mov  ax, 4C00h      ; DOS.Terminate
  int  21h

Upvotes: 2

Related Questions