2014-06-14 4 views
1

MOD + R/M 필드의 변위가 최대로 부호있는 32 비트 정수라는 것을 알고 있습니다. 그러나 32 비트 서명에 비해 너무 큰 값을 전달할 때 일관성없는 동작을 보았습니다 (그러나 부호없는 32 비트에 대해서는 충분히 작음). 포인트왜 AS가 때때로 대형 변위를 수용하고 때로는 그렇지 않습니까?

케이스 :

.intel_syntax noprefix 
mov [eax + eax + 0xdeadbeef], al 
mov [r10d + r10d + 0xdeadbeef], al 
mov [rax + rax + 0xdeadbeef], al 
mov [r10 + r10 + 0xdeadbeef], al 

내가 조립 (및 dissasamble) 때, 나는 다음과 같은 결과를 얻을 : 32 비트 레지스터는 볼 수 있듯이

0: 67 88 84 00 ef be ad mov BYTE PTR [eax+eax*1-0x21524111],al 
7: de 
8: 67 43 88 84 12 ef be mov BYTE PTR [r10d+r10d*1-0x21524111],al 
f: ad de 
11: 88 04 00    mov BYTE PTR [rax+rax*1],al 
14: 43 88 04 12    mov BYTE PTR [r10+r10*1],al 

(eax을, r10d) 32 비트 변위는 문자 그대로 (부호가있는 32 비트 정수로 해석되는) 취해지고 64 비트 레지스터 (rax, r10)의 경우 무시됩니다.

입력에 대한 합리적인 출력이라고 생각하지만이 일관성없는 처리의 이유는 즉시 알 수 없습니다. 이것이 어딘가에 기록되어 있습니까?

답변

3

인텔 구문 모듈의 버그 인 것으로 보입니다.

Error: 0xdeadbeef out range of signed 32bit displacement 

업데이트 :에

mov %al, 0xdeadbeef(%rax, %rax) 

결과 : 당신이 & t의 구문을 사용하는 경우이 오류 메시지가 발생 버그는 i386_finalize_displacement 호출 후 baseindex 플래그가 설정 될 수 있기 때문에 보이는 단지 설정된 경우 오류를 감지합니다. 간단한 수정은 이전에 설정된 플래그를 이동하는 것입니다. 나는 그 어떤 명백한 문제도 보지 않으며, 적어도이 문제를 고칩니다.

--- tc-i386-intel.c.orig  2012-01-16 04:06:06.000000000 +0100 
+++ tc-i386-intel.c  2014-06-14 16:13:31.238740524 +0200 
@@ -835,6 +835,9 @@ 
     memcpy (expP, &exp, sizeof(exp)); 
     resolve_expression (expP); 

+  if (intel_state.base || intel_state.index) 
+  i.types[this_operand].bitfield.baseindex = 1; 
+ 
     if (expP->X_op != O_constant 
      || expP->X_add_number 
      || (!intel_state.base 
@@ -882,9 +885,6 @@ 
      return 0; 
     } 

-  if (intel_state.base || intel_state.index) 
-  i.types[this_operand].bitfield.baseindex = 1; 
- 
     if (intel_state.seg) 
     { 
      for (;;)