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레지스터 가 지워지는 것처럼 보입니다 .
그래서 두 가지 질문이 있습니다.
나는이 어색한 행동이 어딘가에 문서화되어야한다고 생각하지만 어디에서도 자세한 설명 (64 비트 레지스터의 정확히 32 비트가 지워지는 정도)을 찾을 수없는 것 같습니다.
eax항상 닦아내 는 글이 맞rax습니까, 아니면 더 복잡한 것입니까? 모든 64 비트 레지스터에 적용됩니까? 아니면 일부 예외가 있습니까?강하게 관련 질문은 슬프게도이 문서에 다시 더 정확한 참조가 같은 동작을 언급하지만.
즉,이 동작을 지정하는 문서에 대한 링크를 원합니다.
나만 아니면이 모든 것이 정말 이상하고 비논리적 인 것 같습니까 (즉, 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.
'program story' 카테고리의 다른 글
| PHP : __ ( 'Some text')는 무엇을합니까? (0) | 2020.11.12 |
|---|---|
| 큰 파이썬 프로젝트에서 죽은 코드 찾기 (0) | 2020.11.12 |
| 액세스 토큰 대 액세스 토큰 비밀 및 소비자 키 대 소비자 비밀이란 무엇입니까? (0) | 2020.11.12 |
| MySQL Workbench (6.3.9)가 MacOS High Sierra와 호환되지 않습니까? (0) | 2020.11.12 |
| 물체가 피클 가능 (또는 피클 가능)된다는 것은 무엇을 의미합니까? (0) | 2020.11.12 |