2011-08-28 4 views
0

간단한 고수준 어셈블리 프로그램이 있습니다. 여기에서 비트 이동 및 회전 기능을 배우고 있습니다. 나는이 간단한 프로그램을 가지고 비트를 한 바이트 씩 이동하면서 놀 수있다. 마지막 비트가 서명을 위해 예약으로 바이트 (127)에 설정되어캐리 플래그가 설정되지 않는 이유는 무엇입니까?

static 
var: int8 := 127; 

begin test1; 

stdout.put(var, nl); 
shl(1, var); 
stdout.put(var, nl); 
if (@C) then stdout.put("carry set"); endif; 
end test1; 

그것이

01111111. 번 왼쪽으로 시프트함으로써 반드시 있어야 캐리 플래그가 발생 하는가?

그러나 실제로는 모든 바이트가 왼쪽으로 한 번 이동하므로 바이트는 이제 11111110 또는 -2가됩니다.

이 문제가 매번 발생하면 어떤 조건으로 인해 carry 플래그가 설정됩니까?

플랫폼은 그대로는 부호 비트를 두지 않는 것입니다, 당신이 사용중인 이동 명령은 논리적 비트 쉬프터 것 같다 7 64 비트

+0

가능한 중복 ([조립 CF (캐리)와 (오버플로) 플래그의 약] http://stackoverflow.com/questions/791991/ about-assembly-cfcarry-and-ofoverflow-flag) – Amber

+0

"shift"가 의도 였다고 생각합니다. – WaelJ

+0

@paul, 죄송합니다. 지금 내 질문을 반영하도록 코드를 변경했습니다. –

답변

8

즉, 2 비트에 의해 왼쪽 시프트 할 필요가 다른 사람들은 실제로 carry 플래그가 설정되도록 127 칸을 2 칸 이동해야합니다. 하지만 여전히 효과가 없다고 말하는 것입니다. 여기에 대한 내 추측은 다음과 같습니다 :

저는 HLA와 그 라이브러리 함수에 익숙하지 않지만 어셈블리 작성시 일반적으로 라이브러리 함수를 호출하면 임의의 플래그가 변경 될 수 있다고 가정해야합니다 다른 방법으로 명시된 문서가없는 한. 많은 명령어가 플래그를 변경할 수 있으므로 라이브러리 함수를 사용하여 명시 적으로 플래그를 저장하고 종료 할 때 플래그를 저장하지 않는 한 (예 : pushfpopf 명령어로 스택에 저장하면) 모든 상태로 끝날 수 있습니다.

shl(2, var); /* I'm assuming you've already changed 1 to 2 here */ 
stdout.put(var, nl); 
if (@C) then stdout.put("carry set"); endif; 

내가 stdout.put이 플래그를 삭제되는 거라 생각 : 당신의 코드에서

, 당신은 shl와 캐리 플래그의 시험 사이의 stdout.put 라이브러리 루틴을 호출해야합니다.

그래서 이동 후 즉시 테스트를 넣어보십시오

shl(2, var); 
if (@C) then stdout.put("carry set", nl); endif; 
stdout.put(var, nl); 
+0

예, 완벽 했어요, 고마워요! –

0

승리입니다.

+0

아니요, 산술 시프트 왼쪽은 sal입니다.이 shl은 비 산술 시프트 명령어입니다. –

+0

@Jason Sill : 수정 됨. 감사합니다 – WaelJ

+0

@WaelJ : 설명서에'ras','las' 명령이 없습니다. – phoxis

1

은 (SAL) 좌측 및 논리 좌측 시프트 변속 산술 (SHL) 명령어는 동일한 동작을 수행 (x86 명령어에서 SAR 및 SAR)를 산술 시프트 명령을 찾는 시도; 대상 피연산자의 비트를 왼쪽으로 이동합니다 (보다 중요한 비트 위치 인 을 향해). 각각의 시프트 수를 들어, 대상 피연산자의 최상위 비트는 CF 플래그로 시프트되고, 최하위 비트는

시프트 연산 오른쪽 (SAR) 및 시프트를 해제 논리 오른쪽 (SHR) 명령어는 대상 피연산자의 비트 을 오른쪽으로 (덜 중요한 비트 위치로) 이동합니다. 각 시프트 수에 대해 대상 피연산자의 최하위 비트가 유형에 따라 CF 플래그로 시프트되고 최상위 비트가 설정되거나 지워집니다. SHR 명령은 최상위 비트를 지 웁니다 (그림 7-8의 인텔 ® 64 및 IA-32 아키텍처 소프트웨어 개발자 설명서, 볼륨 1). SAR 명령어는 대상 피연산자의 원래 값의 부호 (대부분 유효 비트)에 해당하는 최상위 비트를 설정하거나 지 웁니다. 결과적으로 SAR 명령은 빈 비트 위치의 시프트 값을 부호 변경되지 않은 부호 값으로 채 웁니다.

OF 플래그는 1 비트 시프트에서만 영향을받습니다. 왼쪽 쉬프트의 경우 결과의 최상위 비트가 CF 플래그와 같으면 OF 플래그가 0으로 설정됩니다 (즉 원래 피연산자의 상위 두 비트 이 동일 함). 그렇지 않으면 1로 설정됩니다. SAR 명령의 경우 OF 플래그는 모든 1- 비트 시프트에 대해 지워집니다. SHR 명령의 경우 OF 플래그는 원래 피연산자의 최상위 비트로 설정된 입니다.CF 플래그가 마지막 비트의 값을 또한 포함

대상 피연산자에서 시프트; 이 은 SHL 및 SHR 명령어의 경우 정의되지 않습니다. 여기서 카운트는 대상 오퍼랜드의 크기 (비트) 보다 크거나 같습니다. OF 플래그는 1 비트 시프트에서만 영향을받습니다 (위의 "설명"참조). 그렇지 않으면 정의되지 않습니다. SF, ZF 및 PF 플래그 이 결과에 따라 설정됩니다. 카운트가 0이면 플래그는 영향을받지 않습니다. 0이 아닌 의 경우 AF 플래그는 정의되지 않습니다. 여기

UPDATE 는 설명서가 지시하는 것이다. 만 동작 CF 설정과 시프트 용 루프 본체 도시되어

IF instruction is SAL or SHL 
    THEN 
     CF ← MSB(DEST); 

    ELSE (* Instruction is SAR or SHR *) 
     CF ← LSB(DEST); 
FI; 
IF instruction is SAL or SHL 
    THEN 
     DEST ← DEST ∗ 2; 
    ELSE 
     IF instruction is SAR 
      THEN 
       DEST ← DEST/2; (* Signed divide, rounding toward negative infinity *) 
      ELSE (* Instruction is SHR *) 
       DEST ← DEST/2 ; (* Unsigned divide *) 
     FI; 
FI; 
tempCOUNT ← tempCOUNT – 1; 

상기와 DEST = 01111111SHLCF = MSB (DEST) = 0 및 이진 11111110 2의 상보 표현 해석에 DEST = 127 * 2 = 254이다 DEST = DEST * 2 수에 따라 소수점에 -2 인 .

출처 : Intel 64 and IA32 Architectures Software Developer Manual Volume 2

+0

정말 도움이되지 않습니다. 붙여 넣은 첫 단락 (소스?)에서 가장 중요한 비트는 CF 플래그로 이동되어야합니다. 그러나 분명히 이것은 일어나지 않습니다. –

+0

'var'에'shr'을 적용하면 '01111111'에서'11111110'이됩니까? 모든 텍스트는 아래에 링크 된 소스의 사본입니다. – phoxis

+0

어셈블리뿐만 아니라 고급 어셈블리 언어를 사용하고 있음을 유의해야합니다. 따라서 carry 플래그는 127로 설정하면 안되지만 -2로 설정하면 안됩니까? 비트가 11111110이면 MSB가 1이므로 carry 플래그를 설정하지 않아야합니까? 위의 코드를 -2로 지정하여 var에 변경하면이 경우가 아닙니다. MSB가 1에 캐리 비트가 설정되어 있는지 여부에 관계없이 아무 작업도 수행하지 않습니다. –

1

가장 중요한 비트가 0 - 당신은 캐리 플래그에 1을 얻으려면 다음으로 이미 언급

shl(2, var); // [X] 01111111 -> [1] 11111100 
+0

내가 왼쪽으로 2 시프트하더라도, -4이면 캐리 비트가 설정되지 않습니다. –

관련 문제