powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / K&R 5.5 Указатели символов и функции. Корректен ли код ?
25 сообщений из 66, страница 2 из 3
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545701
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyА мне слету понятна конструкция "while (*s++ = *t++)" а в вашу надо вдумываться чтоб понять.
Добавь после скольки лет писания на Си "слету понятна". А теперь задумайся захочет ли кто-то с гораздо меньшим опытом после тебя что-то дописывать. Сомневаюсь.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545707
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

вот не надо.
Захочет, и рад будет.
Я вот и хотел добавить в предыдущем посте, что " за это мы и любим наш родной язык С ".
А всякие лошары пусть идут и колупаются в своей яве.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545710
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyА мне слету понятна конструкция "while (*s++ = *t++)" а в вашу надо вдумываться чтоб понять.
Так что не надо ту про читаемость :)

Ну просто таки не могу удержаться :
Anatoly MoskovskyА вообще меня всегда поражало, как люди мучают себя и других используя такие конструкции

Код: plaintext
1.
std::for_each(begin, end,  /*что-то невообразимо плохо читаемое и понимаемое*/);

вместо того чтобы написать

Код: plaintext
1.
2.
3.
for(i = begin; i != end; ++ i) {
   // простой и понятный код
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545712
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivА всякие лошары пусть идут и колупаются в своей яве.
Лошары колупаются в 1С, и им за это очень даже неплохо платят. При этом им невозможно объяснить как настроить запуск проги из планировщика, но владельцам бизнеса рекомедую обратится именно к ним, т.к. эти лошары легко заменяемы, в отличии от гениальных писателей вместе с уходом которых умирает проект и приносит бизнесу гораздо большие финансовые потери.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545713
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyDima TДа, это длинно и нудно, но зато понятно всем, даже тем кто мало знаком с Си.

А мне слету понятна конструкция "while (*s++ = *t++)" а в вашу надо вдумываться чтоб понять.
Так что не надо ту про читаемость :)

ЗЫ. Есть такое понятие идиома. Это то что новичек не знает, а опытные понимают с полслова.
"*s++ = *t++" - это идиома, ее не надо перефразировать.

Да мало этого, это просто классика, с которой начинается любая книжка по С.
Да, она тупая и наивная, но она показывает очень хорошо дух языка -- мощь в каждом символе.
С -- хакерский язык, и Unix была хакерская система. Для красноглазиков. Для хакеров. Для мозготрясов.
С -- это ассемблер PDP-11, думающий, что он -- язык высокого уровня.
Но он собственно и поднял IT cо дна вычислительного болота, где ученые только молотили всякие модели самолётов и ядерных взрывов. Ну, конечно, не всё определялось только созданием С, но это определённо была веха в развитии IT, программы стали переносимыми хоть как-то, это великая вещь.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545715
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНо он собственно и поднял IT cо дна вычислительного болота, где ученые только молотили всякие модели ...
... модели того как бороздят космические корабли просторы вселенной (с)

Ну чего это за самовозбуждение лозунгами? Есть простой факт: программист это обслуживающий персонал, не уборщица, но и не производитель добавленной стоимости, с этим надо смириться и учитывать это в процессе своего творчества.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545723
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MozokНу просто таки не могу удержаться:
Anatoly MoskovskyА вообще меня всегда поражало, как люди мучают себя и других используя такие конструкции

Код: plaintext
1.
std::for_each(begin, end,  /*что-то невообразимо плохо читаемое и понимаемое*/);


вместо того чтобы написать

Код: plaintext
1.
2.
3.
for(i = begin; i != end; ++ i) {
   // простой и понятный код
}



Не вижу противоречия.

Это идиома:
Код: plaintext
1.
std::for_each(begin, end, 



А это
Код: plaintext
1.
/*что-то невообразимо плохо читаемое и понимаемое*/

это обычно никому не нужная мутотеть, потому что применяют идиому не к месту.

Вот оттуда же:
Код: plaintext
1.
std::for_each(entityStorage.begin(), entityStorage.end(),  boost::bind(&MyEntityManager::foo, this, _1));


Ну и нахрена так писать когда можно так:
Код: plaintext
1.
2.
3.
for(i = begin; i != end; ++ i) {
  foo(entityStorage[i]);
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545733
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот этот пример нагляднее
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
std::for_each(sessions_.begin(), sessions_.end(), 
    boost::bind(&client_session::stop, 
        boost::bind(&session_map_t::value_type::second, _1)
    )
);
                    
// и то же самое                    
BOOST_FOREACH(session_map_t::value_type& i, sessions_) {
    i.second->stop();
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545751
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TAnatoly MoskovskyА мне слету понятна конструкция "while (*s++ = *t++)" а в вашу надо вдумываться чтоб понять.Добавь после скольки лет писания на Си "слету понятна".сразу. Именно она меня и покорила, в своё время ))
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545753
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TНу чего это за самовозбуждение лозунгами? Есть простой факт: программист это обслуживающий персонал, не уборщица, но и не производитель добавленной стоимости, с этим надо смириться и учитывать это в процессе своего творчества.ну чего это за самовозбуждение баналами? (с) Ты правда считаешь, что ты открыл нам правду наконец то?
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38545756
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivDima T,

вот не надо.
Захочет, и рад будет.
Я вот и хотел добавить в предыдущем посте, что " за это мы и любим наш родной язык С ".
А всякие лошары пусть идут и колупаются в своей яве.+1 ))
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38546727
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.
Буду опускать регистр в дальнейшем. Я понял.

MasterZivдолжно быть

char* strcpy_test(char* to, const char* from)




Почему значение передатчика должно быть константным ?

По поводу
Код: plaintext
1.
while(*s++=*t++)


.
а) Конструкция, может быть, и применима, но не в этом примере.
б)За счёт того что я написал её именно так, а не более развёрнуто, выиграл ли я в скорости выполнения программы ?(хотя бы на 10^(-100) секунды) ?

