Home > other >  how to check if an arr is "wavy"?
how to check if an arr is "wavy"?

Time:12-09

my code should check if an ARR is "'wavy" which means the first element is less then the second, the second is greater then the third and same as this till the end of the arr.. but it doesn't work.. here is the code:

IDEAL
MODEL small
STACK 100h
DATASEG

        
ARR db 3 dup (?)
REZ db 1


CODESEG
start:
    mov ax,@data
    mov ds,ax
    mov cx,3                    ;cx=99
    xor ax,ax                    ; ax=0
    xor si,si                    ;si=0
    
    mov [ARR],0
    mov [ARR 1], 1
    mov [ARR 2], 0
    lea bx,[ARR]                 ; bx=offset arr
    L1: cmp cx,1
        je finish
        mov di,cx                ;di=cx (as index)
        neg di                   ;di=-di
        lea si,[bx di] 
        mov ax,[3 si]
        cmp ax,[4 si]      ; compre the odd vs even index                                                   illegal use of register
        jg wrong                             ; exit if the odd index > even index
        dec cx                               ; cx=cx-1
        cmp cx,0                             ; check if cx=0
        je finish                            ; if  cx=0 finish
        mov di,cx                ;di=cx (as index)
        neg di                   ;di=-di
        lea si,[bx di] 
        mov ax,[3 si]
        cmp ax,[4 si]        ; compre the even vs odd index                                                 illegal use of register
        jl wrong                            ; exit if the even <odd index
        loop L1                             ; cx=cx-1      if cx!=0 -> jump to L1
    wrong:
        mov [REZ],0
    finish:
    


exit:
    mov ax,4c00h
    int 21h
END start


there is even an example but it doesn't work..
do u know where is the mistake?

in the end we should end with res=1 if the arr is "wavy" or if it is not wavy arr=0

CodePudding user response:

You have a mismatch between the size of the array elements (byte), and the size of the operations that you perform on these elements (word).

The definition ARR db 3 dup (?) does not match the code mov ax,[3 si] cmp ax,[4 si]. You need to write mov AL, [3 si] cmp AL, [4 si] instead.

When the loop ends, you should not fall-through into wrong, but rather jmp to exit.

A single address register is enough:

  sub  cx, 1
  jbe  exit         ; In case of 0 or 1 array elements
  lea  si, [ARR]
  cld               ; Clear direction flag so LODSB will increment SI
L1:
  lodsb
  cmp  al, [si]
  jg   wrong
  dec  cx
  jz   exit
  lodsb
  cmp  al, [si]
  jl   wrong
  loop L1
  jmp  exit
wrong:
  ...
exit:
  ...

It is fascinating to explore alternative solutions

  • Using separate loops for the rising and falling edges of the sawtooth. Not only are the new loops very short, they can iterate over just one conditional branch thanks to sticking a sentinel to the end of the array. The sentinel is chosen such that the loop has got to end. The position where the loop exit occurs then decides about success or failure:

      mov  si, offset ARR         ; Address of the array
      mov  cx, ...                ; Number of array elements
      call TestWavy               ; -> AL=[0,1]
      mov  [REZ], al
    
      ...
    
    ; IN (cx,si) OUT (al) MOD (ah,bx,cx,dx,si,di)
    TestWavy:
      cld                         ; Clear DF so LODSW will SI  
      mov  bx, cx
      shr  bx, 1
      jz   .fine                  ; In case of 0 or 1 array elements
      lea  di, [si bx]
      add  di, bx
      mov  dx, [di]               ; Preserve existing bytes
      mov  word ptr [di], 0102h   ; Sentinel for the rising edge
      push si                     ; (1)
    .rise:
      lodsw
      cmp  al, ah
      jng  .rise
      mov  [di], dx               ; Restore the bytes
      cmp  si, di
      pop  si                     ; (1)
      jbe  .wrong
    
      inc  si                     ; Address of the first falling edge
      dec  cx
      shr  cx, 1
      jz   .fine                  ; In case of 2 array elements
      mov  di, si
      add  di, cx
      add  di, cx
      mov  dx, [di]               ; Preserve existing bytes
      mov  word ptr [di], 0201h   ; Sentinel for the falling edge
    .fall:
      lodsw
      cmp  al, ah
      jnl  .fall
      mov  [di], dx               ; Restore the bytes
      cmp  si, di
      jbe  .wrong
    .fine:
      mov  al, 1
      ret
    .wrong:
      mov  al, 0
      ret
    
  • Using the byte-sized registers to the fullest. This minimizes the number of memory accesses as well as the number of iterations on the loop. Every iteration is guaranteed to be able to perform 8 comparisons, thanks to replicating the last element 7 times. The idea is, that this way, no early exits have to be included. And don't forget that you need to keep 7 unoccupied bytes after the array.

      mov  si, offset ARR         ; Address of the array
      mov  cx, ...                ; Number of array elements
      call TestWavy               ; -> AL=[0,1]
      mov  [REZ], al
    
      ...
    
    ; IN (cx,si) OUT (al) MOD (ah,bx,cx,dx,si,di,bp)
    TestWavy:
      sub  cx, 1
      jbe  .fine                  ; In case of 0 or 1 array elements
      cld                         ; Clear DF so LODSW will SI  
      mov  bp, cx                 ;         and STOSB will DI  
      lea  di, [si bp]            ; Address of the last element
      mov  al, [di]
      mov  cx, 8
      rep stosb
    .more:
      lodsw                       ; Load 8 elements
      xchg dx, ax                 ; `mov dx, ax`
      lodsw
      xchg cx, ax                 ; `mov cx, ax`
      lodsw
      xchg bx, ax                 ; `mov bx, ax`
      lodsw
      cmp  dl, dh                 ; Check 4 rising edges
      jg   .wrong
      cmp  cl, ch
      jg   .wrong
      cmp  bl, bh
      jg   .wrong
      cmp  al, ah
      jg   .wrong
      cmp  dh, cl                 ; Check 4 falling edges
      jl   .wrong
      cmp  ch, bl
      jl   .wrong
      cmp  bh, al
      jl   .wrong
      cmp  ah, [si]
      jl   .wrong
      sub  bp, 8
      ja   .more
    .fine:
      mov  al, 1
      ret
    .wrong:
      mov  al, 0
      ret
    
  • Related