#include <iostream>
int main()
{
char *dataptr = new char[33];
char datalocal[33];
dataptr[0] = 'a'; dataptr[1] = 0;
datalocal[0] = 'a'; datalocal[1] = 0;
printf("%p %p %c\n", dataptr, &dataptr, dataptr[0]);
printf("%p %p %c\n", datalocal, &datalocal, datalocal[0]);
delete[] dataptr;
}
Выход:
0xd38050 0x7635bd709448 a
0x7635bd709450 0x7635bd709450 a
Как мы можем видеть, динамический указатель data
действительно переменная указатель (32 бит или 64 бит в 0x7635BD709448
), содержащий указатель на кучу, 0xD38050
.
Локальная переменная - это буфер длиной 33 символа, выделенный по адресу 0x7635BD709450
.
Но datalocal
работает также как значение char *
.
Я немного смущен, что формальное объяснение этого С ++.При написании кода на C++ это кажется вполне естественным, и dataptr [0] - первый элемент в кучевой памяти (т. Е. Разыменование dataptr дважды), но в ассемблере вы видите истинный характер dataptr
, который является адресом переменной указателя. Таким образом, вы должны сначала загрузить указатель кучи на mov eax,[data]
= загружает eax
с 0xD38050
, а затем вы можете загрузить содержимое 0xD38050
в XMM0, используя [eax]
.
С локальной переменной нет переменной с ее адресом; символ datalocal
уже является адресом первого элемента, поэтому тогда будет работать movdqu xmm0,[data]
.
В «неправильном» случае вы все еще можете сделать movdqu xmm0,[data]
; это не проблема CPU для загрузки 128 бит из 32-битной переменной. Он просто продолжит чтение за 32 бита и прочитает еще 96 бит, принадлежащих другим переменным/кодом. Если вы находитесь вокруг границы памяти, и это последняя страница памяти приложения, она выйдет из строя с недопустимым доступом.
Выравнивание упоминалось несколько раз в комментариях. Это действительная точка; для доступа к памяти через movdqu
он должен быть выровнен. Проверьте свои встроенные компиляторы C++. Для Visual Studio это должно работать:
__declspec(align(16)) char datalocal[33];
char *dataptr = _aligned_malloc(33, 16);
_aligned_free(dataptr);
О моей интерпретации C++: Может быть, я получил это неправильно с самого начала.
dataptr
- это значение символа dataptr, то есть этого адреса кучи. Затем dataptr[0]
разыменовывает адрес кучи, обращаясь к первому элементу выделенной памяти. &dataptr
- это адрес значения dataptr
. Это имеет смысл также с синтаксисом, например dataptr = nullptr;
, где вы храните значение nullptr в переменной dataptr, а не переписываете адрес символа dataptr.
С datalocal[]
нет в принципе нет смысла в получении доступа к чистой datalocal
, как в datalocal = 'a';
, так как это переменная массива, так что вы всегда должны обеспечить индекс []
. И &datalocal
- это адрес такого массива. Чистый datalocal
- это сглаженный ярлык для более простой математики точек с массивами и т. Д., Также имеющий тип char *
, но если чистый datalocal
будет вызывать синтаксическую ошибку, все же можно будет написать код C++ (используя &datalocal
для указателя, datalocal[..]
для элементов), и это полностью соответствовало бы логике dataptr
.
Заключение: У вас ваш пример неправильно с самого начала, потому что на языке ассемблера [data]
загружается значение data
, который является указателем на куче возвращенного new
.
Это мое собственное объяснение, и теперь эксперт некоторыхов C++ придет и разорвать его на куски с формальной точки зрения ... :)))
Обратите внимание, что 'data' является указателем. –
Можете ли вы попробовать, если локальная переменная 'char data [33];' вместо нового/delete с указателем может использоваться напрямую, как в исходном сообщении с '[data]'? Я не могу отлаживать сейчас, но я думаю, что это может сработать, поскольку я могу представить скомпилированный источник. Что меня озадачивает, какова разница на C++ от 'char * data'. С точки зрения C++ они выглядят эквивалентными. Я, вероятно, что-то пропускаю. (и в этой второй версии, что 'mov eax, data' скомпилирован в' mov eax, [data] ', right?) – Ped7g
x86 не имеет режима« косвенной адресации »памяти. Вы загружаете указатель в 'xmm0'. Поскольку 'xmm0' больше, чем указатель, вы также читаете байты мусора в памяти за пределами того места, где хранится указатель. –