数组元素的乘积

Product of array elements

在这个练习中,我需要求数组元素的乘积。我写了下面的程序,但它似乎不起作用。正确答案是 -36288,但我一直得到 49.

我想要的结果是:-7 x 8 x -9 x 6 x 6 x -2。数组中的数字 3 被忽略。

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; 

循环遍历数组

这就是遍历数组的基本循环的样子。我相信您老师的循环看起来与这个非常相似。

  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

而且因为乘法是可交换的,所以您也可以从末尾开始遍历数组,第 8 个元素的偏移量为 +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

使用什么样的乘法?

这些数字是带符号的数字,因此您必须使用带符号的乘法 imul
因为数字 -7、8、-9、6、6 和 -2 的乘积是 -36288,所以您必须使用 imul 的字长版本。这意味着您从数组中读取的带符号字节必须先符号扩展为 AX,然后才能在乘法中使用它们。
跳过包含的数字 3 只是增加了复杂性。

  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

打印这个结果很棘手

您正在为此调用 print_num,但这将失败,因为结果超出了带符号字 [-32768, +32767] 的有效范围。屏幕会显示“29248”。
这里的技巧是在我们输出减号并对 AX:

中的数字取反后使用无符号版本 print_num_uns
  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