История изменений
Исправление firkax, (текущая версия) :
Со сдвигами меньше 16 никто бинарники не грузит и даже в досе не грузил. В современных ОС кратность не меньше одной страницы (4096) думаю, и вроде бы краткие опыты это подтверждают, последние даже 3 числа в адресе не меняются от запуска к запуску.
А вот сдвиг .o модуля при линковке может быть произвольным, только что проверил, а я думал модули на 16 выравниваются. Кажется вопрос почти полностью раскрыт, и он не атлоно-специфичный, но конкретно на том проце проявился сильно заметно, а на других может вылезти где-то в другом виде. Оказалось, что то 0xBA в дампе модуля превращалось в 0x...4 в дампе бинарника. То есть лагает если цикл начинается на адресах 0x14..0x1F по модулю 0x20. И примерно понятно почему: при этом цикл пересекает 32-байтовую границу. Извиняюсь за то что неправильно посчитал адреса в начале проверок и всех ввёл в заблуждение.
Однако, одна небольшая деталь всё-таки не ясна. При начале на 0x14 второй байт JNE (тот, где указано назначение перехода) оказывается на адресе 0x20 т.е. всё-таки пересекает границу, но цикл всё равно ещё быстрый.
Что касается выравниваний. Если в .o-файле нет ни одного явного выравнивания, то линкер кладёт его прямо сразу на свободный байт после предыдущего, т.е. не выравнивает вообще никак. Если в его исходнике было упомянуто например .balign 4 (в любом месте), то весь скомпилированный из него .o тоже где-то помечается как выровненный на 4 и линкер это учитывает (очевидно затем, что иначе локальное выравнивание соблюсти не выйдет). Так что если бы я начал не с изучения objdump, а с простановки .balign 16 перед циклом - сразу бы увидел что он стал быстрый и не зависит от посторонних обстоятельств.
Конкретно с атлоном видимо рецепт такой - ставить .balign 8, 16, 32 в зависимости от того сколько байт занимает цикл (чтоб он влез в этот выровненный блок). У других процов могут быть отличия, но если цикл меньше 16 байт и .balign 16 то думаю везде будет хорошо.
Исправление firkax, :
Со сдвигами меньше 16 никто бинарники не грузит и даже в досе не грузил. В современных ОС кратность не меньше одной страницы (4096) думаю, и вроде бы краткие опыты это подтверждают, последние даже 3 числа в адресе не меняются от запуска к запуску.
А вот сдвиг .o модуля при линковке может быть произвольным, только что проверил, а я думал модули на 16 выравниваются. Кажется вопрос почти полностью раскрыт, и он не атлоно-специфичный, но конкретно на том проце проявился сильно заметно. Оказалось, что то 0xBA в дампе модуля превращалось в 0x...4 в дампе бинарника. То есть лагает если цикл начинается на адресах 0x14..0x1F по модулю 0x20. И примерно понятно почему: при этом цикл пересекает 32-байтовую границу. Извиняюсь за то что неправильно посчитал адреса в начале проверок и всех ввёл в заблуждение.
Однако, одна небольшая деталь всё-таки не ясна. При начале на 0x14 второй байт JNE (тот, где указано назначение перехода) оказывается на адресе 0x20 т.е. всё-таки пересекает границу, но цикл всё равно ещё быстрый.
Что касается выравниваний. Если в .o-файле нет ни одного явного выравнивания, то линкер кладёт его прямо сразу на свободный байт после предыдущего, т.е. не выравнивает вообще никак. Если в его исходнике было упомянуто например .balign 4 (в любом месте), то весь скомпилированный из него .o тоже где-то помечается как выровненный на 4 и линкер это учитывает (очевидно затем, что иначе локальное выравнивание соблюсти не выйдет). Так что если бы я начал не с изучения objdump, а с простановки .balign 16 перед циклом - сразу бы увидел что он стал быстрый и не зависит от посторонних обстоятельств.
Исходная версия firkax, :
Со сдвигами меньше 16 никто бинарники не грузит и даже в досе не грузил. В современных ОС кратность не меньше одной страницы (4096) думаю, и вроде бы краткие опыты это подтверждают, последние даже 3 числа в адресе не меняются от запуска к запуску.
А вот сдвиг .o модуля при линковке может быть произвольным, только что проверил, а я думал модули на 16 выравниваются. Кажется вопрос почти полностью раскрыт, и он не атлоно-специфичный. Оказалось, что то 0xBA в дампе модуля превращалось в 0x...4 в дампе бинарника. То есть лагает если цикл начинается на адресах 0x14..0x1F по модулю 0x20. И примерно понятно почему: при этом цикл пересекает 32-байтовую границу. Извиняюсь за то что неправильно посчитал адреса в начале проверок и всех ввёл в заблуждение.
Однако, одна небольшая деталь всё-таки не ясна. При начале на 0x14 второй байт JNE (тот, где указано назначение перехода) оказывается на адресе 0x20 т.е. всё-таки пересекает границу, но цикл всё равно ещё быстрый.
Что касается выравниваний. Если в .o-файле нет ни одного явного выравнивания, то линкер кладёт его прямо сразу на свободный байт после предыдущего, т.е. не выравнивает вообще никак. Если в его исходнике было упомянуто например .balign 4 (в любом месте), то весь скомпилированный из него .o тоже где-то помечается как выровненный на 4 и линкер это учитывает (очевидно затем, что иначе локальное выравнивание соблюсти не выйдет). Так что если бы я начал не с изучения objdump, а с простановки .balign 16 перед циклом - сразу бы увидел что он стал быстрый и не зависит от посторонних обстоятельств.