arraysassemblyx86-16tasm

how to check if an arr is "wavy"?

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

Solution

• 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]
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
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:
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
``````