если я выделяю память в сегменте данных инициализирую например регистр (xmm3) значением - 123 при помощи команды (fxsave) сохраняю данные инициализирую регистр (xmm3) уже значением - 456 потом восстанавливаю данные командой (fxrstor) Код (ASM): .data? wert db 1024 dup (?) .code mov eax,123 movd xmm3,eax fxsave wert mov eax,456 movd xmm3,eax fxrstor wert всё отлично восcтанавливается в регистре (xmm3) опять значение - 123 но если я вместо сегмента данных выделяю динамическую память из кучи Код (ASM): .data? buf dd ? .code invoke VirtualAlloc,0,1024,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE mov buf,eax mov eax,123 movd xmm3,eax fxsave buf mov eax,456 movd xmm3,eax fxrstor buf то в этом случае регистр (xmm3) не восcтанавливается и в нём значение даже не (456) а просто ноль почему в сегменте данных можно сохранить данные а в выделенной динамической памяти из кучи это не получается
Память не правильно выравнена. Попробуйте выделить из кучи больший кусок память и сохраните в нем значения по выравненному на 512 адресу. Хотя, возможно, достаточно и выравнивания на 64, но лезть уточнять не хочу. А в памяти осталось что-то про 512 с выравниванием для блока сохранения fxsave Хотя, судя по использованию VirtualAlloc, стоит проверить память на успешность её выделения. т.к. вы её выделяете не из кучи, а через пользовательский интерфейс страничного механизма работы с секциями памяти.
вроде бы нашёл подводный камень в принципи выравнивание достаточно на - 16 первый код где сохранение в сегменте данных по сути сработал чисто случайно видимо лексема уже была выровнена и чтобы исключить случайность лучше явно выровнить память Код (ASM): .data? align 16 wert db 512 dup (?) .code во втором коде оказывается тоже у лексемы в которой пропишется адрес памяти который не сомненно выровнен даже по размеру странице но вот оказывается этого мало и нужно было чтобы сама лексема инициализированная адресом памяти тоже бала бы выровнена по границе - 16 Код (ASM): .data? align 16 buf dd ? .code вроде бы заработало всем спасибо
В IA нет дереференсов ссылок, тоесть нет обращений в память по указателю на указатель. В Buf указатель(ссылка) на буфер, в инструкции fxsave [[buf]] две адресные предвыборки, а такого быть не может
оказывается даже если лексеме занести адрес динамической памяти и эту лексему поставить параметром - fxsave то сохранение не будет в динамической памяти а будет по адресу этой лексемы в сегменте данных а чтобы сохранение было в динамической памяти,то параметр этим командам нужно передовать наверное только косвенным указателем через регистр Код (ASM): .data? buf dd ? .code invoke VirtualAlloc,0,512,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE mov buf,eax mov eax,123 movd xmm3,eax mov eax,buf fxrstor [eax] ... mov eax,456 movd xmm3,eax ... mov eax,buf fxrstor [eax]
В параметрах инструкции линейный адрес: он вычисляется, проверяются права доступа, адресная трансляция и тд, это все предвыборка(prefetch). Затем уже выполняется выборка из памяти. Предвыборка может быть лишь одна для одного адреса. mov eax,buf тоесть mov r,[m] выборка указателя, затем вторая по этому указателю в fsave. mov eax,buf в ней адресация не явная, может быть это загрузка смещения или выборка по смещению, отсюда у тс путаница. Следует посмотреть режимы адресации IA sdm.
исправил ( в прошлый пост два раза прописал команду - fxrstor) Код (ASM): .data? buf dd ? .code invoke VirtualAlloc,0,512,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE mov buf,eax mov eax,123 movd xmm3,eax mov eax,buf fxsave [eax] ... mov eax,456 movd xmm3,eax ... mov eax,buf fxrstor [eax]
Небольшое уточнение -- если применять динамическую память, то именно выделенную функцией - VirtualAlloc так как она выделяет память по границе страницы, то есть точно выровненную по 16-байтной границе, а если например выделить память функцией - HeapAlloc, то гарантии нет что память будет выровнена по 16-байтной границе, а например по 8-байтной границе можно конечно адрес разделить на 16 и остаток прибавить к адресу, но это кому как нравиться