2017-04-20 46 views
4

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

DAA与'AL'搭配使用。你必须在那里移动结果。您可以 - 像这里一样 - 在添加之前将'AH'移动到'AL'。或者,您可以 - 像您的建议 - 先添加,但之后您必须将“AH”移至“AL”。 – rkhb

+0

谢谢,所以我可以做到这一点,但仍然需要将它全部使用DAA – vkubre

+0

是的。问题在于你以后需要原始的'AH'。情况并非如此,所以两种解决方案都是相同的。 – rkhb

回答

3

由于代码是当前写入,该指令是必要的,因为它将所需的值放入AL寄存器,以准备后续指令。在它后面的ADD指令明确地使用来自AL的值,以及下一个​​指令(隐含地)。

只是为了确保我们在同一页上,并为未来的读者的利益,让我们通过代码,并标注为:

; 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寄存器中,然后对低字节(低8位)和高字节进行打包二进制编码的十进制算术运算。最后,它将结果保存为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 

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

个人,我宁愿设置寄存器第一(如在原代码),然后执行ADD和​​回到后端。为什么?因为​​取决于标志,这些标志由ADD指令隐式设置(具体为辅助进位标志AF)。虽然MOV指令不会破坏标志,大部分其他指令都这样做,所以养成分离ADD和​​指令的风险会带来一个难以发现的错误。

重新排列这样的指令的唯一可能的好处是缓解数据依赖性,从而提高代码的执行速度。但是,这不会发生在这里,因为你在这三条指令之间仍然有一个不间断的依赖关系链。

+0

感谢这个答案确实有助于了解更多关于ALP的知识 – vkubre

相关问题