2016-09-05 11 views
3

Intel набор инструкций ссылка дает нам addsd инструкцию:Intel VEX префикс L разрядное значение не ведет себя в соответствии с Документами

VEX.NDS.LIG.F2.0F.WIG 58 /r 
VADDSD xmm1, xmm2, xmm3/m64 

Как мы можем видеть, L бит игнорируется (может быть либо 0 или 1) ,

код Машина addsd XMM0, XMM0, XMM0: 0xC4, 0xE1, 0x7B, 0x58, 0xC0

C4 - indicates 3-byte VEX prefix 
E1 - R = 1; X = 1; B = 1; m-mmmm = 1 (implied 0F escape) 
7B - W = 0; vvvv = 1111 (xmm0); L = 0; pp = 11 (implied F2 prefix) 
58 - opcode byte 
C0 - mod-rm byte 

Давайте тест:

void exec(Byte* code, int size) 
{ 
    Byte* buf = (Byte*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 

    memcpy(buf, code, size); 

    buf[size] = 0xC3; 

    ((void (*)())buf)(); 

    VirtualFree(buf, 4096, MEM_DECOMMIT); 
} 

void f() 
{ 
    Byte code[] = { 0xC4, 0xE1, 0x7B, 0x58, 0xC0 }; 

    exec(code, sizeof(code)); 
} 

Fine, а также визуальная студия ассемблер распознает инструкцию.

Однако, когда я меняю L бит до 1 (0x7B заменен на 0x7F) дизассемблер не распознает инструкцию и генерируется исключение Invalid Instruction. Означает ли это, что бит L всегда должен быть 0, несмотря на руководство Intel?

+1

Если вы хотите проверить, что последовательности байтов являются действительными инструкциями, гораздо проще просто поместить их в '.asm' и собрать его, например' _start: db 0xC4, 0xE1, 0x7B, 0x58, 0xC0'. Затем вы просто собираете и запускаете его. Что еще более важно, дизассемблеры будут счастливо работать с вашими байтами, потому что они находятся в части вашего объектного файла, который должен содержать код. Похоже, ваш метод работает нормально; это просто сложно. –

+1

С Visual C++ вы также можете использовать '#pragma code_seg (". Text ")' и 'unsigned char const __declspec (выделить (". Text ")) код [] = {0xC4, 0xE1, 0x7B, 0x58, 0xC0, 0xC3}; 'С GCC вы можете просто использовать' unsigned char const __attribute __ ((раздел (". Text"))) code [] = {0xC4, 0xE1, 0x7B, 0x58, 0xC0, 0xC3}; '. –

+0

@PeterCordes: Знаете ли вы, что тег 'незаконной инструкции' прошел обгонку. Я замечаю, что @tkausl удалил его из всех вопросов. Я знаю, вы добавили его к вопросам в прошлом. –

ответ

2

Похоже, что LIG не означает, что бит L игнорируется; эта часть руководства неправильная. На практике это фактически синоним .LZ или .128 и средства L должен быть равен 0.

Вы правы, что insn иого руководство компании Intel (раздел 3.1.1.2 (Опкод Колонка в Instruction сводной таблицы (инструкции с префиксом VEX) тома 2 из x86 инструкций) противоречит наблюдаемому поведению:

Если VEX.LIG присутствует в столбце опкода:. значение VEX.L является игнорировалось Это обычно относится к Vex кодированного скалярной SIMD плавающей Указания по применению.

Однако это также противоречит другой документации в том же руководстве. В руководствах Intel есть случайные ошибки. :(Я думаю, вы можете сообщить об ошибке на форуме Intel.


Предположительно Intel изменила свое мнение об игнорировании немного, и решил сохранить кодировку L = 1 скалярных опкодов зарезервированных, но забыла обновить документацию для что VEX.LIG означает в секции insn-кодирования.

Они публикуют обновления для будущих расширений в справочном руководстве по установке insn, прежде чем они станут официальными, вероятно, до того, как будет завершена каждая деталь аппаратного дизайна. (Текущие дополнения будущего расширения pdf описывает инструкции AVX512 (находится в KNL) и несколько других расширений, которые еще не включены в официальное руководство или доступны в любом коммерчески доступном кремниевом AFAIK.) (Ссылки на документы Intel возраст и т. д., в теге ).


С insn исх руководство компании Intel, Fig2-9 VEX битовые поля:

L: Длина вектора

  1. скаляр или 128-битный вектор
  2. 256-битовые вектор

Раздел 2.3.6.2 объясняет то же самое.


Обратите внимание, что в некоторых инструкциях BMI1/2 используются кодировки VEX, также с L = 0. Похоже, что они указывают на это .Lz: VEX.NDS.LZ.0F38.W0 F2 /r is ANDN r32a, r32b, r/m32.

+0

Вы говорили о запуске asm-файла. Вы имеете в виду, что мне нужно экспортировать ярлык _start и перейти к этому адресу из программы C? – igntec

+0

@igntec: нет, '_start' является точкой входа для компоновщика по умолчанию. Таким образом, код в '_start' буквально является первой инструкцией, которую запускает ваша программа, нет кода запуска CRT или чего-то еще. В Windows я думаю, что вы можете 'ret' из' _start', потому что ОС помещает 'exit' в качестве обратного адреса в стеке. Установите контрольную точку в '_start', запустите свою программу и одношаговый. Однако, вероятно, проще определить 'main:' в asm. Я просто использовал для создания простых статических двоичных файлов в Linux для проверки тривиальных вещей, поэтому я склонен определять '_start'. связанные: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html. –

+0

Благодарим вас за ответ и ссылку. – igntec