2017-04-20 1 views
4

저는 ALP에서 꽤 새로 왔습니다.이 프로그램을 보면서 나는 불필요한 줄을 발견했고 몇 줄을 바꾸어 간단하게 제거 할 수있었습니다. 단지 add ah, bh하지 왜다음 어셈블리 프로그램에서이 줄이 필요합니까?

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 

: 여기

코드인가?
더 높은 바이트를 AX으로 이동 한 다음 추가 할 이유가 있습니까? 아니면 간단히 변경할 수 있습니까?

+1

'DAA'는'AL'과 함께 작동합니다. 결과를 거기로 옮겨야합니다. 여기처럼 - 추가하기 전에 'AH'에서'AL'으로 움직일 수 있습니다. 또는 제안 사항을 먼저 할 수도 있지만 나중에 AH를 AL로 이동해야합니다. – rkhb

+0

고마워요. 그렇게 할 수는 있지만 여전히 daa를 사용하여 모든 것을 옮길 필요가 있습니다. – vkubre

+0

예. 질문은 나중에 원래의 'AH'가 필요합니다.이것은 사실이 아니므로 두 솔루션이 동일합니다. – rkhb

답변

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 

을 이제 원래 코드의 논리를 참조 왜 그것이 어떻게 쓰여졌는지를 AXBX 레지스터에 WORD 크기의 전체 값을로드 한 다음 낮은 BYTE (하위 8 비트) 및 상위 바이트에서 채워진 2 진 코드 10 진수 연산을 수행합니다. 마지막으로 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 

그러나, 절대적으로 같은 코드를 작성 아무런 장점이 없다 : 이것은 당신이 가질 수 있도록 당신이 질문-재정렬 지침에 제안 기본적으로 어떤이다. 그것은 단지 개인적인 선택의 문제이며, 어느 것이 더 명확하다고 생각합니다. 개인적

, I는 레지스터 설정 선호 제 (원래의 코드에서와 같이) 다음 ADD와 백투백 DAA을 실행. 왜? DAAADD 명령 (특히 보조 캐리 플래그, AF)에 의해 암시 적으로 설정된 플래그에 종속되기 때문에. MOV 명령어가 플래그를 훼손하지는 않지만 은 대부분 인스트럭션을 사용하므로 ADDDAA 명령어를 분리하는 습관을 가지면 찾기 힘든 버그가 발생할 위험이 있습니다.

이와 같은 명령을 재정렬하는 유일한 장점은 데이터 종속성을 완화하여 코드의 실행 속도를 높일 수 있다는 것입니다. 당신이 여전히이 세 가지 명령 사이에 끊어짐없는 종속성 체인을 가지고 있기 때문에 그것은 여기에서 일어나지 않을 것입니다.

+0

이 답변을 주셔서 감사 드리며 ALP에 대해 많은 것을 배울 수있었습니다. – vkubre

관련 문제