以下装配程序中是否需要此行?

时间:2017-04-20 03:33:38

标签: assembly x86-16

我是ALP的新手,在查看这个程序时,我发现我认为不需要的一行,可以简单地删除,改变几行。

以下是代码:

DATA SEGMENT
  N1 DW 2804H
  N2 DW 4213H
  BCD_SUM DW ?
DATA ENDS

CODE SEGMENT
ASSUME CS: CODE, DS: DATA
START: MOV AX, DATA
  MOV DS, AX
  MOV AX, N1
  MOV BX, N2
  ADD AL, BL
  DAA
  MOV CL, AL
  MOV AL, AH    ; Here I have Problem
  ADD AL, BH
  DAA
  MOV CH, AL
  MOV BCD_SUM, CX
  MOV AH, 4CH
  INT 21H
CODE ENDS
END START

为什么不只做add ah, bh? 将AX处的较高字节移至较低位置,然后添加,是否有任何原因可以或者我只是简单地更改它?

1 个答案:

答案 0 :(得分:3)

当代码当前写入时,该指令是必要的,因为它将所需的值放在AL寄存器中,以备后续指令。其后的ADD指令明确使用AL中的值,下一个DAA指令(隐式)也是如此。

只是为了确保我们位于同一页面上,并且为了未来读者的利益,让我们浏览一下代码并对其进行注释:

; Set the segment register 'DS' to the constant value 'DATA'
; (indirectly via 'AX', since you can't move an immediate into a segment register).
MOV AX, DATA
MOV DS, AX

; Put the constant values 'N1' and 'N2' into the 'AX' and 'BX' registers, respectively.
MOV AX, N1
MOV BX, N2

; Add the lower 8 bits of 'BX' to the lower 8 bits of 'AX'.
ADD AL, BL

; Using the results of that last addition ('AL' and flags),
; adjust for packed binary-coded decimal arithmetic.
DAA

; Save the result (from 'AL') in 'CL' (since 'AL' is about to be clobbered).
MOV CL, AL

; Having just done the low 8 bits of 'AX' ('AL'), we are now going to do
; the high 8 bits ('AH'). But because the DAA instruction uses 'AL'
; as an implicit operand, we first need to swap 'AL' and 'AH'.
MOV AL, AH
ADD AL, BH
DAA

; Just like we saved the result of the low 8 bits in 'CL',
; save the result of the high 8 bits in 'CH'.
MOV CH, AL

; Now, the result is in 'CX' (low byte in 'CL', high byte in 'CH'),
; so store/save it into the WORD-sized variable 'BCD_SUM'.
MOV BCD_SUM, CX

; Call DOS interrupt to terminate the process.
; 
; Note that there is a bug here: you should be setting the 'AL' register
; to the process's return code. You could do this explicitly with a
; 'MOV AL, ReturnCode' instruction, or you could just do
; 'MOV AX, 4C00h' to set both halves at once.
MOV AH, 4CH
INT 21H

希望您现在可以看到原始代码的逻辑,以及为什么它的编写方式如此。它将完整的WORD大小的值加载到AXBX寄存器中,然后在低BYTE(低8位)和高BYTE上执行打包的二进制编码十进制算术运算。最后,它将结果保存为BCD_SUM中的完整WORD大小的值,间接通过CX作为临时寄存器。

现在,你当然可以用不同的方式编写相同的代码,但仍然可以完成相同的任务。这基本上就是你在问题中的建议 - 重新排序说明,以便你有:

ADD AH, BH     ; add high bytes first
MOV AL, AH     ; swap order of bytes
DAA            ; adjust result of addition, now in AL

然而,编写这样的代码绝对没有优势。这只是个人选择的问题,你认为哪一个更清楚。

就个人而言,我更愿意先设置寄存器(如原始代码中所示),然后再执行ADDDAA -to-回来。为什么?因为DAA依赖于ADD指令隐式设置的标志(特别是辅助进位标志AF)。虽然MOV说明不会破坏标记,大多数其他说明都会这样做,因此养成分离ADDDAA指令的习惯可能会导致难以发现的错误。

重新排列这样的指令的唯一可能优点是减轻数据依赖性,从而提高代码的执行速度。但是,这不会发生在这里,因为你在这三条指令之间仍然存在完整的依赖链。