program story

x86_64는 전체 레지스터 내용을 덮어 쓰는 rax / eax / ax / al을 등록합니다.

inputbox 2020. 11. 12. 08:13
반응형

x86_64는 전체 레지스터 내용을 덮어 쓰는 rax / eax / ax / al을 등록합니다.


널리 알려진 바와 같이 최신 x86_64 프로세서에는 이전 버전과 호환되는 방식으로 32 비트 레지스터, 16 비트 레지스터 및 8 비트 레지스터로 사용할 수있는 64 비트 레지스터가 있습니다. 예를 들면 다음과 같습니다.

0x1122334455667788
  ================ rax (64 bits)
          ======== eax (32 bits)
              ====  ax (16 bits)
              ==    ah (8 bits)
                ==  al (8 bits)

이러한 방식은 문자 그대로 받아 들여질 수 있습니다. 즉, 읽기 또는 쓰기 목적으로 지정된 이름을 사용하여 항상 레지스터의 일부에만 액세스 할 수 있으며 매우 논리적입니다. 실제로 이것은 최대 32 비트의 모든 경우에 해당됩니다.

mov  eax, 0x11112222 ; eax = 0x11112222
mov  ax, 0x3333      ; eax = 0x11113333 (works, only low 16 bits changed)
mov  al, 0x44        ; eax = 0x11113344 (works, only low 8 bits changed)
mov  ah, 0x55        ; eax = 0x11115544 (works, only high 8 bits changed)
xor  ah, ah          ; eax = 0x11110044 (works, only high 8 bits cleared)
mov  eax, 0x11112222 ; eax = 0x11112222
xor  al, al          ; eax = 0x11112200 (works, only low 8 bits cleared)
mov  eax, 0x11112222 ; eax = 0x11112222
xor  ax, ax          ; eax = 0x11110000 (works, only low 16 bits cleared)

그러나 64 비트에 도달하자마자 상황이 상당히 어색해 보입니다.

mov  rax, 0x1111222233334444 ;           rax = 0x1111222233334444
mov  eax, 0x55556666         ; actual:   rax = 0x0000000055556666
                             ; expected: rax = 0x1111222255556666
                             ; upper 32 bits seem to be lost!
mov  rax, 0x1111222233334444 ;           rax = 0x1111222233334444
mov  ax, 0x7777              ;           rax = 0x1111222233337777 (works!)
mov  rax, 0x1111222233334444 ;           rax = 0x1111222233334444
xor  eax, eax                ; actual:   rax = 0x0000000000000000
                             ; expected: rax = 0x1111222200000000
                             ; again, it wiped whole register

그러한 행동은 나에게 매우 우스꽝스럽고 비논리적 인 것 같습니다. eax어떤 방법 으로든 아무것도 쓰려고하면 32 비트의 높은 rax레지스터 가 지워지는 것처럼 보입니다 .

그래서 두 가지 질문이 있습니다.

  1. 나는이 어색한 행동이 어딘가에 문서화되어야한다고 생각하지만 어디에서도 자세한 설명 (64 비트 레지스터의 정확히 32 비트가 지워지는 정도)을 찾을 수없는 것 같습니다. eax항상 닦아내 는 글이 맞 rax습니까, 아니면 더 복잡한 것입니까? 모든 64 비트 레지스터에 적용됩니까? 아니면 일부 예외가 있습니까?

    강하게 관련 질문은 슬프게도이 문서에 다시 더 정확한 참조가 같은 동작을 언급하지만.

    즉,이 동작을 지정하는 문서에 대한 링크를 원합니다.

  2. 나만 아니면이 모든 것이 정말 이상하고 비논리적 인 것 같습니까 (즉, eax-ax-ah-al, rax-ax-ah-al은 한 가지 행동을하고 rax-eax는 다른 행동을하는 것)? 왜 그렇게 구현되었는지에 대한 중요한 요점이 누락되었을 수 있습니까?

    "왜"에 대한 설명은 높이 평가 될 것입니다.


인텔 / AMD 프로세서 매뉴얼에 문서화 된 프로세서 모델 은 현대 코어 실제 실행 엔진에 대해 매우 불완전한 모델입니다 . 특히 프로세서 레지스터의 개념은 현실과 일치하지 않으며 EAX 또는 RAX 레지스터와 같은 것은 없습니다.

One primary job of the instruction decoder is to convert the legacy x86/x64 instructions into micro-ops, instructions of a RISC-like processor. Small instructions that are easy to execute concurrently and being able to take advantage of multiple execution sub-units. Allowing as many as 6 instructions to execute at the same time.

To make that work, the notion of processor registers is virtualized as well. The instruction decoder allocates a register from a big bank of registers. When the instruction is retired, the value of that dynamically allocated register is written back to whatever register currently holds the value of, say, RAX.

To make that work smoothly and efficiently, allowing many instructions to execute concurrently, it is very important that these operations don't have an interdependency. And the worst kind you can have is that the register value depends on other instructions. The EFLAGS register is notorious, many instructions modify it.

Same problem with the way you like it to work. Big problem, it requires two register values to be merged when the instruction is retired. Creating a data dependency that's going to clog up the core. By forcing the upper 32-bit to 0, that dependency instantly disappears, no longer a need to merge. Warp 9 execution speed.

참고URL : https://stackoverflow.com/questions/25455447/x86-64-registers-rax-eax-ax-al-overwriting-full-register-contents

반응형