x86 64 регистры rax/eax/ax / al перезапись полного содержимого регистра [дубликат]
этот вопрос уже есть ответ здесь:
как это широко рекламируется, современные процессоры x86_64 имеют 64-разрядные регистры, которые могут быть использованы в обратной совместимости как 32-разрядные регистры, 16-разрядные регистры и даже 8-битные регистры, например:
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
зарегистрироваться.
Итак, у меня есть 2 вопроса:
-
Я считаю, что это неудобное поведение должно быть задокументировано где-то, но я не могу найти подробного объяснения (как именно высокие 32 бита 64-битного регистра стираются) в любом месте. Я прав, что пишу
eax
всегда салфеткиrax
, или это что-то более сложное? Применяется ли он ко всем 64-разрядным регистрам, или есть некоторые исключения?сильно связанный вопрос упоминает то же самое поведение, но, увы, снова нет точных ссылок на документацию.
другими словами, Я хотел бы ссылку на документацию, которая определяет такое поведение.
-
это только у меня или вся эта история выглядит очень странно и нелогично (то есть еах-ах-ах-ал-Ракс-дя-а-а-Аль, имеющий одно поведение и Ракс-еах, имеющих другой)? Может я упускаю какой-то важный момент здесь, почему он был реализован таким образом?
объяснение "почему" было бы высоко оценено.
1 ответ:
модель процессора, описанная в руководстве по процессору Intel/AMD, является довольно несовершенной моделью для real двигатель исполнения современного ядра. В частности, понятие регистров процессора не соответствует действительности, нет такого понятия, как регистр EAX или RAX.
одной из основных задач декодера инструкций является преобразование устаревших инструкций x86 / x64 в micro-ops, инструкции RISC-подобного процессора. Небольшие инструкции, которые легки для того чтобы исполнить одновременно и мочь принять преимущество множественных подблоков исполнения. Позволяет одновременно выполнять до 6 инструкций.
чтобы сделать эту работу, понятие регистров процессора также виртуализируется. Декодер команд выделяет регистр из большого банка регистров. Когда инструкция пенсии, значение этого динамически выделенного регистра записывается обратно в любой регистр, который в настоящее время содержит значение ну, скажем, РАКС.
чтобы сделать эту работу плавной и эффективной, позволяя многим инструкциям выполняться одновременно, очень важно, чтобы эти операции не имели взаимозависимости. И самое худшее, что вы можете иметь, это то, что значение регистра зависит от других инструкций. Реестр EFLAGS печально известен, многие инструкции изменяют его.
такая же проблема с тем, как вы как его на работу. Большая проблема, она требует, чтобы два значения регистра были объединены когда инструкция будет удалена. Создание зависимости данных, которая будет засорять ядро. Заставляя верхний 32-бит равняться 0, эта зависимость мгновенно исчезает, больше не нужно сливаться. Скорость выполнения деформации 9.