0

In this exercise, I need to find the product of the array elements. I wrote the following program but it doesn't seem to work. The correct answer is -36288, but I keep getting 49.

The result I'm after is : -7 x 8 x -9 x 6 x 6 x -2. The number 3 in the array is be ignored.

include 'emu8086.inc'

ORG 100h
mov bx, 0
MOV di, 0 
cmp b [di+bx], 3 
je skip
skip: add di,1
cmp di, 7
jle qemer 
qemer: mov Al, b [di + bx]
inc di 
imul b [di+bx] 

CALL pthis
DB 13, 10, 'Result:', 0
CALL print_num; print number in AX.
RET; return to operating system.
b DB 3,-7,8,-9,6,3,6,-2
DEFINE_SCAN_NUM
DEFINE_PRINT_STRING
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS; required for print_num.
DEFINE_PTHIS
DEFINE_CLEAR_SCREEN
END; 
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
jane
  • 124
  • 10
  • 1
    Please elaborate on exactly what _"it doesn't seem to work"_ means. – Michael Jan 18 '21 at 11:17
  • I mean, the correct answer is - 36288, but I get 49 – jane Jan 18 '21 at 11:18
  • 3
    Aren't you supposed to iterate over the entire array? I can't see any loop in this code. Also, a conditional jump immedately followed by the jump target is almost always a bug. – Michael Jan 18 '21 at 11:31
  • @Michael our teacher taught us loop only with cmp, i don't know other way to do it – jane Jan 18 '21 at 11:32
  • @Michael if it is not a big deal for you, can you correct this (with cmp) for me? – jane Jan 18 '21 at 11:36
  • 2
    A loop means that you have a block of one or more instructions that can be executed multiple times in succession. That never happens in your code. – Michael Jan 18 '21 at 11:38
  • @Michael yeah, i know but i am new to assembly and at school we are only taught cmp if we need to use loop. so – jane Jan 18 '21 at 11:54
  • Yes, it's possible to use `cmp/jcc` to make a loop, but that's *not* how you've used it. What you've done is more like an empty `if(){}` statement. – Peter Cordes Jan 18 '21 at 12:16

1 Answers1

2

Traversing the array with a loop

This is how your basic loop that traverses the array looks like. I'm sure your teacher's loop will look very similar to this one.

  xor  si, si          ; Clears offset into the array
More:
  mov  al, array [si]  ; Reads an element

  ; act on the value

  inc  si              ; Next byte-sized element
  cmp  si, 8           ; Array has 8 bytes
  jb   More            ; Repeat for all value less than 8

And because multiplication is commutative, you could just as well traverse the array starting at the end, with the 8th element being at offset +7:

  mov  si, 7           ; Offset into the array to the last element
More:
  mov  al, array [si]  ; Reads an element

  ; act on the value

  dec  si              ; Next byte-sized element
  jns  More            ; Repeat for all positive values

What kind of multiplication to use?

The numbers are signed numbers, so you'll have to use the signed multiplication imul.
Because the product of the numbers -7, 8, -9, 6, 6, and -2 is -36288, you'll have to use the word-sized version of imul. This means that the signed bytes that you read from the array must be sign-extended into AX before using them in the multiplication.
And skipping the included numbers 3 is just an added complexity.

  mov  bx, 1           ; Initialize the result with the product-neutral value
  xor  si, si
More:
  mov  al, array [si]
  cmp  al, 3           ; Don't use the number 3
  je   Skip
  cbw                  ; Sign-extend AL into AX
  imul bx              ; AX * BX -> DX:AX = {-7, -56, 504, 3024, 18144, -36288}
  mov  bx, ax          ; Update the result in BX
Skip:
  inc  si
  cmp  si, 8
  jb   More

Printing this result is tricky

You are calling print_num for this, but this will fail because the result is outside the valid range for a signed word [-32768, +32767]. The screen would show you "29248".
The trick here is to use the unsigned version print_num_uns after we have outputted a minus sign and have negated the number in AX:

  call pthis
  db   13, 10, 'Result:', 0
  putc '-'
  mov  ax, bx
  neg  ax
  call print_num_uns
  ret

array db 3, -7, 8, -9, 6, 3, 6, -2
DEFINE_SCAN_NUM
DEFINE_PRINT_STRING
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
DEFINE_PTHIS
DEFINE_CLEAR_SCREEN
END
Sep Roland
  • 33,889
  • 7
  • 43
  • 76