Dima_T
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
char *strcpy(char *s, const char *t)
{
  *s = *t;
   while (*s != 0)
   {
        s++;
        t++;
        *s = *t;
   }
  return s;
}


Да, это длинно и нудно, но зато понятно всем, даже тем кто мало знаком с Си.


По-моему отличный код, ничего нудного. Я не считаю что он простой или нудный.
Думаю, что при разработке программного обеспечения в каких-либо системах реального времени, или для спутников, используются именно такие чёткие конструкции.
f e:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int A()
{
smth do...
}
int B()
{
smth do...
}

int temp=A()+B();//Мы не знаем какая функция вернёт значение первой, А или Б (согласно K&R), однако порой это важно знать.



Два этих примера не идентичны, безусловно. Но мне кажется меня поймут
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38546744
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В этой же главе приведён пример лексикографического сравнения:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
int strcmpr_test(char* s, char* t) //должен ли тут быть const ?
{
	for (; *s == *t; s++, t++) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */
	{
		if (*s == '\0')
		{
			return 0;
		}
	}
	return(*s - *t);
}



Исходя из логики программы, на выходе
Код: plaintext
1.
2.
3.
	char* a = "abc";
	char* b = "a";
	printf("%i", strcmpr_test(a, b));



будет число 98 (ASCII символ b), что неверное. Программа не учитывает все варианты, нужно добавить проверку на *b=='\0'. И то программа будет не полной.
Переписал. Проверьте пожалуйста

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
int strcmpr_test(char* s, char* t) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */
{//должны ли быть const?
	while (*s++ == *t++) //А вот в данной функции, код обсуждавшийся выше очень даже подходит
	{
		if (*++s == '\0' && *++t != '\0')
		{
			return 1;
		}
		else if (*++t == '\0' && *++s != '\0')
		{
			return -1;
		}
	}
	return 0;
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38546747
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашёл у себя отличную ошибку !! Код должен быть такой, вероятно


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
int strcmpr_test(char* s, char* t) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */
{//должны ли быть const?
	while (*s++ == *t++)
	{
		if (*s == '\0' && *t != '\0')
		{
			return 1;
		}
		else if (*t == '\0' && *s != '\0')
		{
			return -1;
		}
		else if (*t == '\0' && *s == '\0')
		{
			return 0;
		}
	}
	return 0;
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38546750
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
int strcmpr_test(char* s, char* t) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */
{//должны ли быть const?
	while (*s++ == *t++) //А вот в данной функции, код обсуждавшийся выше очень даже подходит
	{
		 if (*++s == '\0' && *++t != '\0')  /*инкрементирую лишний раз, строчкой выше после того как взял значение указателя, сделал инкремент ведь */
		{
			return 1;
		}
		else if (*++t == '\0' && *++s != '\0') такая же ошибка
		{
			return -1;
		}
	}
	return 0;
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38546765
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryдолжны ли быть const?
const при передаче указателя в параметрах означает что внутри твоей функции не происходит изменения данных по адресу указателя. Т.е. вызывающая программа может быть уверена что никаких изменений в ее данных не произойдет.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
int f(char* s)
{
  *s = 0; // скомпилируется
   return 0;
}

int fс(const char* s)
{
  *s = 0; // не скомпилируется
   return 0;
}
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38546807
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TMasterZivА всякие лошары пусть идут и колупаются в своей яве.
Лошары колупаются в 1С, и им за это очень даже неплохо платят. При этом им невозможно объяснить как настроить запуск проги из планировщика, но владельцам бизнеса рекомедую обратится именно к ним, т.к. эти лошары легко заменяемы, в отличии от гениальных писателей вместе с уходом которых умирает проект и приносит бизнесу гораздо большие финансовые потери.

если бы эти гениальные писатели не написали 1с , на с++ между прочим, то тем лошарам просто нечего было бы есть...
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38547120
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryб)За счёт того что я написал её именно так, а не более развёрнуто, выиграл ли я в скорости выполнения программы ?(хотя бы на 10^(-100) секунды) ?
Все зависит от компилятора, как именно от откомпилирует. Посмотрел у себя во что реально превращается оба варианта - вижу примерно одно и тоже с незначительными отличиями.
Можно просто взять и померить
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
#define TEST_COUNT 100000000

char* f1(char* s, char *t)
{
	while(*s++=*t++);
	return s;
}

char* f2(char* s, char *t)
{
	*s = *t;
	while (*s != 0)
	{
		s++;
		t++;
		*s = *t;
	};
	return s;
}

int main(int argc,char **argv){
	char* v = "1234567890";
	char buf[256];
	
	unsigned int i, iEnd1, iEnd2, iEnd3, iStart;
	iStart = GetTickCount();
	for(i = 1; i < TEST_COUNT; i++) f1(buf, v);
	iEnd1 = GetTickCount() - iStart;
	iStart = GetTickCount();
	for(i = 1; i < TEST_COUNT; i++) f2(buf, v);
	iEnd2 = GetTickCount() - iStart;
	iStart = GetTickCount();
	for(i = 1; i < TEST_COUNT; i++) strcpy(buf, v);
	iEnd3 = GetTickCount() - iStart;
	printf("f1() %d ms  f2() %d ms  strcpy() = %d ms\n", iEnd1, iEnd2, iEnd3);
	return 0;
}


Результаты у меняВ дебагe
f1() 3478 ms f2() 3604 ms strcpy() = 608 ms
f1() 3494 ms f2() 3589 ms strcpy() = 608 ms
f1() 3495 ms f2() 3588 ms strcpy() = 608 ms
f1() 3495 ms f2() 3588 ms strcpy() = 608 ms
f1() 3494 ms f2() 3588 ms strcpy() = 608 ms

В релизе
f1() 858 ms f2() 827 ms strcpy() = 2808 ms
f1() 858 ms f2() 827 ms strcpy() = 2808 ms
f1() 843 ms f2() 842 ms strcpy() = 2808 ms
f1() 842 ms f2() 842 ms strcpy() = 2808 ms
f1() 843 ms f2() 826 ms strcpy() = 2808 ms

Т.е. получилось что компактно написанное чуть быстрее в дебаге и чуть медленнее в релизе. И очень странный результат у strcpy(), который стал в 4,5 раза медленнее работать в релизе. Всегда думал что быстрее всего работают родные функции Си, а тут задумался.

Все зависит от компилятора. Повтори на своем компиляторе. Может другие результаты будут.

Offtop 2 MasterZivMasterZivесли бы эти гениальные писатели не написали 1с , на с++ между прочим, то тем лошарам просто нечего было бы есть...

Какое-то странное трактование причинно-следственных связей. Не знаю как это прокомментировать.

Что касается причин успеха 1С, то они совсем в другой плоскости, гениальность писателей я бы не ставил на первое место. Да и гениальность под вопросом. Чего только стоит реализация блокировок таблиц в DBFной 1С77, когда ожидающий блокировки процесс в бесконечном цикле пытается заблокировать файл, если все это происходит локально в терминале, то вместо ожидания получается что он отжирает процессорное время у того кто эту блокировку держит, если дальше пытаются получить блокировку другие пользователи, то падал терминал при 4-5 ожидающих. А лечилось в итоге это достаточно просто: грязным хаком патчилась 1С.DLL, где в цикл блокировки вставлялся вызов Sleep(0).

PS MasterZiv, предлагаю подтему про гениальность закрыть. Мир.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38547348
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dina_T, спасибо C:
Завтра обязательно проверю все, уже пора спать
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38547375
S
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
S
Гость
Dima_T*
Извините(((, это автозамена HTC (((
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38548094
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
f1() 9548ms f2() 9469ms strcpy_s() = 17940ms
Данные релиза не удалось получить, к сожалению
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38548157
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryf1() 9548ms f2() 9469ms strcpy_s() = 17940ms
Данные релиза не удалось получить, к сожалению
По большому счету неважно, т.к. подобными улучшениями много не выиграешь, а времени кучу потратишь на замеры. Но иногда этим заниматься стоит, т.к. бывает что думаешь используешь самый быстрый вариант, а он оказывается чуть ли не самый тормозной.
Гораздо полезнее знать алгоритмы увеличивающие производительность. Например можно каждый раз перебирать массив для поиска нужного элемента, а можно отсортировать его и использовать алгоритм двоичного поиска.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38549572
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima_TПо большому счету неважно, т.к. подобными улучшениями много не выиграешь, а времени кучу потратишь на замеры. Но иногда этим заниматься стоит, т.к. бывает что думаешь используешь самый быстрый вариант, а он оказывается чуть ли не самый тормозной.
Гораздо полезнее знать алгоритмы увеличивающие производительность. Например можно каждый раз перебирать массив для поиска нужного элемента, а можно отсортировать его и использовать алгоритм двоичного поиска.

согласен.

Вчера вечером понял, мы, скорее всего, неправильно отнеслись к сравнению скорости выполнения данного кода. Процессор обрабатывает команды не только нашей программы, но и других. А если и проводить такое тестирование, то наверное в ОСРВ.

И вот ещё. Например у нас есть алгоритм поиска. Мы, в теории, можем рассчитать сложность алгоритма. Количество итераций. Тут аналогично. Мне кажется, нужно посмотреть как наш код выглядит на машинном языке, после всех трансляций, и оценить стоимость каждой операции по времени. Ну опять таки, это нужно делать в ОСРВ. Насколько я помню, только там мы можем говорить о гарантированном времени для каждой операции процессора
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38549679
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryВчера вечером понял, мы, скорее всего, неправильно отнеслись к сравнению скорости выполнения данного кода.
Процессор обрабатывает команды не только нашей программы, но и других. А если и проводить такое тестирование, то наверное в ОСРВ.
Я это учитываю в подобных замерах. Запускаю на ненагруженном компе (когда параллельно ничего не считается). Потом пятикратный запуск. Можно еще приоритет процесса повысить до максимального, но это лишнее, т.к. в итоге работать будет в обычном режиме.

SashaMercuryМне кажется, нужно посмотреть как наш код выглядит на машинном языке, после всех трансляций, и оценить стоимость каждой операции по времени. Ну опять таки, это нужно делать в ОСРВ. Насколько я помню, только там мы можем говорить о гарантированном времени для каждой операции процессора
Тут на асме этот пример вчера выложил, по сути в машинных кодах. Код после компиляции почти одинаковый получился.
Только для современных процессоров нельзя говорить о гарантированном времени выполнения конкретной команды, там слишком много оптимизации: кэши, распараллеливание, конвееры с предсказанием результата и т.д.
...
Рейтинг: 0 / 0
K&R 5.5 Указатели символов и функции. Корректен ли код ?
    #38551355
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T Тут на асме этот пример вчера выложил, по сути в машинных кодах. Код после компиляции почти одинаковый получился.ИМХО реализация библиотечной strcpy от while(*s++=*t++) должна сильно отличаться. На асме эффективный по быстродействию код совсем другой.
У Agner Fog ( http://www.agner.org) интересная реализация:
strcpy
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
; Function entry:
_A_strcpy PROC    NEAR
?OVR_strcpy LABEL NEAR

        mov     eax, [esp+8]           ; src
        push    eax
        call    _A_strlen              ; length of src
        pop     ecx                    ; ecx = src. Assume unchanged by _A_strlen
        inc     eax                    ; include terminating zero in length
        mov     edx, [esp+4]           ; dest
        push    eax                    ; length+1
        push    ecx                    ; src
        push    edx                    ; dest
        call    _A_memcpy              ; copy
        add     esp, 12                ; clean up stack
        ret

_A_strcpy ENDP


memcpy
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
; extern "C" void * A_memcpy(void * dest, const void * src, size_t count);
; Function entry:
_A_memcpy PROC    NEAR
?OVR_memcpy LABEL NEAR
        push    esi
        push    edi
        mov     edi, [esp+12]          ; dest
        mov     esi, [esp+16]          ; src
        mov     ecx, [esp+20]          ; count
$memcpyEntry2 label near               ; Entry from memmove

IFNDEF  POSITIONINDEPENDENT
        jmp     [memcpyDispatch]       ; Go to appropriate version, depending on instruction set
RP      equ     0                      ; RP = 0 if not position-independent

ELSE    ; Position-independent code

        push    ebx
        call    get_thunk_ebx          ; get reference point for position-independent code
RP:                                    ; reference point ebx = offset RP
A020:                                  ; Go here after CPU dispatching

; Make the following instruction with address relative to RP:
; cmp [ebx-RP+memcpyCPUVersion], 1
PICREFERENCE memcpyCPUVersion, RP, 83H, 0BBH
        db      1                      ; Last byte of cmp instruction
        
        jb      memcpyCPUDispatch      ; First time: memcpyCPUVersion = 0, go to dispatcher
        je      memcpy386              ; memcpyCPUVersion = 1, go to 80386 version

ENDIF
        
        
memcpySSE2: ; SSE2 and later versions begin here        
        cmp     ecx, 40H
        jae     B100                   ; Use simpler code if count < 64
        
        ; count < 64. Move 32-16-8-4-2-1 bytes
        add     esi, ecx               ; end of src
        add     edi, ecx               ; end of dest
        neg     ecx                    ; negative index from the end
        cmp     ecx, -20H
        jg      A100        
        ; move 32 bytes
        ; movq is faster than movdqu on current processors (2008),
        ; movdqu may be faster on future processors
        movq    xmm0, qword ptr [esi+ecx]
        movq    xmm1, qword ptr [esi+ecx+8]
        movq    xmm2, qword ptr [esi+ecx+10H]
        movq    xmm3, qword ptr [esi+ecx+18H]
        movq    qword ptr [edi+ecx], xmm0
        movq    qword ptr [edi+ecx+8], xmm1
        movq    qword ptr [edi+ecx+10H], xmm2
        movq    qword ptr [edi+ecx+18H], xmm3
        add     ecx, 20H
A100:   cmp     ecx, -10H        
        jg      A200
        ; move 16 bytes
        movq    xmm0, qword ptr [esi+ecx]
        movq    xmm1, qword ptr [esi+ecx+8]
        movq    qword ptr [edi+ecx], xmm0
        movq    qword ptr [edi+ecx+8], xmm1
        add     ecx, 10H
A200:   cmp     ecx, -8        
        jg      A300
        ; move 8 bytes
        movq    xmm0, qword ptr [esi+ecx]
        movq    qword ptr [edi+ecx], xmm0
        add     ecx, 8
A300:   cmp     ecx, -4        
        jg      A400
        ; move 4 bytes
        mov     eax, [esi+ecx]
        mov     [edi+ecx], eax
        add     ecx, 4
        jz      A900                     ; early out if count divisible by 4
A400:   cmp     ecx, -2        
        jg      A500
        ; move 2 bytes
        movzx   eax, word ptr [esi+ecx]
        mov     [edi+ecx], ax
        add     ecx, 2
A500:   cmp     ecx, -1
        jg      A900        
        ; move 1 byte
        movzx   eax, byte ptr [esi+ecx]
        mov     [edi+ecx], al
A900:   ; finished
        RETURNM        
        
B100:   ; count >= 64
        ; Note: this part will not always work if count < 64
        ; Calculate size of first block up to first regular boundary of dest
        mov     edx, edi
        neg     edx
        and     edx, 0FH
        jz      B300                    ; Skip if dest aligned by 16
        
        ; edx = size of first partial block, 1 - 15 bytes
        add     esi, edx
        add     edi, edx
        sub     ecx, edx
        neg     edx
        cmp     edx, -8
        jg      B200
        ; move 8 bytes
        movq    xmm0, qword ptr [esi+edx]
        movq    qword ptr [edi+edx], xmm0
        add     edx, 8
B200:   cmp     edx, -4        
        jg      B210
        ; move 4 bytes
        mov     eax, [esi+edx]
        mov     [edi+edx], eax
        add     edx, 4
B210:   cmp     edx, -2        
        jg      B220
        ; move 2 bytes
        movzx   eax, word ptr [esi+edx]
        mov     [edi+edx], ax
        add     edx, 2
B220:   cmp     edx, -1
        jg      B300
        ; move 1 byte
        movzx   eax, byte ptr [esi+edx]
        mov     [edi+edx], al
        
B300:   ; Now dest is aligned by 16. Any partial block has been moved        
        ; Find alignment of src modulo 16 at this point:
        mov     eax, esi
        and     eax, 0FH
        
        ; Set up for loop moving 32 bytes per iteration:
        mov     edx, ecx               ; Save count
        and     ecx, -20H              ; Round down to nearest multiple of 32
        add     esi, ecx               ; Point to the end
        add     edi, ecx               ; Point to the end
        sub     edx, ecx               ; Remaining data after loop
        sub     esi, eax               ; Nearest preceding aligned block of src

IFNDEF  POSITIONINDEPENDENT
        ; Check if count very big
        cmp     ecx, [_CacheBypassLimit]
        ja      B400                   ; Use non-temporal store if count > _CacheBypassLimit
        neg     ecx                    ; Negative index from the end
        
        ; Dispatch to different codes depending on src alignment
        jmp     AlignmentDispatch[eax*4]

B400:   neg     ecx
        ; Dispatch to different codes depending on src alignment
        jmp     AlignmentDispatchNT[eax*4]

ELSE    ; Position-independent code

        ; Check if count very big
        ; Make the following instruction with address relative to RP:
        ; cmp     ecx, [ebx-RP+_CacheBypassLimit]
        PICREFERENCE _CacheBypassLimit, RP, 3BH, 8BH
        ja      B400                   ; Use non-temporal store if count > _CacheBypassLimit
        neg     ecx                    ; Negative index from the end
        
        ; Dispatch to different codes depending on src alignment
        

        ; AlignmentDispatch table contains addresses relative to RP
        ; Add table entry to ebx=RP to get jump address.

        ; Make the following instruction with address relative to RP:
        ; add ebx,[ebx-RP+AlignmentDispatch+eax*4]
        PICREFERENCE AlignmentDispatch, RP, 03H, 9CH, 83H
        jmp     ebx
        
B400:   neg     ecx

        ; Same with AlignmentDispatchNT:        
        PICREFERENCE AlignmentDispatchNT, RP, 03H, 9CH, 83H
        jmp     ebx        
ENDIF

align   16
C100:   ; Code for aligned src. SSE2 or later instruction set
        ; The nice case, src and dest have same alignment.

        ; Loop. ecx has negative index from the end, counting up to zero
        movaps  xmm0, [esi+ecx]
        movaps  xmm1, [esi+ecx+10H]
        movaps  [edi+ecx], xmm0
        movaps  [edi+ecx+10H], xmm1
        add     ecx, 20H
        jnz     C100
        
        ; Move the remaining edx bytes (0 - 31):
        add     esi, edx
        add     edi, edx
        neg     edx
        jz      C500                   ; Skip if no more data
        ; move 16-8-4-2-1 bytes, aligned
        cmp     edx, -10H
        jg      C200
        ; move 16 bytes
        movaps  xmm0, [esi+edx]
        movaps  [edi+edx], xmm0
        add     edx, 10H
C200:   cmp     edx, -8
        jg      C210        
        ; move 8 bytes
        movq    xmm0, qword ptr [esi+edx]
        movq    qword ptr [edi+edx], xmm0
        add     edx, 8 
        jz      C500                   ; Early skip if count divisible by 8       
C210:   cmp     edx, -4
        jg      C220        
        ; move 4 bytes
        mov     eax, [esi+edx]
        mov     [edi+edx], eax
        add     edx, 4        
C220:   cmp     edx, -2
        jg      C230        
        ; move 2 bytes
        movzx   eax, word ptr [esi+edx]
        mov     [edi+edx], ax
        add     edx, 2
C230:   cmp     edx, -1
        jg      C500        
        ; move 1 byte
        movzx   eax, byte ptr [esi+edx]
        mov     [edi+edx], al
C500:   ; finished     
        RETURNM
        
       
; Code for each src alignment, SSE2 instruction set:
; Make separate code for each alignment u because the shift instructions
; have the shift count as a constant:

MOVE_UNALIGNED_SSE2 MACRO u, nt
; Move ecx + edx bytes of data
; Source is misaligned. (src-dest) modulo 16 = u
; nt = 1 if non-temporal store desired
; eax = u
; esi = src - u = nearest preceding 16-bytes boundary
; edi = dest (aligned)
; ecx = - (count rounded down to nearest divisible by 32)
; edx = remaining bytes to move after loop
LOCAL L1, L2
        movdqa  xmm0, [esi+ecx]        ; Read from nearest preceding 16B boundary
L1:    ; Loop. ecx has negative index from the end, counting up to zero
        movdqa  xmm1, [esi+ecx+10H]    ; Read next two blocks aligned
        movdqa  xmm2, [esi+ecx+20H]
        movdqa  xmm3, xmm1             ; Copy because used twice
        psrldq  xmm0, u                ; shift right
        pslldq  xmm1, 16-u             ; shift left
        por     xmm0, xmm1             ; combine blocks
        IF nt eq 0
        movdqa  [edi+ecx], xmm0        ; Save aligned
        ELSE
        movntdq [edi+ecx], xmm0        ; non-temporal save
        ENDIF
        movdqa  xmm0, xmm2             ; Save for next iteration
        psrldq  xmm3, u                ; shift right
        pslldq  xmm2, 16-u             ; shift left
        por     xmm3, xmm2             ; combine blocks
        IF nt eq 0
        movdqa  [edi+ecx+10H], xmm3    ; Save aligned
        ELSE
        movntdq [edi+ecx+10H], xmm3    ; non-temporal save
        ENDIF
        add     ecx, 20H               ; Loop through negative values up to zero
        jnz     L1
        
        ; Set up for edx remaining bytes
        add     esi, edx
        add     edi, edx
        neg     edx
        cmp     edx, -10H
        jg      L2
        ; One more 16-bytes block to move
        movdqa  xmm1, [esi+edx+10H]
        psrldq  xmm0, u                ; shift right
        pslldq  xmm1, 16-u             ; shift left
        por     xmm0, xmm1             ; combine blocks
        IF nt eq 0
        movdqa  [edi+edx], xmm0        ; Save aligned
        ELSE
        movntdq [edi+edx], xmm0        ; non-temporal save
        ENDIF        
        add     edx, 10H        
L2:     ; Get src pointer back to misaligned state
        add     esi, eax
        ; Move remaining 0 - 15 bytes, unaligned
        jmp     C200
ENDM

MOVE_UNALIGNED_SSE2_4 MACRO nt
; Special case for u = 4
LOCAL L1, L2
        movaps  xmm0, [esi+ecx]        ; Read from nearest preceding 16B boundary
L1:     ; Loop. ecx has negative index from the end, counting up to zero
        movaps  xmm1, [esi+ecx+10H]    ; Read next two blocks aligned
        movss   xmm0, xmm1             ; Moves 4 bytes, leaves remaining bytes unchanged
        pshufd  xmm0, xmm0, 00111001B
        IF nt eq 0
        movdqa  [edi+ecx], xmm0        ; Save aligned
        ELSE
        movntdq [edi+ecx], xmm0        ; Non-temporal save
        ENDIF
        movaps  xmm0, [esi+ecx+20H]
        movss   xmm1, xmm0
        pshufd  xmm1, xmm1, 00111001B
        IF nt eq 0
        movdqa  [edi+ecx+10H], xmm1    ; Save aligned
        ELSE
        movntdq [edi+ecx+10H], xmm1    ; Non-temporal save
        ENDIF
        add     ecx, 20H               ; Loop through negative values up to zero
        jnz     L1        
        ; Set up for edx remaining bytes
        add     esi, edx
        add     edi, edx
        neg     edx
        cmp     edx, -10H
        jg      L2
        ; One more 16-bytes block to move
        movaps  xmm1, [esi+edx+10H]    ; Read next two blocks aligned
        movss   xmm0, xmm1
        pshufd  xmm0, xmm0, 00111001B
        IF nt eq 0
        movdqa  [edi+edx], xmm0        ; Save aligned
        ELSE
        movntdq [edi+edx], xmm0        ; Non-temporal save
        ENDIF
        add     edx, 10H        
L2:     ; Get src pointer back to misaligned state
        add     esi, eax
        ; Move remaining 0 - 15 bytes, unaligned
        jmp     C200
ENDM 

MOVE_UNALIGNED_SSE2_8 MACRO nt
; Special case for u = 8
LOCAL L1, L2
        movaps  xmm0, [esi+ecx]        ; Read from nearest preceding 16B boundary
L1:     ; Loop. ecx has negative index from the end, counting up to zero
        movaps  xmm1, [esi+ecx+10H]    ; Read next two blocks aligned
        movsd   xmm0, xmm1             ; Moves 8 bytes, leaves remaining bytes unchanged
        shufps  xmm0, xmm0, 01001110B  ; Rotate
        IF nt eq 0
        movdqa  [edi+ecx], xmm0        ; Save aligned
        ELSE
        movntdq [edi+ecx], xmm0        ; Non-temporal save
        ENDIF
        movaps  xmm0, [esi+ecx+20H]
        movsd   xmm1, xmm0
        shufps  xmm1, xmm1, 01001110B
        IF nt eq 0
        movdqa  [edi+ecx+10H], xmm1    ; Save aligned
        ELSE
        movntdq [edi+ecx+10H], xmm1    ; Non-temporal save
        ENDIF
        add     ecx, 20H               ; Loop through negative values up to zero
        jnz     L1        
        ; Set up for edx remaining bytes
        add     esi, edx
        add     edi, edx
        neg     edx
        cmp     edx, -10H
        jg      L2
        ; One more 16-bytes block to move
        movaps  xmm1, [esi+edx+10H]    ; Read next two blocks aligned
        movsd   xmm0, xmm1
        shufps  xmm0, xmm0, 01001110B
        IF nt eq 0
        movdqa  [edi+edx], xmm0        ; Save aligned
        ELSE
        movntdq [edi+edx], xmm0        ; Non-temporal save
        ENDIF
        add     edx, 10H        
L2:     ; Get src pointer back to misaligned state
        add     esi, eax
        ; Move remaining 0 - 15 bytes, unaligned
        jmp     C200
ENDM 

MOVE_UNALIGNED_SSE2_12 MACRO nt
; Special case for u = 12
LOCAL L1, L2
        movaps  xmm0, [esi+ecx]        ; Read from nearest preceding 16B boundary
        pshufd  xmm0, xmm0, 10010011B
L1:     ; Loop. ecx has negative index from the end, counting up to zero
        movaps  xmm1, [esi+ecx+10H]    ; Read next two blocks aligned
        movaps  xmm2, [esi+ecx+20H]
        pshufd  xmm1, xmm1, 10010011B
        pshufd  xmm2, xmm2, 10010011B
        movaps  xmm3, xmm2
        movss   xmm2, xmm1             ; Moves 4 bytes, leaves remaining bytes unchanged
        movss   xmm1, xmm0             ; Moves 4 bytes, leaves remaining bytes unchanged       
        IF nt eq 0
        movdqa  [edi+ecx], xmm1        ; Save aligned
        movdqa  [edi+ecx+10H], xmm2    ; Save aligned
        ELSE
        movntdq [edi+ecx], xmm1        ; Non-temporal save
        movntdq [edi+ecx+10H], xmm2    ; Non-temporal save
        ENDIF
        movaps  xmm0, xmm3             ; Save for next iteration        
        add     ecx, 20H               ; Loop through negative values up to zero
        jnz     L1        
        ; Set up for edx remaining bytes
        add     esi, edx
        add     edi, edx
        neg     edx
        cmp     edx, -10H
        jg      L2
        ; One more 16-bytes block to move
        movaps  xmm1, [esi+edx+10H]    ; Read next two blocks aligned
        pshufd  xmm1, xmm1, 10010011B
        movss   xmm1, xmm0             ; Moves 4 bytes, leaves remaining bytes unchanged       
        IF nt eq 0
        movdqa  [edi+edx], xmm1        ; Save aligned
        ELSE
        movntdq [edi+edx], xmm1        ; Non-temporal save
        ENDIF
        add     edx, 10H        
L2:     ; Get src pointer back to misaligned state
        add     esi, eax
        ; Move remaining 0 - 15 bytes, unaligned
        jmp     C200
ENDM 

; Code for each src alignment, Suppl.SSE3 instruction set:
; Make separate code for each alignment u because the palignr instruction
; has the shift count as a constant:

MOVE_UNALIGNED_SSSE3 MACRO u
; Move ecx + edx bytes of data
; Source is misaligned. (src-dest) modulo 16 = u
; eax = u
; esi = src - u = nearest preceding 16-bytes boundary
; edi = dest (aligned)
; ecx = - (count rounded down to nearest divisible by 32)
; edx = remaining bytes to move after loop
LOCAL L1, L2
        movdqa  xmm0, [esi+ecx]        ; Read from nearest preceding 16B boundary
        
L1:     ; Loop. ecx has negative index from the end, counting up to zero
        movdqa  xmm2, [esi+ecx+10H]    ; Read next two blocks
        movdqa  xmm3, [esi+ecx+20H]
        movdqa  xmm1, xmm0             ; Save xmm0
        movdqa  xmm0, xmm3             ; Save for next iteration
        palignr xmm3, xmm2, u          ; Combine parts into aligned block
        palignr xmm2, xmm1, u          ; Combine parts into aligned block
        movdqa  [edi+ecx], xmm2        ; Save aligned
        movdqa  [edi+ecx+10H], xmm3    ; Save aligned
        add     ecx, 20H
        jnz     L1
        
        ; Set up for edx remaining bytes
        add     esi, edx
        add     edi, edx
        neg     edx
        cmp     edx, -10H
        jg      L2
        ; One more 16-bytes block to move
        movdqa  xmm2, [esi+edx+10H]
        palignr xmm2, xmm0, u
        movdqa  [edi+edx], xmm2
        add     edx, 10H        
L2:     ; Get src pointer back to misaligned state
        add     esi, eax
        ; Move remaining 0 - 15 bytes
        jmp     C200
ENDM        

; Make 15 instances of SSE2 macro for each value of the alignment u.
; These are pointed to by the jump table AlignmentDispatchSSE2 below
; (aligns are inserted manually to minimize the number of 16-bytes
; boundaries inside loops)

D101:   MOVE_UNALIGNED_SSE2 1,   0
D102:   MOVE_UNALIGNED_SSE2 2,   0
D103:   MOVE_UNALIGNED_SSE2 3,   0
align   16
D104:   MOVE_UNALIGNED_SSE2_4    0
D105:   MOVE_UNALIGNED_SSE2 5,   0
D106:   MOVE_UNALIGNED_SSE2 6,   0
align   8
D107:   MOVE_UNALIGNED_SSE2 7,   0
align   16
D108:   MOVE_UNALIGNED_SSE2_8    0
D109:   MOVE_UNALIGNED_SSE2 9,   0
D10A:   MOVE_UNALIGNED_SSE2 0AH, 0
D10B:   MOVE_UNALIGNED_SSE2 0BH, 0
align   8
D10C:   MOVE_UNALIGNED_SSE2_12   0
D10D:   MOVE_UNALIGNED_SSE2 0DH, 0
D10E:   MOVE_UNALIGNED_SSE2 0EH, 0
D10F:   MOVE_UNALIGNED_SSE2 0FH, 0
        
; Make 15 instances of Suppl-SSE3 macro for each value of the alignment u.
; These are pointed to by the jump table AlignmentDispatchSupSSE3 below

align   8
E101:   MOVE_UNALIGNED_SSSE3 1
E102:   MOVE_UNALIGNED_SSSE3 2
E103:   MOVE_UNALIGNED_SSSE3 3
E104:   MOVE_UNALIGNED_SSSE3 4
align   8
E105:   MOVE_UNALIGNED_SSSE3 5
E106:   MOVE_UNALIGNED_SSSE3 6
E107:   MOVE_UNALIGNED_SSSE3 7
E108:   MOVE_UNALIGNED_SSSE3 8
align   8
E109:   MOVE_UNALIGNED_SSSE3 9
E10A:   MOVE_UNALIGNED_SSSE3 0AH
E10B:   MOVE_UNALIGNED_SSSE3 0BH
E10C:   MOVE_UNALIGNED_SSSE3 0CH
align   8
E10D:   MOVE_UNALIGNED_SSSE3 0DH
E10E:   MOVE_UNALIGNED_SSSE3 0EH
E10F:   MOVE_UNALIGNED_SSSE3 0FH

; Codes for non-temporal move. Aligned case first

F100:   ; Non-temporal move, src and dest have same alignment.
        ; Loop. ecx has negative index from the end, counting up to zero
        movaps  xmm0, [esi+ecx]        ; Read
        movaps  xmm1, [esi+ecx+10H]
        movntps [edi+ecx], xmm0        ; Write non-temporal (bypass cache)
        movntps [edi+ecx+10H], xmm1
        add     ecx, 20H
        jnz     F100                   ; Loop through negative ecx up to zero
                
        ; Move the remaining edx bytes (0 - 31):
        add     esi, edx
        add     edi, edx
        neg     edx
        jz      C500                   ; Skip if no more data
        ; Check if we can more one more 16-bytes block
        cmp     edx, -10H
        jg      C200
        ; move 16 bytes, aligned
        movaps  xmm0, [esi+edx]
        movntps [edi+edx], xmm0
        add     edx, 10H
        ; move the remaining 0 - 15 bytes
        jmp     C200

; Make 15 instances of MOVE_UNALIGNED_SSE2 macro for each value of 
; the alignment u.
; These are pointed to by the jump table AlignmentDispatchNT below

F101:   MOVE_UNALIGNED_SSE2 1,   1
F102:   MOVE_UNALIGNED_SSE2 2,   1
F103:   MOVE_UNALIGNED_SSE2 3,   1
F104:   MOVE_UNALIGNED_SSE2_4    1
F105:   MOVE_UNALIGNED_SSE2 5,   1
F106:   MOVE_UNALIGNED_SSE2 6,   1
F107:   MOVE_UNALIGNED_SSE2 7,   1
F108:   MOVE_UNALIGNED_SSE2_8    1
F109:   MOVE_UNALIGNED_SSE2 9,   1
F10A:   MOVE_UNALIGNED_SSE2 0AH, 1
F10B:   MOVE_UNALIGNED_SSE2 0BH, 1
F10C:   MOVE_UNALIGNED_SSE2_12   1
F10D:   MOVE_UNALIGNED_SSE2 0DH, 1
F10E:   MOVE_UNALIGNED_SSE2 0EH, 1
F10F:   MOVE_UNALIGNED_SSE2 0FH, 1

IFDEF   POSITIONINDEPENDENT
get_thunk_ebx: ; load caller address into ebx for position-independent code
        mov ebx, [esp]
        ret
ENDIF

; 80386 version used when SSE2 not supported:
memcpy386:
; edi = dest
; esi = src
; ecx = count
        cld
        cmp     ecx, 8
        jb      G500
G100:   test    edi, 1
        jz      G200
        movsb
        dec     ecx
G200:   test    edi, 2
        jz      G300
        movsw
        sub     ecx, 2
G300:   ; edi is aligned now
        mov     edx, ecx
        shr     ecx, 2
        rep     movsd                  ; move 4 bytes at a time
        mov     ecx, edx
        and     ecx, 3
        rep     movsb                  ; move remaining 0-3 bytes
        RETURNM
        
G500:   ; count < 8. Move one byte at a time
        rep     movsb                  ; move count bytes
        RETURNM
        
; CPU dispatching for memcpy. This is executed only once
memcpyCPUDispatch:
IFNDEF   POSITIONINDEPENDENT
        pushad
        call    _InstructionSet
        ; Point to generic version of memcpy
        mov     [memcpyDispatch], offset memcpy386
        cmp     eax, 4                 ; check SSE2
        jb      M100
        ; SSE2 supported
        ; Point to SSE2 and later version of memcpy
        mov     [memcpyDispatch], offset memcpySSE2
        cmp     eax, 6                 ; check Suppl-SSE3
        jb      M100
        ; Suppl-SSE3 supported
        ; Replace alignment dispatch table with Suppl-SSE3 version        
        mov     esi, offset AlignmentDispatchSupSSE3
        mov     edi, offset AlignmentDispatchSSE2
        mov     ecx, 16
        cld
        rep     movsd
M100:   popad
        ; Continue in appropriate version of memcpy
        jmp     [memcpyDispatch]

ELSE    ; Position-independent version
        pushad
        call    _InstructionSet
        
; Make the following instruction with address relative to RP:
; lea edx, [ebx-RP+memcpyCPUVersion]
PICREFERENCE memcpyCPUVersion, RP, 8DH, 93H
; Now edx points to memcpyCPUVersion. Use edx as reference to data segment

        mov     byte ptr [edx], 1      ; Indicate generic version
        cmp     eax, 4                 ; check SSE2
        jb      M100
        ; SSE2 supported
        mov     byte ptr [edx], 2      ; Indicate SSE2 or later version
        cmp     eax, 6                 ; check Suppl-SSE3
        jb      M100
        ; Suppl-SSE3 supported
        ; Replace alignment dispatch table with Suppl-SSE3 version        
        lea     esi, [edx][AlignmentDispatchSupSSE3-memcpyCPUVersion]
        lea     edi, [edx][AlignmentDispatchSSE2-memcpyCPUVersion]
        mov     ecx, 16
        cld
        rep     movsd
M100:   popad
        jmp     A020                   ; Go back and dispatch
        
ENDIF


; Data segment must be included in function namespace
.data

; Jump tables for alignments 0 - 15:
; The CPU dispatcher replaces AlignmentDispatchSSE2 with 
; AlignmentDispatchSupSSE3 if Suppl-SSE3 is supported
; RP = reference point if position-independent code, otherwise RP = 0

AlignmentDispatch label dword
; Code pointer for each alignment for SSE2 instruction set
AlignmentDispatchSSE2 label dword
DD C100-RP, D101-RP, D102-RP, D103-RP, D104-RP, D105-RP, D106-RP, D107-RP
DD D108-RP, D109-RP, D10A-RP, D10B-RP, D10C-RP, D10D-RP, D10E-RP, D10F-RP

; Code pointer for each alignment for Suppl.SSE3 instruction set
AlignmentDispatchSupSSE3 label dword
DD C100-RP, E101-RP, E102-RP, E103-RP, E104-RP, E105-RP, E106-RP, E107-RP
DD E108-RP, E109-RP, E10A-RP, E10B-RP, E10C-RP, E10D-RP, E10E-RP, E10F-RP

; Code pointer for each alignment for non-temporal store
AlignmentDispatchNT label dword
DD F100-RP, F101-RP, F102-RP, F103-RP, F104-RP, F105-RP, F106-RP, F107-RP
DD F108-RP, F109-RP, F10A-RP, F10B-RP, F10C-RP, F10D-RP, F10E-RP, F10F-RP

IFNDEF  POSITIONINDEPENDENT
; Pointer to appropriate version.
; This initially points to memcpyCPUDispatch. memcpyCPUDispatch will
; change this to the appropriate version of memcpy, so that
; memcpyCPUDispatch is only executed once:
memcpyDispatch DD memcpyCPUDispatch
ELSE
; CPU version: 0=unknown, 1=80386, 2=SSE2 or later
memcpyCPUVersion DD 0
ENDIF

; Bypass cache by using non-temporal moves if count > _CacheBypassLimit
; The optimal value of _CacheBypassLimit is difficult to estimate, but
; a reasonable value is half the size of the largest cache:
_CacheBypassLimit DD 400000H             ; 400000H = 4 Megabytes

.code
_A_memcpy ENDP                           ; End of function namespace

...
Рейтинг: 0 / 0
25 сообщений из 66, страница 2 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / K&R 5.5 Указатели символов и функции. Корректен ли код ?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]