Вычисление эффективных адресов в 64-разрядном режиме

Тема в разделе "WASM.X64", создана пользователем SII, 31 янв 2010.

  1. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Сел детально разбираться с кодированием команд IA-32 во всех режимах. Само кодирование понятно, однако возник попутный вопрос: а какова разрядность регистров, участвующих в вычислении эффективного адреса в 64-разрядном режиме? Казалось бы, полный ответ на этот вопрос даёт первый том Интеловского руководства:

    Как явствует из этой цитаты, если префикс REX отсутствует или его бит W равен нулю (т.е. если используется 16- или 32-разрядный размер операндов), для вычисления адреса используется содержимое 32-разрядных регистров, и лишь при REX.W=1 применяются полные 64-разрядные регистры -- т.е. размер регистров, используемых для _адресации_, зависит от размера _операнда_. Однако это вызывает недоумение:

    1) получается, что невозможно что-либо сделать со словом или двойным словом, находящимся в памяти, для обращения к которой необходимо использовать 64-разрядный регистр, поскольку для 64-разрядной адресации необходимо установить бит REX.W, а для обработки 16- или 32-разрядных операндов этот бит должен быть сброшен;

    2) в 64-разрядном режиме разрядность данных по умолчанию равна 32 битам (именно поэтому для обработки 64-разрядных величин нужен префикс REX с установленным битом W), однако размер эффективного адреса по умолчанию равен 64 битам и меняется на 32 бита только с помощью префикса изменения размера адреса 67h (об этом прямо говорится в документации AMD; документация Intel обходит этот вопрос молчанием):

    3) наконец, ни в документации AMD, ни в документации Intel не упоминается о том, что префикс REX используется для изменения размера регистров, используемых для вычисления адреса, там говорится исключительно о размере операнда.

    В общем, всё это наводит на мысль, что приведённая в начале поста цитата из интеловского мануала содержит ошибку, и на самом деле для вычисления эффективного адреса по умолчанию используются 64-разрядные регистры независимо от размера операнда, и лишь при наличии префикса 67h используются 32-разрядные регистры. Но хотелось бы узнать, что по этому поводу думают другие и проверял ли кто это на практике?
     
  2. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Именно так. REX используется только для доступа к новым регистрам (р8-р15), т.е. используются только REX.B/R/X. W влияет исключительно на размер операнда. С самим же размером операнда есть нюанс в случае команд, неявно использующих xSP и near-branch (push/pop, retn, call/jmp near и пр.) - там по умолчанию размер операнда 64 бита (рекс не нужен), 66h переключает в 16 бит, 32 бита не кодируются.

    зы В интеловских манах такие принципиальные (!) ошибки вообще можно мешками грузить.
     
  3. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Vic3Dexe
    Спасибо. Я тоже был уверен, что это ошибка, но... Полума хорошо, а полтора -- лучше, как известно :)

    А что качество ещё то, это я в курсе. И если откровенных ошибок всё ж не слишком много, то просто неясностей и т.п. -- пруд пруди.

    Кстати говоря, изложил свои изыскания по поводу кодирования команд вот здесь: http://ru.osdev.wikia.com/wiki/Кодирование_команд. Если вдруг кого туда занесёт и он обнаружит неточности, ошибки и т.д., буду благодарен за замечания и исправления :)
     
  4. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    SII
    А можешь рассказать как кодируют команды сопроцессора и SSE а то не очень понятно как они кодируются. Какиет-о там последние числа из байта опкода отводятся под них. Особенно в том плане что там в опкод может входить байт 66h и 67h - и это будет не префикс, а именно опкод.
     
  5. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Pavia
    67h в SSE командах не используется. Там используются 66, F2, F3. Отличие их от обычных префиксов в том, что в некоторых SSE командах одновременное присутствие 66 и Fx недопустимо и вызывает исключение, а вот из F2/F3 действует последний как в строковых командах. А процессоры без SSE-расширений, у которых есть только MMX, префиксы Fx игнорировали. А код команды в последнем байте это чаще всего встречается в 3DNow, хотя может там сейчас и другие команды поселились.
     
  6. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    По
    навскидку:

    1. AMD выделяет F0 в отдельную группу, и считает, что групп 5, а не 4. Реально, их все равно 4, т.к. ни одна команда, принимающая lock, не принимает rep/repne и наоборот, так что их можно считать взаимоисключающими (что, видимо, и сделала интел).
    2. lock в тех случаях, где его юзать нельзя приводит к #UD, а не игнорируется.
    3. "отклонение" я бы переименовал в более привычное "смещение", а то воспринимается как отклонение от нормы =)
    4. Ну и общая грамматика, местами глюки типа
     
  7. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    2Pavia
    В SSE черт ногу сломит. Закономерностей очень мало, костыль - он костыль и есть.

    addps 0F 58
    addpd 66 0F 58
    addss F3 0F 58
    addsd F2 0F 58

    Вот тут 66/F2/F3 - именно часть опкода, ни о каких 16 битах или rep/repne речи нет. REX, если он есть должен стоять перед 0F, т.е.

    addss F3 4x 0F 58

    хотя F3 по-прежнему считается опкодом
     
  8. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Pavia
    66h там будет всё равно префиксом, но префиксом обязательным, т.е. де-факто это часть кода операции (поскольку без префикса получается совсем другая операция или вообще никакая не получается), хотя де-юре префикс (а посему может быть отделён от собственно кода операции префиксом REX).

    Специально же никакими группами команд я пока не занимался, ограничился лишь общим форматом кодирования, поэтому никаких "интимных" подробностей про SSE не сообщу. Когда дойдут руки, займусь в т.ч. и ими, но это нескоро будет, поскольку практической нужды пока нет (а вот в общем кодировании разобраться было нужно).

    Vic3Dexe
    1. Я писал по интелу, потому и групп 4. В принципе, можно будет отметить, что АМД выделяет 5 групп.
    2. Вроде интел об этом не упоминает, надо дополнить будет.
    3. "Отклонение" я использовал, поскольку смещение -- это offset, т.е. вторая часть логического адреса (первая -- селектор сегмента), ну а displacement не является частью логического адреса, а используется для вычисления смещения. Использовать одинаковое слово не хотелось бы из-за возможности смешивания, а ничего более удачного я не придумал.
    4. Угу, глаз замыливается, уже не видишь очевидных ляпов. Отдохну и попробую вычитать-исправить.
     
  9. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    SII
    2. Упоминает в описании самой LOCK (в списке команд).
     
  10. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Black_mirror
    Именно вызывает исключение? Насколько я понимаю, x86 вообще лояльно отностися к невлияющим на инструкцию префиксам, просто игнорируя их (за исключением специально оговоренных случаев).
     
  11. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Vic3Dexe
    Посмотрел доку: там говорится, что использование LOCK с непредусмотренными для него инструкциями (или с предусмотренными, но приёмником которых является не память) _может_ привести к #UD -- но не _обязано_ приводить. Отметил это обстоятельство на Вике.
     
  12. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Не всегда лояльно.Rep emms тому пример, хоят как бы реп здесь и не причем, однако UD
     
  13. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    В осдевовской вике, хтати, коррективы всякие внёс. Но, если кто будет мои бредни там читать, по-прежнему просьба сообщать о всех ляпах, что найдутся :)

    medstrax1
    Коды репов (F2 и F3) в ряде команд же используются как обязательные префиксы (де-факто части кода операции), так что, может, из-за этого крышу и рвёт...
     
  14. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Хз из за чего рвет. Emms ничем не выделяется среди других, однако на rep'e сносит башню только ей. На прочих командах не увидел влияния репа
     
  15. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Тож перечитал. Там еще тоньше:
    1. С любой левой инструкцией - #UD однозначно (и в тексте, и в списке эксепшенов, у АМД тож самое).
    2. С правильной инструкцией, но с операндом-приемником НЕ памятью - может привести (у АМД не нашел об этом).
    А вообще, конечно, не суть важны такие тонкости. Все равно в lock с операндом не-памятью смысла ноль.