Вернуться   Биткоин Форум > Разработка и Техническое Обсуждение
18 апреля 2017, 2:10:40 PM   # 1
 
 
Сообщения: 778
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Взлом Биткоин адресов.
500 Биткоинов взломаны в "мозговом кошельке" с паролем "bitcoin is awesome"
Адрес кошелька: 14NWDXkQwcGN1Pd9fboL8npVynD5SfyJAE
Приватный ключ: 5J64pq77XjeacCezwmAr2V1s7snvvJkuAz8sENxw7xCkikceV6e
подробнее...


Всем кто хочет заработать Биткоины без вложений - рекомендую сайт http://bitcoin-zarabotat.ru
Здравствуй,
Я хочу использовать скорость полевых операций в libsecp256k1, чтобы быстрее операции по модулю р (р = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F).

Я написал простую программу для вычисления умножения двух 256-битных чисел. Мой код выполняет 100M раз Mult: Gx * Гр по модулю р.

Есть 2 версии: A (ГМП библиотека), B (secp256k1 библиотека)

Проблема заключается в том, что в данный момент я могу получить лучшие результаты с ГМП библиотекой, чем libsecp256k1 (по крайней мере, + 10%):

Программа А (библиотека ГМП):  

Код:
---@ubuntu: ~ / SRC / вар / мул $ время ./a.out

Результат: fd3dc529c6eb60fb 9d166034cf3c1a5a 72324aa9dfd3428a 56d7e1ce0179fd9b

реальный 0m5.399s
пользователь 0m5.324s
системный 0m0.012s


Программа B (secp256k1 библиотека):
Код:
---@ubuntu: ~ / SRC / вар / мул $ время ./a.out

Результат: FD 3d с5 29 с6 ЕВ 60 FB 9d 16 60 34 сра 3c 1a 5а 72 32 4 а9 DF d3 42 8а 56 D7 е1 с-79 FD 9b

реальный 0m6.076s
пользователь 0m5.988s
системный 0m0.004s


Не должно быть наоборот? Есть ли что-то не так в моем коде?




Программа А (библиотека ГМП):
Код:
#включают
#включают
#включают

рядный недействительным красный (неподписанный долгий INT * а) {

...> выполняет "мод р"

}

Int основных () {

неподписанных долгое INT I;
без знака длиной Int А [8];

без знака длиной INT Сх [4] = {0x59f2815b16f81798, 0x029bfcdb2dce28d9, 0x55a06295ce870b07, 0x79be667ef9dcbbac};
без знака длиной INT Гр [4] = {0x9c47d08ffb10d4b8, 0xfd17b448a6855419, 0x5da4fbfc0e1108a8, 0x483ada7726a3c465};


для (я = 0; я<100000000; я ++) {

mpn_mul_n (а, Сх, Гр, 4); // # 1M
красный (а);
}

Е ("Результат:% лк% лк% лк% лк \ п", А [3], а [2], а [1], а [0]);

возвращать 0;
}

Программа B (libsecp256k1 библиотека):
Код:
// Компиляция с:                                                    
// GCC -O2 -I secp256k1 / SRC / -I secp256k1 / mul.c -lgmp

#включают
#включают
#включают "libsecp256k1-config.h"
#включают "включить / secp256k1.h"
#включают "secp256k1.c"

Int основных () {


        Const символ без знака Сх [32] = {0x79,0xBE, 0x66,0x7E, 0xF9,0xDC, 0xBB, 0xac, 0x55,0xA0,0x62,0x95,0xCE, //
                            0x87,0x0B, 0x07,0x02,0x9B, 0xFC, 0xdb, 0x2D, ​​0xCE, 0x28,0xD9,0x59,0xF2, //
                                             0x81,0x5B, 0x16,0xF8,0x17,0x98};

        Const символ без знака Гр [32] = {0x48,0x3A, 0xDA, 0x77,0x26,0xA3,0xC4,0x65,0x5D, 0xA4, //
                      0xFB, 0xFC, 0x0E, 0x11,0x08,0xA8,0xFD, 0x17,0xB4, //
                                               0x48,0xA6,0x85,0x54,0x19,0x9C, 0x47,0xD0,0x8F, 0xFB, 0x10,0xD4,0xB8};


       secp256k1_fe а, б, г;
       символ без знака с [32];

       secp256k1_fe_set_b32 (&а, Сх);
       secp256k1_fe_set_b32 (&б, Гр);


       для (я = 0; я<100000000; я ++) {// 100 000 000

    secp256k1_fe_mul (&р, &а, &б);
    // secp256k1_fe_normalize_var (&р);


       }

       secp256k1_fe_get_b32 (с, &р);

       Е ("Результат:% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х% х % х% х% х% х% х% х% х% х \ п"//
       с [0], с [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]);

       возвращать 0;
}

arulbero сейчас офлайн Пожаловаться на arulbero   Ответить с цитированием Мультицитирование сообщения от arulbero Быстрый ответ на сообщение arulbero


Как заработать Биткоины?
Без вложений. Не майнинг.


19 апреля 2017, 5:20:37 AM   # 2
 
 
Сообщения: 2366
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Получил 1806 Биткоинов
Реальная история.





libsecp256k1 Крипто library-- не bignum библиотека.

Его примитивные операции постоянное время для сопротивления sidechannel, они не ожидается, будут быстрее, чем GMP для большинства things-- просто не беспричинна медленнее. Он также оптимизированы для конкретных видов операций, которые выполняются в эллиптической кривой, которая редко crypto-- состоит из многократно умножения значения в цикле, но вместо этого имеет последовательности операций умножения и сложения и представления FE построен, чтобы сделать эти дополнения очень быстро ,

Ваш бенчмаркинг метод, который не использует большую часть продукции, вероятно, также получить плохие результаты из-за части теста оптимизируется из.

Функции, которые призывают не подвергаются частям библиотеки, не являются стабильными интерфейсами, и не должны использоваться внешней software--, как я уже говорил, это не bignum библиотеки. Функции, которые она экспортирует определенные в включают / secp256k1.h ... вы обходя общедоступный интерфейс, включив файл .c.

Как и в сторону, почему бы вы когда-либо хотите выполнять арифметические операции над 2 ^ 256 - 4294968273? Порядок группы будет неудивителен ...
gmaxwell сейчас офлайн Пожаловаться на gmaxwell   Ответить с цитированием Мультицитирование сообщения от gmaxwell Быстрый ответ на сообщение gmaxwell

22 апреля 2017, 3:59:25 PM   # 3
 
 
Сообщения: 1442
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

libsecp256k1 Крипто library-- не bignum библиотека.

Его примитивные операции постоянное время для сопротивления sidechannel, они не ожидается, будут быстрее, чем GMP для большинства things-- просто не беспричинна медленнее.

Из того, что я понимаю sidechannel сопротивления требуется для подписания, так что закрытый ключ не просочилось, верно? Верификация все общедоступные данные, так что это не имеет значения (в случае BTC).

Если это так, то и обоснование правильно, то это, вероятно, имеет смысл, для приложения, как Bitcoin с асимметричными проверки / подписи нагрузок (где вам нужно проверить тысячи и тысячи, чтобы синхронизировать blockchain в течение последних нескольких дней, пока вы только отправить деньги пару раз), чтобы иметь повторяющиеся операции:

-Один из них не является действительно боковым каналом упорного и очень быстро и
-один, который не очень быстро (или очень медленно, действительно), но очень закаленные от атак со стороны каналов, так что вы не потеряете деньги.

В зависимости от того, что вы хотите сделать (синхронизацию blockchain или подписание нового ТХ), вы вызываете различные функции и наслаждаться лучшее из обоих миров: Максимальная скорость, когда вам нужно проверить Txs навалом, и максимальная безопасность при входе ТХ.

Я ошибаюсь где-нибудь?
AlexGR сейчас офлайн Пожаловаться на AlexGR   Ответить с цитированием Мультицитирование сообщения от AlexGR Быстрый ответ на сообщение AlexGR

23 апреля 2017, 3:50:09 AM   # 4
 
 
Сообщения: 2366
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Вы пропустили часть моего поста:

" просто не беспричинно медленнее. Он также оптимизированы для конкретных видов операций, которые выполняются в эллиптической кривой, которая редко crypto-- состоит из многократно умножения значения в цикле, но вместо этого имеет последовательности операций умножения и сложения и представления FE построен, чтобы сделать эти дополнения очень быстро , "

Библиотека изначально была написана с использованием GMP для поля арифметики, затем восстанавливают до его использования для проверки только, затем восстанавливает не использовать его на всех, когда новый код был быстрее для этого фактического использования на большинстве хостов.

Угол проверки также имеет два других вопросы, которые вы не рассматриваете: консенсусную последовательность. Использование GMP валидация бы точное поведение GMP консенсуса критического, что является проблемой, так как разные системы работают разные коды. (GMP также имеет лицензию, которая является более ограничительным, чем программное обеспечение Bitcoin).

Если вы не имели в виду, используя GMP, но только с помощью различных операций для не sidechannel чувствительной paths-- библиотеки уже делает, что во многих places--, хотя и не для FE мул / добавить. FE нормализует делать принимать переменное время проверки. Если у вас есть ускорение, основанное на том, что вы можете отправить его!
gmaxwell сейчас офлайн Пожаловаться на gmaxwell   Ответить с цитированием Мультицитирование сообщения от gmaxwell Быстрый ответ на сообщение gmaxwell

23 апреля 2017, 9:16:11 AM   # 5
 
 
Сообщения: 1442
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Угол проверки также имеет два других вопросы, которые вы не рассматриваете: консенсусную последовательность. Использование GMP валидация бы точное поведение GMP консенсуса критического, что является проблемой, так как разные системы работают разные коды. (GMP также имеет лицензию, которая является более ограничительным, чем программное обеспечение Bitcoin).

Я никогда бы не подумал, консистенция, возможно, были проблемы с целыми значениями, пока я вроде не узнал об этом на собственном горьком опыте, теряя день, получая избили двух умножений в конце поля 10x26 при преобразовании все это в SSE2 работать на регистры MMX для моего 12yr старый Пентиум-м ноутбук ...

D + = с * (R1 >> 4) + t1

а также

д = с * (R0 >> 4) + t0;

где R1 представл ет >>4 = 64, R0 >>4 = 977 ... не было никакого способа, чтобы получить его вычислить с с * 64 / с * 977, как это: "PMULUDQ (регистр с 64 или 977 в качестве источника) и (регистрироваться в) в качестве мишени.

Я до сих пор не знаю, почему сдвиг влево на 6 не то же самое, как умножение с 64 - если перелива и обтекание не в игре (или, может быть, это я не знаю, - но от того, что я вижу, количество бит должен быть 53 и 56, вдали от переполненности).

    D = C * (R 0 >> 4) + t0;
    VERIFY_BITS (д, 56);

    D + = C * (R 1 >> 4) + t1;
    VERIFY_BITS (д, 53);


Во всяком случае, мой ум все еще недоумевал по этому поводу, но я должен был работать вокруг него, пока тест не не сломается.

Для * 64 Я сделал это с сворачивает налево на 6.

Для * 977 Я сделал это с уродством, где с были скопированы в нескольких регистров, а затем каждый экземпляр был сдвинут соответствующим образом, а затем сдвинутый гр получил добавленное.

Во всяком случае, несмотря на это дорогой обходного пути, родные 64-разрядные арифметические регистры MMX разнести ССАГПЗ / лязг / ICC скомпилированных версии для более -m32 сборки. размер Опкод также был уменьшен (1900 против 2800 байт для field_mul, 1300 против 2200+ байт для field_sqr).

котировка
Если вы не имели в виду, используя GMP, но только с помощью различных операций для не sidechannel чувствительной paths-- библиотеки уже делает, что во многих places--, хотя и не для FE мул / добавить. FE нормализует делать принимать переменное время проверки. Если у вас есть ускорение, основанное на том, что вы можете отправить его!

Сейчас только массивный убыстрение я достиг в 32-битной версии, где компиляторы используют 32-битные регистры (вместо 64-битных MMX / SSE регистров). Для 64-битной версии, с не AVX использования, я на ~ 10% прибыли в не-комментировал код (который, кажется, плохо для обзора), из которых 3-5% был недавнее увеличение, за счет уменьшения параметров затирания на ассемблере и вручную перемежении начальных толчков и конечные хлопки в удобных этапах (например, умножение и сложение киосков).


Чем быстрее 32-разрядная версия ниже (я сделал комментарии о том, что делает каждая строка, в случае, если это будет полезно для других, но я не рассматривал его "представление" за счет использования массива, который не sidechannel устойчивостью (и я думал, что это было "требование"). По существу массив используется в начале для хранения результатов умножений и дополнений, которые являются нелинейными и, таким образом, может быть вычислено на старте.)

На моем ноутбуке (Пентиум-м 2,13) ​​bench_verify (с endomoprhism) вниз к 350us от 570us.

На моем рабочем столе (Q8200 @ 1,86) это в 404us вниз от 652us. Это, вероятно, может пойти вниз еще на 5-10%, если код читаемость страдает много (это уже страдает от некоторого ручного чередования операций памяти с мулами и добавляет, чтобы получить ~ 7-10%).

C версии (-m32 / поле 10x26):
field_sqr: мин 0.187us / ср / макс 0.188us 0.189us
field_mul: мин 0.275us / ср / макс 0.277us 0.278us
field_inverse: мин 55.4us / ср / макс 55.6us 55.8us
field_inverse_var: мин 55.4us / ср / макс 55.6us 55.9us
field_sqrt: мин 53.8us / ср / макс 54.1us 54.5us
...
context_verify: мин 77649us / ср / макс 77741us 77891us
context_sign: мин 267us / ср / макс 268us 269us
...

версия ASM (-m32 / поле 10x26) (sse2 на MMX * регистры):
field_sqr: мин 0.101us / ср / макс 0.101us 0.102us
field_mul: мин 0.135us / ср / макс 0.135us 0.135us
field_inverse: мин 28.3us / ср / макс 28.3us 28.4us
field_inverse_var: мин 28.3us / ср / макс 28.3us 28.4us
field_sqrt: мин 28.0us / ср / макс 28.0us 28.0us
...
context_verify: мин 42876us / ср / макс 43099us 43391us
context_sign: мин 170us / ср / макс 170us 170us

* В Core2, это не делает разницы, если это XMM или регистры мм (за исключением 2-3% ускорения с удалением EMMS в конце концов). На Пентиуме-м, операции XMM регистров очень медленно, чтобы начать с того, я подозреваю, что они эмулируются с точкой зрения ширины, что приводит к удвоенным операциям внутренне, но MMX регистров отображаются на регистрах 80bit ФПА, которые имеют хорошую фактическую ширину и собственно скорость.

Код:
SECP256K1_INLINE статической силы secp256k1_fe_mul_inner (uint32_t * г, Const uint32_t * а, Const uint32_t * SECP256K1_RESTRICT б) {
/ * Uint64_t с, д; * /
    uint64_t результат [19]; / * Температура хранения массива * /
    uint32_t tempstor [2]; / * Температура хранения массива * /
    Const uint32_t М = 0x3FFFFFFUL, R0 = 0x3D10UL / *, R 1 = 0x400UL * /;
    
tempstor [0] = М;
tempstor [1] = R0;
/ * Tempstor [2] для R1 не требуется. Это 1024, так сворачивает налево на 10 вместо * /
    
  __asm__ __volatile __ (  
  
 / * Часть # 1: Умножения и дополнения
  *
  * D = (uint64_t) (uint64_t) а [0] * б [9]
       + (Uint64_t) а [1] * б [8]
       + (Uint64_t) а [2] * б [7]
       + (Uint64_t) а [3] * б [6]
       + (Uint64_t) а [4] * б [5]
       + (Uint64_t) а [5] * б [4]
       + (Uint64_t) а [6] * б [3]
       + (Uint64_t) а [7] * б [2]
       + (Uint64_t) а [8] * б [1]
       + (Uint64_t) а [9] * б [0]; * /
 
 "MOVD 0 (% 0), %% MM0 \ п"  / * A0 * /
 "MOVD 36 (% 1), %% ММ2 \ п"  / * B9 * /
 "MOVD 4 (% 0), %% ММ1 \ п" / * A1 * /
 "MOVD 32 (% 1), %% ММ3 \ п" / * B8 * /
 "PMULUDQ %% MM0, %% MM2 \ п" / * A0 * b9 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A1 * b8 * /
 "MOVD 8 (% 0), %% ММ4 \ п"  / * A2 * /
 "MOVD 28 (% 1), %% ММ6 \ п"  / * B7 * /
 "MOVD 12 (% 0), %% ММ5 \ п" / * A3 * /
 "MOVD 24 (% 1), %% MM7 \ п" / * B6 * /
 "PMULUDQ %% MM4, %% MM6 \ п" / * A2 * b7 * /
 "PMULUDQ %% ММ5, %% MM7 \ п" / * A3 * b6 * /
 "MOVD 16 (% 0), %% MM0 \ п"  / * A4 * /
 "MOVD 20 (% 0), %% ММ1 \ п" / * A5 * /
 "PADDQ %% MM2, %% MM3 \ п"
 "PADDQ %% MM6, %% MM7 \ п"
 "PADDQ %% MM3, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 20 (% 1), %% ММ2 \ п"  / * B5 * /
 "MOVD 16 (% 1), %% ММ3 \ п" / * B4 * /
 "PMULUDQ %% MM0, %% MM2 \ п" / * A4 * b5 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A5 * b4 * /
 "MOVD 24 (% 0), %% MM0 \ п"  / * A6 * /
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 28 (% 0), %% ММ1 \ п" / * A7 * /
 "PADDQ %% MM3, %% MM7 \ п"  / * Результат учета дополнений в mm7 * /
 "MOVD 12 (% 1), %% ММ2 \ п"  / * B3 * /
 "MOVD 8 (% 1), %% ММ3 \ п" /* Би 2 */
 "PMULUDQ %% MM0, %% MM2 \ п" / * A6 * b3 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A7 * b2 * /
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 32 (% 0), %% MM0 \ п"  / * A8 * /
 "MOVD 36 (% 0), %% ММ1 \ п" / * A9 * /
 "PADDQ %% MM3, %% MM7 \ п"  / * Результат учета дополнений в mm7 * /
 "MOVD 4 (% 1), %% ММ2 \ п"  / * B1 * /
 "MOVD 0 (% 1), %% ММ3 \ п" / * B0 * /
 "PMULUDQ %% MM0, %% MM2 \ п" / * A8 * b1 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A9 * b0 * /
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 4 (% 1), %% ММ2 \ п"  / * B1 * /
 "PADDQ %% MM3, %% MM7 \ п"  / * Результат учета дополнений в mm7 * /
 "MOVD 8 (% 1), %% ММ3 \ п" /* Би 2 */
 "MOVQ %% MM7, 0 (% 2) \ п"    / * Экстракт результат [0] * /
  
  / * Часть # 2: Умножения и дополнения
  *
  *
  D + = (uint64_t) а [1] * б [9]
       + (Uint64_t) а [2] * б [8]
       + (Uint64_t) а [3] * б [7]
       + (Uint64_t) а [4] * б [6]
       + (Uint64_t) а [5] * б [5]
       + (Uint64_t) а [6] * б [4]
       + (Uint64_t) а [7] * б [3]
       + (Uint64_t) а [8] * б [2]
       + (Uint64_t) а [9] * б [1]; * /
 
 "PMULUDQ %% MM1, %% MM2 \ п" / * A9 * b1 * /
 "PMULUDQ %% MM0, %% MM3 \ п" / * A8 * b2 * /
 "MOVD 28 (% 1), %% ММ6 \ п"  / * B7 * /
 "MOVD 32 (% 1), %% MM7 \ п" / * B8 * /
 "PMULUDQ %% ММ5, %% MM6 \ п" / * A3 * b7 * /
 "PMULUDQ %% MM4, %% MM7 \ п" / * A2 * b8 * /
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 4 (% 0), %% MM0 \ п"  / * A1 * /
 "MOVD 36 (% 1), %% ММ2 \ п"  / * B9 * /
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVD 16 (% 0), %% ММ1 \ п" / * A4 * /
 "PADDQ %% MM6, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 24 (% 1), %% ММ3 \ п" / * B6 * /
 "PMULUDQ %% MM0, %% MM2 \ п" / * A1 * b9 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A4 * b6 * /
 "MOVD 28 (% 0), %% ММ4 \ п" / * A7 * /
 "MOVD 12 (% 1), %% ММ5 \ п" / * B3 * /
 "PADDQ %% MM2, %% MM7 \ п"
 "MOVD 20 (% 0), %% MM0 \ п"  / * A5 * /
 "MOVD 24 (% 0), %% ММ1 \ п" / * A6 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 20 (% 1), %% ММ2 \ п"  / * B5 * /
 "MOVD 16 (% 1), %% ММ3 \ п" / * B4 * /
 "PMULUDQ %% MM0, %% MM2 \ п" / * A5 * b5 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A6 * b4 * /
 "PMULUDQ %% MM4, %% ММ5 \ п" / * A7 * b3 * /
 "MOVD 20 (% 1), %% ММ6 \ п" / * B5 * /
 "PADDQ %% MM2, %% MM7 \ п"
 "MOVD 16 (% 0), %% ММ2 \ п"  / * A4 * /
 "PADDQ %% ММ5, %% MM7 \ п"
 "PADDQ %% MM3, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 24 (% 1), %% ММ5 \ п"  / * B6 * /
 "MOVQ %% MM7, 8 (% 2) \ п"   / * Экстракт результат [1] * /  
 
   / * Часть # 3: Умножения и дополнения
  *
  * = D + (uint64_t) а [2] * б [9]
       + (Uint64_t) а [3] * б [8]
       + (Uint64_t) а [4] * б [7]  
       + (Uint64_t) а [5] * б [6]
       + (Uint64_t) а [6] * б [5]
       + (Uint64_t) а [7] * б [4]
       + (Uint64_t) а [8] * б [3]
       + (Uint64_t) а [9] * б [2]; * /

 "PMULUDQ %% MM1, %% MM6 \ п" / * A6 * b5 * /
 "MOVD 16 (% 1), %% MM7 \ п"  / * B4 * /
 "PMULUDQ %% MM0, %% ММ5 \ п" / * A5 * b6 * /
 "PMULUDQ %% MM4, %% MM7 \ п" / * A7 * b4 * /
 "MOVD 36 (% 1), %% ММ3 \ п"  / * B9 * /
 "MOVD 12 (% 0), %% ММ1 \ п" / * A3 * /
 "PADDQ %% MM6, %% ММ5 \ п"
 "MOVD 32 (% 1), %% ММ4 \ п" / * B8 * /
 "PADDQ %% ММ5, %% MM7 \ п"  / * Результат учета дополнений в mm7 * /
 "MOVD 8 (% 0), %% MM0 \ п"  / * A2 * /
 "MOVD 28 (% 1), %% ММ5 \ п"  / * B7 * /
 "PMULUDQ %% MM1, %% MM4 \ п" / * A3 * b8 * /
 "PMULUDQ %% MM2, %% ММ5 \ п" / * A4 * b7 * /
 "PMULUDQ %% MM0, %% MM3 \ п" / * A2 * b9 * /
 "MOVD 12 (% 1), %% ММ6 \ п"  / * B3 * /
 "PADDQ %% MM4, %% MM7 \ п"
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVD 36 (% 0), %% ММ4 \ п" / * A9 * /
 "MOVD 32 (% 0), %% ММ5 \ п"  / * A8 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 8 (% 1), %% ММ3 \ п"  /*Би 2 */
 "PMULUDQ %% ММ5, %% MM6 \ п" / * A8 * b3 * /
 "PMULUDQ %% MM4, %% MM3 \ п" / * A9 * b2 - (порядок b2 * a9) * /
 "MOVD 12 (% 1), %% MM0 \ п"  / * B3 * /
 "PADDQ %% MM6, %% MM7 \ п"
 "MOVD 32 (% 1), %% ММ6 \ п"  / * B8 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Результат учета дополнений в mm7 * /  
 "MOVD 16 (% 1), %% ММ3 \ п"  / * B4 * /
 "MOVQ %% MM7, 16 (% 2) \ п"   / * Экстракт результат [2] * /  
 
  / * Часть # 4: Умножения и дополнения
  *
  *
  * = D + (uint64_t) а [3] * б [9]
       + (Uint64_t) а [4] * б [8]
       + (Uint64_t) а [5] * б [7]
       + (Uint64_t) а [6] * б [6]
       + (Uint64_t) а [7] * б [5]
       + (Uint64_t) а [8] * б [4]
       + (Uint64_t) а [9] * б [3]; * /

 "PMULUDQ %% MM4, %% MM0 \ п" / * A9 * b3 * /
 "MOVD 36 (% 1), %% MM7 \ п" / * B9 * /
 "PMULUDQ %% ММ5, %% MM3 \ п" / * A8 * b4 * /
 "PMULUDQ %% MM2, %% MM6 \ п" / * A4 * b8 * /
 "PMULUDQ %% MM1, %% MM7 \ п" / * A3 * b9 * /  
 "PADDQ %% MM0, %% MM3 \ п"
 "MOVD 24 (% 1), %% ММ4 \ п"  / * B6 * /
 "MOVD 20 (% 1), %% ММ5 \ п" / * B5 * /
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVD 20 (% 0), %% MM0 \ п"  / * A5 * /
 "MOVD 28 (% 0), %% ММ2 \ п"  / * A7 * /
 "PADDQ %% MM6, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 24 (% 0), %% ММ6 \ п"  / * A6 * /
 "MOVD 28 (% 1), %% ММ3 \ п"  / * B7 * /
 "PMULUDQ %% MM2, %% ММ5 \ п" / * A7 * b5 * /
 "PMULUDQ %% MM6, %% MM4 \ п" / * A6 * b6 * /
 "PMULUDQ %% MM0, %% MM3 \ п" / * A5 * b7 * /
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVD 16 (% 0), %% ММ1 \ п"  / * A4 * /  
 "PADDQ %% MM4, %% MM7 \ п"
 "MOVD 32 (% 1), %% ММ5 \ п"  / * B8 * /  
 "PADDQ %% MM3, %% MM7 \ п"
 "MOVD 28 (% 1), %% ММ4 \ п"  / * B7 * /
 "MOVQ %% MM7, 24 (% 2) \ п"   / * Экстракт результат [3] * /  
 
  / * Часть # 5: Умножения и дополнения
  *  
        D + = (uint64_t) а [4] * б [9]
       + (Uint64_t) а [5] * б [8]
       + (Uint64_t) а [6] * б [7]
       + (Uint64_t) а [7] * б [6]
       + (Uint64_t) а [8] * б [5]
       + (Uint64_t) а [9] * б [4]; * /
    
 "PMULUDQ %% MM6, %% MM4 \ п" / * A6 * b7 * /
 "MOVD 24 (% 1), %% ММ3 \ п" / * B6 * /
 "MOVD 36 (% 1), %% MM7 \ п"  / * B9 * /
 "PMULUDQ %% MM0, %% ММ5 \ п" / * A5 * b8 * /
 "PMULUDQ %% MM2, %% MM3 \ п" / * A7 * b6 * /
 "PMULUDQ %% MM1, %% MM7 \ п" / * A4 * b9 * /
 "PADDQ %% MM4, %% ММ5 \ п"
 "MOVD 36 (% 0), %% ММ4 \ п"  / * A9 * /
 "PADDQ %% ММ5, %% MM3 \ п"
 "MOVD 20 (% 1), %% ММ5 \ п"  / * B5 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "MOVD 32 (% 0), %% ММ3 \ п" / * A8 * /
 "MOVD 16 (% 1), %% ММ1 \ п"  / * B4 * /
 "PMULUDQ %% MM3, %% ММ5 \ п" / * A8 * b5 * /
 "PMULUDQ %% MM4, %% MM1 \ п" / * A9 * b4 * /
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVD 28 (% 1), %% ММ3 \ п"  / * B7 * /
 "MOVD 32 (% 1), %% ММ5 \ п"  / * B8 * /  
 "PADDQ %% MM1, %% MM7 \ п"
 "MOVQ %% MM7, 32 (% 2) \ п"   / * Экстракт результат [4] * /  
 
  / * Часть # 6: Умножения и дополнения
  *
  *
  * = D + (uint64_t) а [5] * б [9]
       + (Uint64_t) а [6] * б [8]
       + (Uint64_t) а [7] * б [7]
       + (Uint64_t) а [8] * б [6]
       + (Uint64_t) а [9] * б [5];
       * /
  
 "PMULUDQ %% MM2, %% MM3 \ п" / * A7 * b7 * /
 "MOVD 20 (% 1), %% ММ1 \ п" / * B5 * /
 "MOVD 36 (% 1), %% MM7 \ п"  / * B9 * /
 "PMULUDQ %% MM6, %% ММ5 \ п" / * A6 * b8 * /
 "PMULUDQ %% MM4, %% MM1 \ п" / * A9 * b5 * /
 "PMULUDQ %% MM0, %% MM7 \ п" / * A5 * b9 * /
 "PADDQ %% MM3, %% ММ5 \ п"
 "MOVD 24 (% 1), %% ММ3 \ п"  / * B6 * /
 "PADDQ %% MM1, %% ММ5 \ п"
 "MOVD 32 (% 0), %% ММ1 \ п" / * A8 * /
 "PADDQ %% ММ5, %% MM7 \ п" / * Результат учета дополнений в mm7 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A8 * b6 * /
 "MOVD 24 (% 1), %% MM0 \ п" / * B6 * /
 "MOVD 32 (% 1), %% ММ5 \ п"  / * B8 * /  
 "PADDQ %% MM3, %% MM7 \ п"
 "MOVQ %% MM7, 40 (% 2) \ п"   / * Экстракт результат [5] * /  
 
   / * Часть # 7: Умножения и дополнения
  *
  *
  * = D + (uint64_t) а [6] * б [9]
       + (Uint64_t) а [7] * б [8]
       + (Uint64_t) а [8] * б [7]
       + (Uint64_t) а [9] * б [6]; * /
 
 "PMULUDQ %% MM4, %% MM0 \ п" / * A9 * b6 * /
 "MOVD 28 (% 1), %% ММ3 \ п"  / * B7 * /
 "MOVD 36 (% 1), %% MM7 \ п"  / * B9 * /  
 "PMULUDQ %% MM2, %% ММ5 \ п" / * A7 * b8 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A8 * b7 * /
 "PMULUDQ %% MM6, %% MM7 \ п" / * A6 * b9 * /
 "PADDQ %% MM0, %% ММ5 \ п"
 "PADDQ %% MM3, %% MM7 \ п"
 "MOVD 24 (% 1), %% MM0 \ п" / * B6 * /
 "PADDQ %% ММ5, %% MM7 \ п" / * Добавление результатов mm7 * /
 "MOVQ %% MM7, 48 (% 2) \ п"   / * Экстракт результат [6] * /
 
 
 / * Часть # 8: Умножения и дополнение 3 отдельных результатов
  *
  *  
       D + = (uint64_t) а [7] * б [9]
       + (Uint64_t) а [8] * б [8]
       + (Uint64_t) а [9] * б [7]; результат 7

       D + = (uint64_t) а [8] * б [9]
       + (Uint64_t) а [9] * б [8]; результат 8

      D + = (uint64_t) а [9] * б [9]; Результат 9 * /
    
  
 "MOVD 28 (% 1), %% ММ3 \ п"  / * B7 * /
 "MOVD 32 (% 1), %% ММ5 \ п"  / * B8 * /
 "MOVD 36 (% 1), %% MM7 \ п"  / * B9 * /  
 "PMULUDQ %% MM4, %% MM3 \ п" / * A9 * b7 * /
 "PMULUDQ %% MM1, %% ММ5 \ п" / * A8 * b8 * /
 "MOVQ %% MM7, %% MM6 \ п"  / * B9 * /  
 "PMULUDQ %% MM2, %% MM7 \ п" / * A7 * b9 * /
 "PADDQ %% MM3, %% ММ5 \ п"
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVQ %% MM6, %% MM3 \ п"  / * B9 * /  
 "MOVD 32 (% 1), %% ММ5 \ п"  / * B8 * /
 "MOVQ %% MM7, 56 (% 2) \ п"   / * Экстракт результат [7] * /
 "PMULUDQ %% MM1, %% MM6 \ п" / * A8 * b9 * /  
 "PMULUDQ %% MM4, %% ММ5 \ п" / * A9 * b8 * /
 "PMULUDQ %% MM4, %% MM3 \ п" / * A9 * b9 * /
 "MOVD 8 (% 0), %% MM7 \ п" / * A2 * /
 "PADDQ %% ММ5, %% MM6 \ п"
 "MOVQ %% ММ3, 72 (% 2) \ п"   / * Экстракт результат [9] * /
 "MOVQ %% ММ6, 64 (% 2) \ п"   / * Экстракт результат [8] * /
 
  / * Часть # 9: Умножения и дополнения
  *
  * С + = (uint64_t) а [0] * б [8]
       + (Uint64_t) а [1] * б [7]  
       + (Uint64_t) а [2] * б [6]  
       + (Uint64_t) а [3] * б [5]  
       + (Uint64_t) а [4] * б [4]
       + (Uint64_t) а [5] * б [3]
       + (Uint64_t) а [6] * б [2]
       + (Uint64_t) а [7] * б [1]
       + (Uint64_t) а [8] * б [0]; * /
 
  
 "PMULUDQ %% MM7, %% MM0 \ п" / * A2 * b6 * /
 "MOVD 0 (% 1), %% ММ3 \ п" / * B0 * /
 "PMULUDQ %% MM1, %% MM3 \ п" / * A8 * b0 * /
 "MOVD 4 (% 1), %% MM7 \ п" / * B1 * /
 "PMULUDQ %% MM2, %% MM7 \ п" / * A7 * b1 * /
 "MOVD 4 (% 0), %% ММ1 \ п" / * A1 * /
 "PADDQ %% MM0, %% MM3 \ п"
 "MOVD 20 (% 1), %% ММ4 \ п"  / * B5 * /  
 "PADDQ %% MM3, %% MM7 \ п"  
 "MOVD 12 (% 0), %% ММ2 \ п"  / * A3 * /
 "MOVD 28 (% 1), %% ММ5 \ п"  / * B7 * /
 "PMULUDQ %% MM2, %% MM4 \ п" / * A3 * b5 * /
 "MOVD 16 (% 0), %% ММ3 \ п"  / * A4 * /
 "MOVD 16 (% 1), %% ММ6 \ п" / * B4 * /
 "PMULUDQ %% MM1, %% ММ5 \ п" / * A1 * b7 * /
 "MOVD 0 (% 0), %% MM0 \ п" / * A0 * /
 "PMULUDQ %% MM6, %% MM3 \ п" / * B4 * a4 * /
 "MOVD 32 (% 1), %% ММ6 \ п"  / * B8 * /
 "PMULUDQ %% MM0, %% MM6 \ п" / * A0 * b8 * /
 "PADDQ %% MM4, %% ММ5 \ п"
 "MOVD 24 (% 0), %% ММ4 \ п" / * A6 * /
 "PADDQ %% MM6, %% MM3 \ п"
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVD 8 (% 1), %% ММ6 \ п"  /*Би 2*/
 "PADDQ %% MM3, %% MM7 \ п"
 "MOVD 12 (% 1), %% ММ5 \ п"  / * B3 * /
 "MOVD 20 (% 0), %% ММ3 \ п" / * A5 * /
 "PMULUDQ %% MM4, %% MM6 \ п" / * A6 * b2 * /
 "PMULUDQ %% MM3, %% ММ5 \ п" / * A5 * b3 * /
 "PADDQ %% MM6, %% MM7 \ п"
 "MOVD 0 (% 1), %% ММ4 \ п" / * B0 * /
 "PADDQ %% ММ5, %% MM7 \ п" / * Аддитивные результаты по mm7 * /
 "MOVD 8 (% 0), %% ММ3 \ п"  / * A2 * /  
 "MOVD 4 (% 1), %% ММ5 \ п"  / * B1 * /
 "MOVQ %% MM7, 80 (% 2) \ п"  / * Результат экстракта [10] * /
 
 
   / * Часть # 10: Умножения и дополнения
  *
  * С + = (uint64_t) а [0] * б [3]
       + (Uint64_t) а [1] * б [2]
       + (Uint64_t) а [2] * б [1]
       + (Uint64_t) а [3] * б [0]; result11  
  
       с + = (uint64_t) а [0] * б [1]
       + (Uint64_t) а [1] * б [0]; result12

        с = (uint64_t) а [0] * б [0]; result13      
      
           с + = (uint64_t) а [0] * б [2]
       + (Uint64_t) а [1] * б [1]
       + (Uint64_t) а [2] * б [0]; result14 * /
        

 "PMULUDQ %% MM4, %% MM2 \ п" / * B0 * a3 * /
 "PMULUDQ %% ММ5, %% MM3 \ п" / * B1 * a2 * /
 "MOVD 8 (% 1), %% MM7 \ п"  /*Би 2*/
 "MOVD 12 (% 1), %% ММ6 \ п"  / * B3 * /
 "PMULUDQ %% MM7, %% MM1 \ п" / * B2 * a1 * /
 "PMULUDQ %% MM6, %% MM0 \ п" / * B3 * a0 * /
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 8 (% 1), %% ММ2 \ п"  /*Би 2*/  
 "PADDQ %% MM1, %% MM0 \ п"  
 "MOVD 4 (% 1), %% ММ1 \ п"  / * B1 * /  
 "PADDQ %% MM0, %% MM3 \ п"  
 "MOVD 0 (% 1), %% MM0 \ п"  / * B0 * /  
 "MOVQ %% MM3, 88 (% 2) \ п"  / * Результат экстракта [11] * /  
 
 "MOVD 0 (% 0), %% ММ4 \ п" / * A0 * /
 "MOVQ %% MM0, %% MM3 \ п" / * B0 * /
 "MOVD 4 (% 0), %% ММ5 \ п"  / * A1 * /
 "MOVD 8 (% 0), %% MM7 \ п"  / * A2 * /
 "MOVQ %% MM1, %% MM6 \ п" / * B1 * /
 "PMULUDQ %% ММ5, %% MM3 \ п" / * A1 * b0 * /
 "PMULUDQ %% MM4, %% MM6 \ п" / * A0 * b1 * /
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVQ %% MM0, %% MM3 \ п" / * B0 * /
 "MOVQ %% ММ6, 96 (% 2) \ п"  / * Результат экстракта [12] * /  
 "PMULUDQ %% MM4, %% MM3 \ п" / * A0 * b0 * /
 "PMULUDQ %% MM4, %% MM2 \ п" / * A0 * b2 * /
 "MOVQ %% мм3 104 (% 2) \ п"  / * Результат экстракта [13] * /    
 "MOVQ %% MM1, %% MM6 \ п" / * B1 * /
 "PMULUDQ %% ММ5, %% MM6 \ п" / * A1 * b1 * /
 "MOVQ %% MM0, %% MM3 \ п" / * B0 * /
 "PMULUDQ %% MM7, %% MM3 \ п" / * A2 * b0 * /  
 "PADDQ %% MM2, %% MM6 \ п"
 "PADDQ %% MM6, %% MM3 \ п"
 "MOVD 16 (% 1), %% ММ2 \ п"  / * B4 * /  
 "MOVQ %% ММ3, 112 (% 2) \ п"  / * Результат экстракта [14] * /  
 
  / * Часть # 11: Умножения и дополнения
  *
  *  
     с + = (uint64_t) а [0] * б [4]  
       + (Uint64_t) а [1] * б [3]  
       + (Uint64_t) а [2] * б [2]
       + (Uint64_t) а [3] * б [1]
       + (Uint64_t) а [4] * б [0] * /

 "PMULUDQ %% MM4, %% MM2 \ п" / * A0 * b4 * /
 "MOVD 16 (% 0), %% ММ3 \ п"  / * A4 * /    
 "MOVD 12 (% 0), %% ММ6 \ п" / * A3 * /
 "PMULUDQ %% MM0, %% MM3 \ п" / * B0 * a4 * /
 "PMULUDQ %% MM1, %% MM6 \ п" / * B1 * a3 * /  
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 12 (% 1), %% ММ2 \ п"  / * B3 * /    
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVD 8 (% 1), %% ММ3 \ п"  /*Би 2*/  
 "PMULUDQ %% ММ5, %% MM2 \ п" / * A1 * b3 * /
 "PMULUDQ %% MM7, %% MM3 \ п" / * A2 * b2 * /
 "PADDQ %% MM2, %% MM6 \ п"
 "MOVD 20 (% 1), %% ММ2 \ п"  / * B5 * /    
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVD 20 (% 0), %% ММ3 \ п"  / * A5 * /    
 "MOVQ %% ММ6, 120 (% 2) \ п"  / * Результат экстракта [15] * /  
 
   / * Часть # 12: Умножения и дополнения
  *
  * С + = (uint64_t) а [0] * б [5]
       + (Uint64_t) а [1] * б [4]
       + (Uint64_t) а [2] * б [3]
       + (Uint64_t) а [3] * б [2]
       + (Uint64_t) а [4] * б [1]
       + (Uint64_t) а [5] * б [0] * /  
  
 "PMULUDQ %% MM4, %% MM2 \ п" / * A0 * b5 * /
 "MOVD 16 (% 0), %% ММ6 \ п" / * A4 * /
 "PMULUDQ %% MM0, %% MM3 \ п" / * B0 * a5 * /
 "PMULUDQ %% MM1, %% MM6 \ п" / * B1 * a4 * /  
 "PADDQ %% MM2, %% MM3 \ п"
 "MOVD 16 (% 1), %% ММ2 \ п"  / * B4 * /  
 "PADDQ %% MM3, %% MM6 \ п" / * Добавление результатов MM6 * /
 "MOVD 12 (% 1), %% ММ3 \ п"  / * B3 * /    
 "PMULUDQ %% ММ5, %% MM2 \ п" / * A1 * b4 * /
 "PMULUDQ %% MM7, %% MM3 \ п" / * A2 * b3 * /
 "MOVD 8 (% 1), %% MM0 \ п"  /*Би 2*/  
 "PADDQ %% MM2, %% MM6 \ п"
 "MOVD 12 (% 0), %% ММ2 \ п" / * A3 * /
 "PADDQ %% MM3, %% MM6 \ п"
 "PMULUDQ %% MM0, %% MM2 \ п" / * B2 * a3 * /    
 "MOVD 24 (% 0), %% ММ3 \ п"  / * A6 * /  
 "MOVD 0 (% 1), %% MM0 \ п"  / * B0 * /  
 "PADDQ %% MM2, %% MM6 \ п" / * Все дополнения в конечном итоге в MM6 * /
 "MOVD 24 (% 1), %% ММ2 \ п"  / * B6 * /  
 "MOVQ %% ММ6, 128 (% 2) \ п"  / * Результат экстракта [16] * /  
  
    / * Часть # 13: Умножения и дополнения
  *  
  * С + = (uint64_t) а [0] * б [6]
       + (Uint64_t) а [1] * б [5]
       + (Uint64_t) а [2] * б [4]
       + (Uint64_t) а [3] * б [3]
       + (Uint64_t) а [4] * б [2]
       + (Uint64_t) а [5] * б [1]
       + (Uint64_t) а [6] * б [0]; * /
  
 "PMULUDQ %% MM0, %% MM3 \ п" / * A6 * b0 * /
 "MOVD 20 (% 0), %% ММ6 \ п" / * A5 * /  
 "PMULUDQ %% MM4, %% MM2 \ п" / * B6 * a0 * /
 "PMULUDQ %% MM1, %% MM6 \ п" / * A5 * b1 * /    
 "PADDQ %% MM2, %% MM3 \ п"
 "PADDQ %% MM3, %% MM6 \ п" / * Добавление всех результатов на MM6 * /
 "MOVD 20 (% 1), %% ММ2 \ п"  / * B5 * /  
 "MOVD 16 (% 1), %% ММ3 \ п"  / * B4 * /    
 "PMULUDQ %% ММ5, %% MM2 \ п" / * A1 * b5 * /
 "PMULUDQ %% MM7, %% MM3 \ п" / * A2 * b4 * /
 "MOVD 8 (% 1), %% ММ4 \ п"  /*Би 2*/  
 "MOVD 12 (% 1), %% ММ1 \ п"  / * B3 * /  
 "PADDQ %% MM2, %% MM6 \ п"
 "MOVD 12 (% 0), %% ММ2 \ п"  / * A3 * /  
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVD 16 (% 0), %% ММ3 \ п"  / * A4 * /    
 "PMULUDQ %% MM1, %% MM2 \ п" / * B3 * a3 * /
 "PMULUDQ %% MM4, %% MM3 \ п" / * B2 * a4 * /
 "PADDQ %% MM2, %% MM6 \ п"
 "MOVD 4 (% 1), %% ММ1 \ п"  / * B1 * /
 "MOVD 24 (% 0), %% ММ2 \ п" / * A6 * /
 "PADDQ %% MM3, %% MM6 \ п"
 "MOVD 0 (% 0), %% ММ4 \ п"  / * A0 * /  
 "MOVQ %% ММ6, 136 (% 2) \ п"  / * Результат экстракта [17] * /  
  
 / * Часть # 14: Умножения и дополнения
  *  
  * С + = (uint64_t) а [0] * б [7]
       + (Uint64_t) а [1] * б [6]  
       + (Uint64_t) а [2] * б [5]
       + (Uint64_t) а [3] * б [4]
       + (Uint64_t) а [4] * б [3]
       + (Uint64_t) а [5] * б [2]
       + (Uint64_t) а [6] * б [1]  
       + (Uint64_t) а [7] * б [0]; * /
      
 "PMULUDQ %% MM2, %% MM1 \ п" / * A6 * b1 * /
 "MOVD 28 (% 0), %% ММ6 \ п" / * A7 * /
 "MOVD 28 (% 1), %% ММ3 \ п" / * B7 * /  
 "PMULUDQ %% MM6, %% MM0 \ п" / * A7 * b0 * /
 "PMULUDQ %% MM3, %% MM4 \ п" / * B7 * a0 * /    
 "MOVD 24 (% 1), %% ММ6 \ п" / * B6 * /
 "MOVD 20 (% 1), %% ММ2 \ п" / * B5 * /
 "PMULUDQ %% MM6, %% ММ5 \ п" / * B6 * a1 * /
 "PMULUDQ %% MM2, %% MM7 \ п" / * B5 * a2 * /
 "PADDQ %% MM0, %% MM1 \ п"
 "MOVQ 8 (% 2), %% ММ3 \ п"/ * Упреждающей result1 * /
 "PADDQ %% MM4, %% ММ5 \ п"
 "MOVD 12 (% 0), %% MM0 \ п" / * A3 * /
 "MOVD 8 (% 1), %% ММ6 \ п" /*Би 2*/
 "PADDQ %% MM1, %% ММ5 \ п"
 "MOVD 20 (% 0), %% ММ2 \ п" / * A5 * /
 "MOVD 12 (% 1), %% ММ4 \ п" / * B3 * /
 "PADDQ %% ММ5, %% MM7 \ п"
 "PMULUDQ %% MM2, %% MM6 \ п" / * A5 * b2 * /
 "MOVD 16 (% 0), %% ММ1 \ п" / * A4 * /
 "MOVD 16 (% 1), %% ММ5 \ п" / * B4 * /
 "PMULUDQ %% MM1, %% MM4 \ п" / * A4 * b3 * /
 "PMULUDQ %% MM0, %% ММ5 \ п" / * A3 * b4 * /    
 "PADDQ %% MM6, %% MM4 \ п"
 "MOVD 0 (% 4), %% ММ2 \ п"  / * Упреждающей M в MM2 * /
 "PADDQ %% MM4, %% ММ5 \ п"
 "PADDQ %% MM7, %% ММ5 \ п"
 "MOVQ 0 (% 2), %% ММ6 \ п" / * Предвыборки д в результате из [0] * /
 "MOVQ %% MM2, %% MM0 \ п" / * М вторичного хранения * /
 "MOVQ %% ММ5, 144 (% 2) \ п"  / * Результат экстракта [18] * /  
  

  "MOVQ 104 (% 2), %% MM7 \ п" / * С в результате из [13] * /
  "PAND %% MM6, %% MM2 \ п"   / * Г [9] = d & M; * /
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /    
  "MOVD 4 (% 4), %% ММ4 \ п"  / * R0 до MM4 * /  
  "MOVD %% ММ2, 36 (% 3) \ п" / * Экстракт г [9] = d & M; * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) результат [1] * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M назад в мм2 * /
  
  "MOVQ 16 (% 2), %% ММ3 \ п"  / * Упреждающей result2 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [2] * /
  "MOVQ 96 (% 2), %% ММ5 \ п"  / * Упреждающей result12 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 0 (% 3) \ п" / * Экспорт t0 / г [0] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [12] * /    
  
  "MOVQ 24 (% 2), %% ММ3 \ п"/ * Упреждающей result3 * /  
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [3] * /
  "MOVQ 112 (% 2), %% ММ5 \ п"  / * Упреждающей result14 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 4 (% 3) \ п" / * Экспорт t1 / г [1] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [14] * /    
  
  "MOVQ 32 (% 2), %% ММ3 \ п"/ * Упреждающей result4 * /    
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) результат [4] * /
  "MOVQ 88 (% 2), %% ММ5 \ п"  / * Упреждающей result11 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 8 (% 3) \ п" / * Экспорт t2 / г [2] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /  
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [11] * /    

  "MOVQ 40 (% 2), %% ММ3 \ п"/ * Упреждающей result5 * /    
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [5] * /
  "MOVQ 120 (% 2), %% ММ5 \ п"  / * Упреждающей result15 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 12 (% 3) \ п" / * Экспорт t3 / г [3] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /    
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [15] * /    
  
  "MOVQ 48 (% 2), %% ММ3 \ п"/ * Упреждающей result6 * /    
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) результат [6] * /
  "MOVQ 128 (% 2), %% ММ5 \ п"  / * Упреждающей result16 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 16 (% 3) \ п" / * Экспорт t4 / г [4] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /  
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [16] * /    

  "MOVQ 56 (% 2), %% ММ3 \ п"/ * Упреждающей result7 * /    
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) результат [7] * /
  "MOVQ 136 (% 2), %% ММ5 \ п"  / * Упреждающей result16 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 20 (% 3) \ п" / * Экспорт t5 / г [5] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /    
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [16] * /      
  
  "MOVQ 64 (% 2), %% ММ3 \ п"/ * Упреждающей result8 * /    
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [8] * /
  "MOVQ 144 (% 2), %% ММ5 \ п"  / * Упреждающей result18 * /        
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 24 (% 3) \ п" / * Экспорт t6 / г [6] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /  
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [18] * /      
  
  "MOVQ 72 (% 2), %% ММ3 \ п"/ * Упреждающей result9 * /  
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [9] * /
  "MOVQ 80 (% 2), %% ММ5 \ п"  / * Упреждающей result10 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 28 (% 3) \ п" / * Экспорт T7 / г [7] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /    
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [10] * /      
  
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "MOVQ %% MM0, %% MM2 \ п" / * Клонирование M в мм2 * /
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 32 (% 3) \ п" / * Экспорт t8 / г [8] = с & M * /

  "PMULUDQ %% MM6, %% MM4 \ п" / * D * R 0 * /
  "PSRLQ $ 4, %% MM0 \ п"    / * M >>= 4 * /  
  "MOVD 36 (% 3), %% ММ1 \ п" / * R [9] * /    
  "PADDQ %% MM4, %% MM7 \ п" / * = С + d * R0 * /
  "PADDQ %% MM1, %% MM7 \ п" / * С + = г [9] ===> с + = d * R 0 + г [9] * /  

  "PAND %% MM7, %% MM0 \ п"  / * С & (M >> 4) * /
  "MOVD %% MM0, 36 (% 3) \ п"  / * R [9] = с & (M >> 4) * /

  "PSRLQ $ 22, %% MM7 \ п"    / * С >>= 22 * ​​/  
  "PSLLQ $ 14, %% MM6 \ п" / * Д * (R1 << 4). Так как (R1 << 4) равен 16384, это по существу левый сдвиг на 14 * /
  "PADDQ %% MM6, %% MM7 \ п" / * = С + d * (R1 << 4) * /
 
  
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с * /
  "PSLLQ $ 6, %% MM7 \ п" / * Результат с * (R 1 >> 4), которая равна с сдвигается влево на 6, так как (R1 >> 4) = 64 * /    

  "MOVQ %% MM3, %% MM0 \ п"     / * Это ручная попытка умножения C с x3D1 или 977 десятичными, путем сдвига и добавления копий с ... * /
  "MOVQ %% MM3, %% MM1 \ п"     / * Все это сегмент, это, на самом деле, просто (с * 977) одиночная линия умножения * /
  "MOVQ %% MM3, %% MM6 \ п"     / *, Которые по каким-то причинам не хочет работать иначе с простой PMULUDQ с * 977 * константой /
  "MOVQ %% MM3, %% MM4 \ п"
  "MOVQ %% MM3, %% ММ5 \ п"  
  "PSLLQ $ 9, %% MM0 \ п" / * X512 * /    
  "PSLLQ $ 8, %% MM1 \ п" / * X256 * /    
  "PSLLQ $ 7, %% MM6 \ п" / * X128 * /      
  "PSLLQ $ 6, %% MM4 \ п" / * 64 * /        
  "PSLLQ $ 4, %% ММ5 \ п" / * Х16 * / / * 512 + 256 + 128 + 64 = 976x, так что +1 добавить сверху = 977 или 0x3D1 * /
  "PADDQ %% MM3, %% MM0 \ п"
  "PADDQ %% MM1, %% MM6 \ п"
  "MOVD 0 (% 3), %% ММ3 \ п"  / * Предвыборки г [0] для MM3 * /    
  "PADDQ %% MM4, %% MM0 \ п"
  "PADDQ %% MM6, %% MM0 \ п"  
  "PADDQ %% MM0, %% ММ5 \ п"     / * Результат с * (R0 >> 4) * /    
  
  "PADDQ %% MM3, %% ММ5 \ п"  / * Д = г [0] + с (R 0 >> 4) * /
  "MOVD 4 (% 3), %% ММ4 \ п"  / * Г [1] ММ4 * /  
  "MOVD 8 (% 3), %% MM0 \ п"  / * Г [2], чтобы ММ5 * /    
  "MOVQ %% ММ5, %% MM3 \ п" / * * Клонирование д /

  "PAND %% MM2, %% ММ5 \ п" / * Д&M * /
  "PSRLQ $ 26, %% MM3 \ п"    / * Д >>= 26 * /    
  "PADDQ %% MM7, %% MM4 \ п" / * C * (R 1 >> 4) + г [1] * /
  "PADDQ %% MM4, %% MM3 \ п" / * D + = C * (R 1 >> 4) + г [1]; * /
  "MOVD %% ММ5, 0 (% 3) \ п" / * Экспорт д к г [0] * /
  "MOVQ %% MM3, %% MM7 \ п" / * * Клонирование д /
  
  "PAND %% MM2, %% MM7 \ п" / * Д&M * /
  "PSRLQ $ 26, %% MM3 \ п"    / * Д >>= 26 * /      
  "PADDQ %% MM0, %% MM3 \ п"  / * Й + = г [2]; * /
  "MOVD %% MM7, 4 (% 3) \ п"  / * Г [1] = d & M; * /
  "MOVD %% ММ3, 8 (% 3) \ п" / * Г [2] = д; * /
  "EMMS \ п"

:
: "Q"(А), "Q"(Б), "Q"(Результат), "Q"(р), "S"(Tempstor)
: "Память", "% mm0", "% mm1", "% мм2", "% мм3", "% mm4", "% ММ5", "% MM6", "% MM7"
);
}

AlexGR сейчас офлайн Пожаловаться на AlexGR   Ответить с цитированием Мультицитирование сообщения от AlexGR Быстрый ответ на сообщение AlexGR

23 апреля 2017, 9:16:38 AM   # 6
 
 
Сообщения: 1442
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Код:
SECP256K1_INLINE статической силы secp256k1_fe_sqr_inner (uint32_t * г, Const uint32_t * а) {
  / * Uint64_t с, д; * /
    uint64_t результат [17]; / * Температура хранения массива * /
    uint32_t tempstor [2]; / * Температура хранения массива * /
    Const uint32_t М = 0x3FFFFFFUL, R0 = 0x3D10UL / *, R 1 = 0x400UL * /;

  tempstor [0] = М;
  tempstor [1] = R0;
/ * Tempstor [2] для R1 не требуется. Это 1024, так сворачивает налево на 10 вместо * /

  __asm__ __volatile __ (  
 / * Часть # 1: Умножения и дополнения
  *
  *  
  * (Uint64_t) (а [0] * 2) * а [1] = result0
  *
  * (Uint64_t) (а [0] * 2) * а [2]
       + (Uint64_t) а [1] * а [1] = результат1
            
      (Uint64_t) (а [0] * 2) * а [3]
       + (Uint64_t) (а [1] * 2) * а [2] = результат2
      
       (Uint64_t) (а [0] * 2) * а [4] = result3
       + (Uint64_t) (а [1] * 2) * а [3]
       + (Uint64_t) а [2] * а [2];        
      
      (Uint64_t) (а [0] * 2) * а [5]
       + (Uint64_t) (а [1] * 2) * а [4] = result4
       + (Uint64_t) (а [2] * 2) * а [3]; * /

 "MOVD 0 (% 0), %% MM0 \ п"  / * A0 * /
 "MOVD 8 (% 0), %% ММ2 \ п"  / * A2 * /
 "MOVD 4 (% 0), %% ММ1 \ п" / * A1 * /
 "MOVQ %% MM0, %% MM6 \ п" / * Клонирование а0 MM6 * /
 "MOVQ %% MM0, %% MM4 \ п" / * Клонирование а0 mm4 * /
 "MOVQ %% MM1, %% ММ5 \ п" / * Клонирование а1 ММ5 * /
 "PMULUDQ %% MM2, %% MM6 \ п" / * A2 * a0 * /
 "MOVQ %% MM1, %% MM7 \ п"  / * Клонирование а1 mm7 * /
 "PMULUDQ %% ММ5, %% ММ5 \ п" / * A1 * a1 * /
 "PMULUDQ %% MM0, %% MM7 \ п" / * A0 * a1 * /
 "MOVD 12 (% 0), %% ММ3 \ п" / * A3 * /
 "PADDQ %% MM6, %% MM6 \ п"  / * Удвоилась a2 * a0 * /
 "PADDQ %% ММ5, %% MM6 \ п" / * (А2 * а0 * 2) + (а1 * а1) * /
 "PADDQ %% MM7, %% MM7 \ п" / * Удвоилась a0 * a1 * /
 "MOVQ %% MM1, %% ММ5 \ п" / * Клонирование а1 ММ5 * /
 "MOVQ %% ММ6, 8 (% 1) \ п" / * Результат [1] * /  
 "MOVQ %% MM7, 0 (% 1) \ п" / * Результат [0] * /
 
 "PMULUDQ %% MM3, %% MM4 \ п" / * A3 * a0 * /
 "PMULUDQ %% MM2, %% ММ5 \ п" / * A2 * a1 * /  
 "MOVD 16 (% 0), %% MM7 \ п" / * А4 mm7 * /
 "PADDQ %% MM4, %% ММ5 \ п" / * (A3 * a0) + (a2 * a1) * /
 "PADDQ %% ММ5, %% ММ5 \ п" / * (A3 * a0) + (a2 * a1) в два раза * /
 "MOVQ %% ММ5, 16 (% 1) \ п" / * Результат [2] * /  
 
 "MOVQ %% MM2, %% MM6 \ п" / * Клонирование а2 MM6 * /
 "MOVQ %% MM7, %% MM4 \ п" / * Клонирование а4 mm4 * /
 "MOVQ %% MM3, %% ММ5 \ п" / * Клонирование а3 ММ5 * /
 "PMULUDQ %% MM0, %% MM7 \ п" / * A0 * a4 * /
 "PMULUDQ %% MM1, %% ММ5 \ п" / * A1 * a3 * /
 "PMULUDQ %% MM2, %% MM6 \ п" / * A2 * a2 * /  
 "PADDQ %% MM7, %% ММ5 \ п" / * (A0 * a4) + (a1 * a3) * /
 "PADDQ %% ММ5, %% ММ5 \ п"/ * Удвоение (a0 * a4) + (a1 * a3) * /
 "MOVD 20 (% 0), %% MM7 \ п" / * Упреждающей a5 в mm7 * /
 "PADDQ %% MM6, %% ММ5 \ п" / * (2 * (а0 * а4) + (а1 * а3)) + (а2 * а2) * /
 "MOVQ %% ММ5, 24 (% 1) \ п" / * Результат [3] * /  
 
 "MOVQ %% MM4, %% MM6 \ п" / * Клонирование а4 MM6 * /
 "PMULUDQ %% MM0, %% MM7 \ п" / * A0 * a5 * /
 "MOVQ %% MM3, %% ММ5 \ п" / * Клонирование а3 ММ5 * /
 "PMULUDQ %% MM1, %% MM6 \ п" / * A1 * a4 * /
 "PMULUDQ %% MM2, %% ММ5 \ п" / * A2 * a3 * /
 "PADDQ %% MM6, %% MM7 \ п"
 "MOVD 24 (% 0), %% ММ6 \ п" / * Упреждающей a6 в MM6 * /
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVD 20 (% 0), %% ММ5 \ п" / * Упреждающей a5 в ММ5 * /
 "PADDQ %% MM7, %% MM7 \ п" / * Добавление и удвоение a1 * a4 + a0 * a5 + a2 * a3 * /
 "MOVQ %% MM7, 32 (% 1) \ п" / * Результат [4] * /  
 
 / * Часть # 2: Умножения и дополнения
  *  
       (Uint64_t) (а [0] * 2) * а [6]
       + (Uint64_t) (а [1] * 2) * а [5]
       + (Uint64_t) (а [2] * 2) * а [4] = result5
       + (Uint64_t) а [3] * а [3]
      
       (Uint64_t) (а [0] * 2) * а [7]
       + (Uint64_t) (а [1] * 2) * а [6]
       + (Uint64_t) (а [2] * 2) * а [5]
       + (Uint64_t) (а [3] * 2) * а [4] = result6
      
        (Uint64_t) (а [0] * 2) * а [8]
       + (Uint64_t) (а [1] * 2) * а [7]
       + (Uint64_t) (а [2] * 2) * а [6]
       + (Uint64_t) (а [3] * 2) * а [5]
       + (Uint64_t) а [4] * а [4] = result7 * /

 "PMULUDQ %% MM3, %% MM3 \ п" / * A3 * a3 * /
 "MOVQ %% MM4, %% MM7 \ п" / * А4 mm7 * /
 "PMULUDQ %% MM0, %% MM6 \ п" / * A0 * a6 * /
 "PMULUDQ %% MM1, %% ММ5 \ п" / * A1 * a5 * /
 "PMULUDQ %% MM2, %% MM7 \ п" / * A2 * a4 * /
 "PADDQ %% MM6, %% ММ5 \ п"
 "MOVD 24 (% 0), %% ММ6 \ п" / * Упреждающей a6 в MM6 * /  
 "PADDQ %% ММ5, %% MM7 \ п"
 "MOVD 20 (% 0), %% ММ5 \ п" / * Упреждающей a5 в ММ5 * /  
 "PADDQ %% MM7, %% MM7 \ п" / * Добавление и удвоение а0 * a6 + a1 * a5 + a2 * a4 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Добавление не удвоением a3 * a3 * /
 "MOVD 12 (% 0), %% ММ3 \ п" / * Упреждающий а3 мм3 * /
 "MOVQ %% MM7, 40 (% 1) \ п" / * Результат [5] * /  
 
 "PMULUDQ %% MM2, %% ММ5 \ п" / * A2 * a5 * /
 "PMULUDQ %% MM1, %% MM6 \ п" / * A1 * a6 * /
 "PMULUDQ %% MM3, %% MM4 \ п" / * A3 * a4 * /
 "MOVD 28 (% 0), %% MM7 \ п" / * A7 в mm7 * /
 "PMULUDQ %% MM0, %% MM7 \ п" / * A0 * a7 * /
 "PADDQ %% ММ5, %% MM6 \ п"
 "PADDQ %% MM6, %% MM4 \ п"   / * Добавление 4 предыдущих умножений * /
 "MOVD 24 (% 0), %% ММ5 \ п" / * Упреждающей a6 в ММ5 * /
 "PADDQ %% MM4, %% MM7 \ п"
 "MOVD 20 (% 0), %% ММ4 \ п" / * Упреждающей a5 в mm4 * /  
 "PADDQ %% MM7, %% MM7 \ п"  / * Удваивая результат * /
 "MOVQ %% MM7, 48 (% 1) \ п" / * Результат [6] * /    

 "PMULUDQ %% MM4, %% MM3 \ п" / * A5 * a3 * /
 "MOVD 28 (% 0), %% ММ6 \ п" / * A7 в MM6 * /
 "PMULUDQ %% ММ5, %% MM2 \ п" / * A6 * a2 * /
 "MOVD 32 (% 0), %% MM7 \ п" / * A8 в mm7 * /  
 "PMULUDQ %% MM6, %% MM1 \ п" / * A7 * a1 * /
 "MOVD 16 (% 0), %% ММ4 \ п" / * А4 mm4 * /  
 "PMULUDQ %% MM7, %% MM0 \ п" / * A8 * a0 * /
 "PMULUDQ %% MM4, %% MM4 \ п" / * A4 * a4 * /
 "PADDQ %% MM3, %% MM2 \ п"
 "PADDQ %% MM2, %% MM1 \ п"   / * Добавляя первые 4 умножений * /
 "PADDQ %% MM1, %% MM0 \ п"
 "MOVD 36 (% 0), %% ММ2 \ п" / * A9 в мм2 * /  
 "PADDQ %% MM0, %% MM0 \ п"  / * Удваивая результат первых 4 умножений * /
 "MOVQ %% MM7, %% MM1 \ п"  / * Клонирование a8 в mm1 * /
 "PADDQ %% MM4, %% MM0 \ п"  / * Добавление не-удвоилась a4 * a4 * /
 "MOVQ %% MM2, %% MM3 \ п"  / * Клонирование a9 в мм3 * /
 "MOVQ %% MM0, 56 (% 1) \ п" / * Результат [7] * /  
 
/ * Часть # 3: Умножения и дополнения
  *  
  * (Uint64_t) а [9] * а [9] = result8
      
       (Uint64_t) (а [8] * 2) * а [9] = result9
          
       (Uint64_t) (а [7] * 2) * а [9]
       + (Uint64_t) а [8] * а [8] = result10
      
       (Uint64_t) (а [6] * 2) * а [9]
       + (Uint64_t) (а [7] * 2) * а [8] = result11    
      
       (Uint64_t) (а [5] * 2) * а [9]
       + (Uint64_t) (а [6] * 2) * а [8] = result12
       + (Uint64_t) а [7] * а [7]
      
       (Uint64_t) (а [4] * 2) * а [9]
       + (Uint64_t) (а [5] * 2) * а [8] = result13
       + (Uint64_t) (а [6] * 2) * а [7]
      
       (Uint64_t) (а [3] * 2) * а [9]
       + (Uint64_t) (а [4] * 2) * а [8]
       + (Uint64_t) (а [5] * 2) * а [7]
       + (Uint64_t) а [6] * а [6] = result14 * /

 "PMULUDQ %% MM3, %% MM3 \ п" / * A9 * a9 * /
 "MOVQ %% MM2, %% MM4 \ п"  / * Клонирование a9 в mm4 * /  
 "PADDQ %% MM7, %% MM7 \ п" / * A8 удвоилась * /
 "MOVQ %% MM1, %% MM0 \ п" / * Клонирование a8 в mm0 * /
 "MOVQ %% ММ3, 64 (% 1) \ п" / * Результат [8] = а9 * а9 * /
 
 "PMULUDQ %% MM7, %% MM4 \ п" / * (А8 * 2) * а9 * /
 "MOVQ %% MM2, %% MM3 \ п"  / * Клонирование a9 в мм3 * /  
 "MOVQ %% ММ4, 72 (% 1) \ п" / * Результат [9] * /
 "PMULUDQ %% MM0, %% MM0 \ п" / * A8 * a8 * /  
 "PMULUDQ %% MM6, %% MM3 \ п" / * * A7 a9 * /
 "MOVQ %% MM2, %% MM4 \ п"  / * Клонирование a9 в mm4 * /  
 "PMULUDQ %% ММ5, %% MM4 \ п" / * A6 * a9 * /
 "PADDQ %% MM3, %% MM3 \ п" / * * A7 a9 удвоилась * /  
 "PADDQ %% MM0, %% MM3 \ п" / * * A7 a9 удвоилась + a8 * a8 * /
 "MOVQ %% MM1, %% MM0 \ п" / * Клонирование a8 в mm0 * /
 "MOVQ %% MM2, %% MM7 \ п" / * Клонирование a9 в mm7 * /
 "MOVQ %% ММ3, 80 (% 1) \ п" / * Результат [10] * /
 
 "PMULUDQ %% MM6, %% MM0 \ п" / * * A7 a8 * /  
 "MOVQ %% MM1, %% MM3 \ п" / * Клонирование a8 в мм3 * /
 "PADDQ %% MM4, %% MM0 \ п" / * * A7 a8 + a6 * a9 * /
 "MOVD 20 (% 0), %% ММ4 \ п" / * A5 в mm4 * /  
 "PADDQ %% MM0, %% MM0 \ п" / * * A7 a8 + a6 * a9 удвоения * /
 "MOVQ %% MM0, 88 (% 1) \ п" / * Результат [11] * /  

 "PMULUDQ %% ММ5, %% MM3 \ п" / * * A6 a8 * /  
 "PMULUDQ %% MM4, %% MM7 \ п" / * A5 * a9 * /  
 "MOVQ %% MM6, %% MM0 \ п" / * Клонирование a7 * /  
 "PMULUDQ %% MM0, %% MM0 \ п" / * * A7 a7 * /  
 "PADDQ %% MM3, %% MM7 \ п" / * A5 * a9 + a6 * a8 * /
 "PADDQ %% MM7, %% MM7 \ п"/ * A5 * a9 + a6 * a8 удвоилась * /
 "MOVD 16 (% 0), %% ММ3 \ п" / * A4 * /
 "PADDQ %% MM0, %% MM7 \ п"/ * A5 * a9 + a6 * a8 удвоилась + a7 * a7 * /
 "MOVQ %% MM2, %% MM0 \ п" / * Клонирование a9 * /
 "MOVQ %% MM7, 96 (% 1) \ п" / * Результат [12] * /

 "PMULUDQ %% MM3, %% MM0 \ п" / * A4 * a9 * /    
 "MOVQ %% MM1, %% MM7 \ п" / * Клонирование a8 * /
 "MOVQ %% MM6, %% MM3 \ п" / * Клонирование a7 * /  
 "PMULUDQ %% MM4, %% MM7 \ п" / * A5 * a8 * /    
 "PMULUDQ %% ММ5, %% MM3 \ п" / * * A6 a7 * /  
 "PADDQ %% MM0, %% MM7 \ п"
 "MOVD 12 (% 0), %% MM0 \ п" / * A3 в mm0 * /
 "PADDQ %% MM3, %% MM7 \ п"  / * Добавление 3 предшествующих умножений * /
 "PADDQ %% MM7, %% MM7 \ п"  / * Удваивая результат 3 * умножений /
 "MOVQ %% MM7, 104 (% 1) \ п" / * Результат [13] * /

 "PMULUDQ %% ММ5, %% ММ5 \ п" / * * A6 a6 * /    
 "MOVQ %% MM6, %% MM3 \ п" / * Клонирование a7 * /
 "MOVD 16 (% 0), %% MM7 \ п" / * A4 в mm7 * /    
 "PMULUDQ %% MM2, %% MM0 \ п" / * A3 * a9 * /  
 "PMULUDQ %% MM4, %% MM3 \ п" / * A5 * a7 * /  
 "PMULUDQ %% MM1, %% MM7 \ п" / * A4 * a8 * /  
 "PADDQ %% MM0, %% MM3 \ п"
 "MOVD 8 (% 0), %% MM0 \ п" / * A2 в mm0 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Добавление последних 3 умножений * /
 "MOVD 16 (% 0), %% ММ3 \ п" / * A4 в мм3 * /  
 "PADDQ %% MM7, %% MM7 \ п" / * Удвоение суммы 3 умножений * /
 "PADDQ %% ММ5, %% MM7 \ п" / * Добавление не удвоением a6 * a6 * /
 "MOVQ %% MM7, 112 (% 1) \ п" / * Результат [14] * /

/ * Часть # 4: Умножения и дополнения
  *  
  * (Uint64_t) (а [2] * 2) * а [9]
       + (Uint64_t) (а [3] * 2) * а [8]
       + (Uint64_t) (а [4] * 2) * а [7]
       + (Uint64_t) (а [5] * 2) * а [6] = 15 результат
      
       (Uint64_t) (а [1] * 2) * а [9]
       + (Uint64_t) (а [2] * 2) * а [8]
       + (Uint64_t) (а [3] * 2) * а [7]
       + (Uint64_t) (а [4] * 2) * а [6]
       + (Uint64_t) а [5] * а [5] = result16
      
        (Uint64_t) (а [0] * 2) * а [9]
       + (Uint64_t) (а [1] * 2) * а [8]
       + (Uint64_t) (а [2] * 2) * а [7]
       + (Uint64_t) (а [3] * 2) * а [6]
       + (Uint64_t) (а [4] * 2) * а [5] = result17 / начальное значение г * /

 "MOVD 24 (% 0), %% ММ5 \ п" / * A6 в ММ5 * /
 "PMULUDQ %% MM2, %% MM0 \ п" / * A2 * a9 * /  
 "MOVD 12 (% 0), %% MM7 \ п" / * A3 в mm7 * /
 "PMULUDQ %% MM6, %% MM3 \ п" / * A4 * a7 * /
 "PMULUDQ %% MM4, %% ММ5 \ п" / * A5 * a6 * /
 "PMULUDQ %% MM1, %% MM7 \ п" / * A3 * a8 * /  
 "PADDQ %% MM0, %% MM3 \ п"
 "MOVD 4 (% 0), %% MM0 \ п" / * A1 в mm0 * /  
 "PADDQ %% MM3, %% ММ5 \ п"
 "MOVD 16 (% 0), %% ММ3 \ п" / * A4in мм3 * /  
 "PADDQ %% ММ5, %% MM7 \ п" / * ... добавив все resuts * /
 "MOVD 24 (% 0), %% ММ5 \ п" / * A6 в ММ5 * /
 "PADDQ %% MM7, %% MM7 \ п" / * Удваивая их * /
 "MOVQ %% MM7, 120 (% 1) \ п" / * Результат [15] * /

 "PMULUDQ %% MM3, %% ММ5 \ п" / * A4 * a6 * /
 "PMULUDQ %% MM2, %% MM0 \ п" / * A1 * a9 * /
 "PMULUDQ %% MM4, %% MM4 \ п" / * A5 * a5 * /  
 "MOVD 8 (% 0), %% MM7 \ п" / * A2 в mm7 * /
 "MOVD 12 (% 0), %% ММ3 \ п" / * A3 в мм3 * /  
 "PMULUDQ %% MM1, %% MM7 \ п" / * A2 * a8 * /  
 "PMULUDQ %% MM6, %% MM3 \ п" / * A3 * a7 * /
 "PADDQ %% ММ5, %% MM0 \ п"
 "MOVD 24 (% 0), %% ММ5 \ п" / * Упреждающей a6 в ММ5 * /
 "PADDQ %% MM0, %% MM7 \ п"
 "MOVD 0 (% 0), %% MM0 \ п" / * Упреждающей a0 в mm0 * /
 "PADDQ %% MM3, %% MM7 \ п" / * Добавление 4 умножений, за исключением a5 * a5 * /
 "MOVD 4 (% 0), %% ММ3 \ п" / * Упреждающей a1 в мм3 * /
 "PADDQ %% MM7, %% MM7 \ п" /*...and удваивая их * /
 "PADDQ %% MM4, %% MM7 \ п" / * Добавление не-удвоилась a5 * a5 * /
 "MOVD 20 (% 0), %% ММ4 \ п" / * Упреждающей a5 в mm4 * /
 "MOVQ %% MM7, 128 (% 1) \ п" / * Результат [16] * /  
 
 "MOVD 8 (% 0), %% MM7 \ п" / * A2 в mm7 * /
 "PMULUDQ %% MM3, %% MM1 \ п" / * A1 * a8 * /
 "PMULUDQ %% MM0, %% MM2 \ п" / * A0 * a9 * /  
 "MOVD 12 (% 0), %% ММ3 \ п" / * A3 в мм3 * /
 "PMULUDQ %% MM7, %% MM6 \ п" / * A2 * a7 * /
 "MOVD 16 (% 0), %% MM7 \ п" / * A4 в mm7 * /
 "PMULUDQ %% MM0, %% MM0 \ п" / * * А0 а0 = с начальным значением * /
 "PMULUDQ %% MM3, %% ММ5 \ п" / * A3 * a6 * /  
 "PMULUDQ %% MM7, %% MM4 \ п" / * A4 * a5 * /    
 "PADDQ %% MM2, %% MM1 \ п"
 "MOVD 0 (% 3), %% ММ2 \ п"  / * Упреждающей M в MM2 * /
 "PADDQ %% MM1, %% MM6 \ п"
 "MOVQ %% MM0, %% MM7 \ п" / * Шаг с в MM7 (a0 * a0) * /
 "MOVQ 128 (% 1), %% ММ3 \ п" / * Упреждающей result16 * /
 "PADDQ %% ММ5, %% MM6 \ п"  
 "MOVQ %% MM2, %% MM0 \ п" / * Клонирование М до mm0 для вторичного хранения * /
 "PADDQ %% MM4, %% MM6 \ п" / * Добавление всех умножений вместе, кроме а0 * а0, которая является другим результатом * /
 "MOVD 4 (% 3), %% ММ4 \ п"  / * R0 до MM4 * /
 "PADDQ %% MM6, %% MM6 \ п" / * Удвоение результата - начальное значение г * /
/ * "MOVQ %% MM6, 144 (% 1) \ п" * / / * Результат [17] - который является также начальным значением D, поэтому он может быть использован непосредственно * /  
  
 
 "PAND %% MM6, %% MM2 \ п"   / * Г [9] = d & M; * /
 "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /    
 "MOVD %% ММ2, 36 (% 2) \ п" / * Г [9] = d & M; * /
 "MOVQ %% MM0, %% MM2 \ п"  / * M назад в мм2 * /
 "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [16] * /

  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ 120 (% 1), %% ММ3 \ п" / * Упреждающей result15 * /
  "MOVQ 0 (% 1), %% ММ5 \ п"  / * Упреждающей result0 * /    
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [15] * /  
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 0 (% 2) \ п" / * Экспорт t0 / г [0] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [0] * /    

  "MOVQ 112 (% 1), %% ММ3 \ п"   / * Упреждающей result14 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [14] * /  
  "MOVQ 8 (% 1), %% ММ5 \ п"  / * Упреждающей result1 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 4 (% 2) \ п" / * Экспорт t1 / г [1] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /  
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) результат [1] * /    

  "MOVQ 104 (% 1), %% MM3 \ п"  / * Упреждающей result13 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [13] * /  
  "MOVQ 16 (% 1), %% ММ5 \ п"  / * Упреждающей result2 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 8 (% 2) \ п" / * Экспорт t2 / г [2] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [2] * /    

  "MOVQ 96 (% 1), %% ММ3 \ п"  / * Упреждающей result12 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [12] * /  
  "MOVQ 24 (% 1), %% ММ5 \ п"  / * Упреждающей result3 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 12 (% 2) \ п" / * Экспорт t3 / г [3] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /  
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [3] * /      
  
  "MOVQ 88 (% 1), %% MM3 \ п"  / * Упреждающей result11 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [11] * /  
  "MOVQ 32 (% 1), %% ММ5 \ п"  / * Упреждающей result4 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 16 (% 2) \ п" / * Экспорт t4 / г [4] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) результат [4] * /      

  "MOVQ 80 (% 1), %% ММ3 \ п"  / * Упреждающей result10 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [10] * /
  "MOVQ 40 (% 1), %% ММ5 \ п"  / * Упреждающей result5 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 20 (% 2) \ п" / * Экспорт t5 / г [5] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /  
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) Результат [5] * /      

  "MOVQ 72 (% 1), %% ММ3 \ п"  / * Упреждающей result9 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [9] * /  
  "MOVQ 48 (% 1), %% ММ5 \ п"  / * Упреждающей result6 * /      
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 24 (% 2) \ п" / * Экспорт t6 / г [6] = с & M * /
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) результат [6] * /        

  "MOVQ 64 (% 1), %% ММ3 \ п"  / * Упреждающей result8 * /
  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM3, %% MM6 \ п"  / * D + = (uint64_t) Результат [8] * /
  "MOVQ 56 (% 1), %% ММ5 \ п"  / * Упреждающей result7 * /    
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "MOVQ %% MM0, %% MM2 \ п"  / * M * /
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  "MOVD %% ММ3, 28 (% 2) \ п" / * Экспорт T7 / г [7] = с & M * /
  "PADDQ %% ММ5, %% MM7 \ п"  / * = С + (uint64_t) результат [7] * /    

  "PAND %% MM6, %% MM2 \ п"   / * И0 = д & M; * /
  "MOVQ %% MM2, %% MM1 \ п"   / * U0, чтобы температура mm1 * /  
  "PSRLQ $ 26, %% MM6 \ п"    / * Д >>= 26; * /
  "PMULUDQ %% MM4, %% MM2 \ п" / * R0 * u0 * /
  "PSLLQ $ 10, %% MM1 \ п" / * R1 * u0 - с R1 равен 1024, это сдвиг влево на 10 для u0 * /  
  "PADDQ %% MM2, %% MM7 \ п"  / * С = (результат от R0 * u0) + с * /
  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с для операции AND * /
  "PAND %% MM0, %% MM3 \ п"  / * С & M * /
  "PSRLQ $ 26, %% MM7 \ п"    / * С >>= 26; * /  
  "MOVD %% ММ3, 32 (% 2) \ п" / * Экспорт t8 / г [8] = с & M * /
  "PADDQ %% MM1, %% MM7 \ п" / * С + = и0 * R1 * /
  
  "MOVQ %% MM0, %% MM2 \ п" / * Клонирование M * /
  "MOVD 36 (% 2), %% ММ1 \ п" / * R [9] * /    
  "PMULUDQ %% MM6, %% MM4 \ п" / * D * R 0 * /
  "PADDQ %% MM1, %% MM4 \ п" / * D * R 0 + г [9] * /  
  "PADDQ %% MM4, %% MM7 \ п" / * = С + d * R 0 + г [9] * /
  
  "PSRLQ $ 4, %% MM0 \ п"    / * M >>= 4; * /
  "PAND %% MM7, %% MM0 \ п" / * С & M >>4 * /
  "MOVD %% MM0, 36 (% 2) \ п"  / * R [9] = с & (M >> 4); * /
  
  "PSRLQ $ 22, %% MM7 \ п"    / * С >>= 22 * ​​/  
  "PSLLQ $ 14, %% MM6 \ п" / * Д * (R1 << 4). Так как (R1 << 4) равен 16384, это по существу левый сдвиг на 14 * /
  "PADDQ %% MM6, %% MM7 \ п" / * = С + d * (R1 << 4); * /

  "MOVQ %% MM7, %% MM3 \ п" / * Клонирование с * /
  "PSLLQ $ 6, %% MM7 \ п" / * Результат с * (R 1 >> 4), которая равна с сдвигается влево на 6, так как (R1 >> 4) = 64 * /    

  "MOVQ %% MM3, %% MM0 \ п"     / * Это ручная попытка умножения C с x3D1 или 977 десятичными, путем сдвига и добавления копий с ... * /
  "MOVQ %% MM3, %% MM1 \ п"     / * Все это сегмент, это, на самом деле, просто (с * 977) одиночная линия умножения * /
  "MOVQ %% MM3, %% MM6 \ п"     / *, Которые по каким-то причинам не хочет работать иначе с простой PMULUDQ с * 977 * константой /
  "MOVQ %% MM3, %% MM4 \ п"
  "MOVQ %% MM3, %% ММ5 \ п"  
  "PSLLQ $ 9, %% MM0 \ п" / * X512 * /    
  "PSLLQ $ 8, %% MM1 \ п" / * X256 * /    
  "PSLLQ $ 7, %% MM6 \ п" / * X128 * /      
  "PSLLQ $ 6, %% MM4 \ п" / * 64 * /        
  "PSLLQ $ 4, %% ММ5 \ п" / * X16 * / / * 512 + 256 + 128 + 64 = 976 раз с, так что +1 добавить сверху = 977 раз С или С * 0x3D1 * /
  "PADDQ %% MM3, %% MM0 \ п"
  "PADDQ %% MM1, %% MM0 \ п"
  "MOVD 0 (% 2), %% ММ3 \ п"          / * Предвыборки г [0] для MM3 * /
  "PADDQ %% MM6, %% MM0 \ п"  
  "PADDQ %% MM4, %% MM0 \ п"  
  "PADDQ %% MM0, %% ММ5 \ п"     / * Результат с * (R0 >> 4) * /    
    
  "PADDQ %% MM3, %% ММ5 \ п"  / * Д = г [0] + с (R 0 >> 4) * /
  "MOVD 4 (% 2), %% ММ6 \ п"  / * Г [1] MM6 * /  
  "MOVQ %% ММ5, %% MM3 \ п" / * * Клонирование д /
  
  "PAND %% MM2, %% ММ5 \ п" / * Д&M * /
  "MOVD 8 (% 2), %% MM0 \ п"  / * Г [2], чтобы mm0 * /      
  "PSRLQ $ 26, %% MM3 \ п"    / * Д >>= 26 * /    
  "PADDQ %% MM7, %% MM6 \ п" / * C * (R 1 >> 4) + г [1] * /
  "PADDQ %% MM6, %% MM3 \ п" / * D + = C * (R 1 >> 4) + г [1]; * /
  "MOVD %% ММ5, 0 (% 2) \ п" / * Экспорт д к г [0] * /
  "MOVQ %% MM3, %% MM7 \ п" / * * Клонирование д /
  
  "PAND %% MM2, %% MM7 \ п" / * Д&M * /
  "PSRLQ $ 26, %% MM3 \ п"    / * Д >>= 26 * /      
  "PADDQ %% MM0, %% MM3 \ п"  / * Й + = г [2]; * /
  "MOVD %% MM7, 4 (% 2) \ п"  / * Г [1] = d & M; * /
  "MOVD %% ММ3, 8 (% 2) \ п"  / * Г [2] = d * /
  "EMMS \ п"
  
 :
 : "Q"(А), "Q"(Результат), "Q"(р) , "Q" (Tempstor)
 : "Память", "% mm0", "% mm1", "% мм2", "% мм3", "% mm4", "% ММ5", "% MM6", "% MM7"
 );  
}    

Если кто-то хочет, чтобы его использовать, или интегрировать его где-нибудь, не чувствуют свободные (без необходимых кредитов), но я не могу утверждать, что это будет 100% соответствует, когда я даже не понимаю, почему 2 умножений сломались и требуются обходной путь.

Я могу попробовать это снова в будущем с упакованной версии о регистрах YMM / ZMM. В скученно может даже пороть поле 5x52. Как получится...


Редактирование: Черт, я просто понял, почему она сломалась. Я умножение двойного, чтобы получить четверное слово, но с =46биты не могут поместиться в качестве источника двойного слова. Doh ...
AlexGR сейчас офлайн Пожаловаться на AlexGR   Ответить с цитированием Мультицитирование сообщения от AlexGR Быстрый ответ на сообщение AlexGR

23 апреля 2017, 10:24:09 AM   # 7
 
 
Сообщения: 2366
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Я никогда бы не подумал, консистенция, возможно, были проблемы с целыми значениями, пока я вроде не узнал об этом на собственном горьком опыте,
Очень ценный урок там.

FWIW, я бы не ожидать какая-либо нетривиальная программа будет полностью ошибка бесплатно, если это не было очень энергичная рамка проверки вокруг него, которая была значительно больше, чем сам код; или, если это не было что-то порядка одного человека дня обзора в каждой строку коды по меньшей мере двух различных лиц и, по крайней мере, умеренно хорошие рамками проверки вокруг него.

Там было много битого криптографического кода там используется для генерации ключей, много это связано с основной сломанные реализации bignum. Существует причина, тесты в libsecp256k1 являются обширны, как они есть.
gmaxwell сейчас офлайн Пожаловаться на gmaxwell   Ответить с цитированием Мультицитирование сообщения от gmaxwell Быстрый ответ на сообщение gmaxwell

23 апреля 2017, 2:52:52 PM   # 8
 
 
Сообщения: 1988
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

FWIW, я бы не ожидать какая-либо нетривиальная программа будет полностью ошибка бесплатно, если это не было очень энергичная рамка проверки вокруг него, которая была значительно больше, чем сам код; или, если это не было что-то порядка одного человека дня обзора в каждой строку коды по меньшей мере двух различных лиц и, по крайней мере, умеренно хорошие рамками проверки вокруг него.

Там было много битого криптографического кода там используется для генерации ключей, много это связано с основной сломанные реализации bignum. Существует причина, тесты в libsecp256k1 являются обширны, как они есть.
Излишне мрачная оценка, имхо.

Мы живем в XXI веке. Машина сгенерированных и машинно-проверяемый коды путь. В XXI веке даже чистые математики готовы принять фабричные доказательства, при условии, что "машины" участие разумно чисто разработаны.

В связи с данным вопросом:

но я не рассматривал его "представление" за счет использования массива, который не sidechannel устойчивостью (и я думал, что это было "требование").
Почему бы массив исключает сопротивление бокового канала? Используйте абсолютно любую абстракцию высокого уровня в вашем коде, так долго, как шаблоны доступа к памяти (выборка коды и доступ к данным), не в зависимости от фактических входных данных, только от его размера (в данном случае является постоянным). В конце концов, ваш код выполняется машиной фон-Неймана, который содержится в массиве ячеек памяти.

Я на самом деле не читал ваш код, просто прокручивать через него. Лично я бы избежать использования сырья сборки мнемоника и использовать процессор в зависимости от встроенных функций. Это больше работы изначально (потому что вы должны просмотреть созданный узел), но меньше работы в долгосрочной эксплуатации.
2112 сейчас офлайн Пожаловаться на 2112   Ответить с цитированием Мультицитирование Сообщения от 2112 Быстрый ответ на сообщение 2112

24 апреля 2017, 3:40:35 AM   # 9
 
 
Сообщения: 2366
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Мы живем в XXI веке. Машина сгенерированных и машинно-проверяемый коды путь.
Я говорю, если не очень сильная основа проверки. (Мы машина проверить код в libsecp256k1-- но инструмент не масштабирует особенно хорошо, до сих пор)

котировка
Почему бы массив исключает сопротивление бокового канала? Используйте абсолютно любой высокий уровень абстракции в вашем коде,
На большинстве современных платформ, в том числе x86_64 частей Intel, получает доступ к массиву принимать измеримо разное время, основываясь на значении адреса мод cache_line_size--, потому что нагрузки всегда в полной строки кэша, но данные в начале кэш-линии доступны первые. Есть фактические демонстрации использования этого sidechannel для восстановления ключей.

В постоянных частях временных libsecp256k1 мы используем логические операции для построения забывая нагрузки (которые прочитали все данные, и выбрать правильную строку с маскировкой) всякий раз, когда нам нужно получить доступ к таблице с помощью секретного индекса по этой причине.

котировка
использовать процессор в зависимости от встроенных функций.
Intrinsics не позволяет контролировать распределение регистров, а также на многой коде все преимущество в производительности с помощью операций SIMD может быть уничтожено ненужными разливами и нагрузками. Составители становятся лучше ... но это не обязательно выигрыш. У нас использовать сборку в другом месте, в частности, чтобы получить доступ к флагу переноса цепи, которая не иначе легко подвергается. Это на самом деле не много нагрузки технического обслуживания, так как мы используем встроенный ассемблер, что позволяет избежать необходимости иметь дело с различием в соглашениях о вызовах между платформами.
gmaxwell сейчас офлайн Пожаловаться на gmaxwell   Ответить с цитированием Мультицитирование сообщения от gmaxwell Быстрый ответ на сообщение gmaxwell

24 апреля 2017, 6:03:41 PM   # 10
 
 
Сообщения: 1988
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Я говорю, если не очень сильная основа проверки. (Мы машина проверить код в libsecp256k1-- но инструмент не масштабирует особенно хорошо, до сих пор)
Я не хочу, чтобы попасть в словесные игры. Я понимаю ваши опасения, но я в основном согласен с акцентом на ваши заявления:
а) подчеркивая человек / ручную работу над машинной работой
б) подчеркивает верификации / проверки над автоматизированной / алгоритмической генерации кода высокого уровня

Мы получаем в глубокой паранойи территории, охватываемой Кен Томпсон "Размышления о доверительном доверии", Если кто-то хочет, чтобы сломать ваш код высокого уровня, он всегда может проникнуть необходимую поломку в сборке набор инструментов и процесс сборки.
 
На большинстве современных платформ, в том числе x86_64 частей Intel, получает доступ к массиву принимать измеримо разное время, основываясь на значении адреса мод cache_line_size--, потому что нагрузки всегда в полной строки кэша, но данные в начале кэш-линии доступны первые. Есть фактические демонстрации использования этого sidechannel для восстановления ключей.
Я думаю, что недопонимание произошло здесь. Я хотел сказать, что можно использовать любую абстракцию, например,

а) ..... a1, a2, a3 .....
б) ..... а [1], а [2], а [3] .....
в) для (я = 1; я <= 3; ++ я)
      ..... а [я], .....

так долго, как скомпилированный код имеет точно такое же модель доступа к памяти, независимо от фактических значений, хранящихся в а * переменных. Я не утверждаю, что семантика не может быть изменена соответствующим образом злоупотребляя отладку или флаги оптимизации в компиляторе, динамическое связывание или поток локального хранения, или какой-то другой механизм выполнения как пейджинговой MMU, SMM, TSX и т.д.

В постоянных частях временных libsecp256k1 мы используем логические операции для построения забывая нагрузки (которые прочитали все данные, и выбрать правильную строку с маскировкой) всякий раз, когда нам нужно получить доступ к таблице с помощью секретного индекса по этой причине.
В основном то, что я хочу сказать, что это: предположим, я в диапазоне от 0 до 1

Неправильно:
х) г = а [I];
у), если (я) г = а [1]; остальной г = а [0];
г), если (я) г = а1; остальной г = а0;

Хорошо:
а) г = I * А1 + (1-я) * а0;
б) г = г * в [1] + (1-I) * а [0];
в) для (J = 0; J <= 1; j ++) г + = (J == я) * а [J];

Опять же, я не уверен, предполагая отсутствие сборки времени проделки как компиляции кода C с компилятором C ++ с оператором [] перегружен, и т.д.

Intrinsics не позволяет контролировать распределение регистров, а также на многой коде все преимущество в производительности с помощью операций SIMD может быть уничтожено ненужными разливами и нагрузками. Составители становятся лучше ... но это не обязательно выигрыш. У нас использовать сборку в другом месте, в частности, чтобы получить доступ к флагу переноса цепи, которая не иначе легко подвергается. Это на самом деле не много нагрузки технического обслуживания, так как мы используем встроенный ассемблер, что позволяет избежать необходимости иметь дело с различием в соглашениях о вызовах между платформами.
Ну, вы, безусловно, есть пункт здесь, особенно о ADD / ADC и SUB / SBB, который я использовал в прошлом, когда повторно реализации RSA. Я также узнал очень рано в школе о поддержании давления регистра низкого и сохранения векторных блоков заняты при переносе Cray коды на более дешевые аппаратные средства и портирование MATLAB прототипов в самостоятельное C. Для меня это так естественно, что я забываю, что библиотека как secp256k1 не был предназначена для легкой SIMD-кации.

например. трудно для компилятора векторизации:
      ECsign (подпись * сообщение *, secret_key *, * нонс)
      Каждый аргумент указывает на один объект конкретного типа

по сравнению с легко компилятор векторизации:
     ECsign (Int N, подпись [], сообщение [], secret_key [], одноразовое значение [])
     каждый аргумент указывает на вектор из п объектов определенного типа.

Я просто смотрел на GitHub в фактическом файле заголовка и есть еще один вопрос, чтобы спросить: почему не использовать "ограниченный" C указатели? По моему опыту, что был один из самых простых и дешевых прибыли для достижения путем переключения указателей C на непересекающиеся FORTRAN семантики. Он был стандартизирован так давно, что в настоящее время все это поддерживает.
2112 сейчас офлайн Пожаловаться на 2112   Ответить с цитированием Мультицитирование Сообщения от 2112 Быстрый ответ на сообщение 2112

25 апреля 2017, 12:00:09 AM   # 11
 
 
Сообщения: 2366
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

G *** это. Для разговора модераторов Bitcoin есть кнопка редактирования на каждый пост рядом с кнопкой цитаты. Экран редактирования выглядит почти идентично тому, что вы получаете, когда вы цитируете сообщение.

После нескольких лет замедлителей я наконец-то удалось ответить на вместо редактирования чей-то пост. К сожалению 2112. Я собираюсь попытаться получить theymos в ООН # $ @ вещи. У меня есть ответ, но у меня нет исходного сообщения. Если случайно у вас есть, вы могли бы просто перепечатывать. В противном случае мы застряли в ожидании его исправляются.

Я очень извиняюсь за это screwup.
gmaxwell сейчас офлайн Пожаловаться на gmaxwell   Ответить с цитированием Мультицитирование сообщения от gmaxwell Быстрый ответ на сообщение gmaxwell

25 апреля 2017, 12:17:04 AM   # 12
 
 
Сообщения: 1988
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

G *** это. Для разговора модераторов Bitcoin есть кнопка редактирования на каждый пост рядом с кнопкой цитаты. Экран редактирования выглядит почти идентично тому, что вы получаете, когда вы цитируете сообщение.

После нескольких лет замедлителей я наконец-то удалось ответить на вместо редактирования чей-то пост. К сожалению 2112. Я собираюсь попытаться получить theymos в ООН # $ @ вещи. У меня есть ответ, но у меня нет исходного сообщения. Если случайно у вас есть, вы могли бы просто перепечатывать. В противном случае мы застряли в ожидании его исправляются.

Я очень извиняюсь за это screwup.
Окей, позвольте мне попытаться извлечь из проектов. Я также получил от ПМ "гость" с тем, что был похож ваш ответ в течение композиции. Сообщение, если вы хотите, чтобы продолжить его редактирование, то я удалить "Bitcoin Forum" процитировать ниже.

Edit: теперь Theymos восстановил случайно удален оригинал 2-й экземпляр опущен мой пост.

Цитата: Bitcoin Forum
Ответ ваших, цитируемый ниже, был удален модератором Bitcoin Forum. Сообщения наиболее часто удаляются, потому что они не по теме, хотя они также могут быть удалены по другим причинам. В будущем, пожалуйста, не разместить вещи, которые должны быть удалены.

котировка
Неправильно:
х) г = а [I];
у), если (я) г = а [1]; остальной г = а [0];
г), если (я) г = а1; остальной г = а0;

Хорошо:
а) г = I * А1 + (1-я) * а0;
б) г = г * в [1] + (1-I) * а [0];
в) для (J = 0; J <= 1; j ++) г + = (J == я) * а [J];

Правильно, с помощью использования целочисленного умножения неоправданно медленно, но вот как раз правильная идея. Хотя можно построить оптимизации, которые только быстрее, если вы можете уйти с что то, что я думал, что я говорю здесь.

(Если вам интересно, вот как мы достигаем эти условные доступы, мы перебираю запись с https://github.com/bitcoin-core/secp256k1/blob/master/src/field_5x52_impl.h#L419 ).

котировка
по сравнению с легко компилятор векторизации:
     ECsign (Int N, подпись [], сообщение [], secret_key [], одноразовое значение [])
     каждый аргумент указывает на вектор из п объектов определенного типа.


Ну мы не будем заботиться о векторизации подписания в любом case-- по крайней мере, в Bitcoin земле подписание много сообщений сразу никогда не является узким местом (и на самом деле, если вы разрабатываете что-то новое там, где она есть, merkelize ваших данных и сделать одну сигнатуру (возможно, с агрегированным ключом).  

Но давайте говорить проверка: По крайней мере, на x86 стиле SIMD эффективно делать быстрый поиск в таблице (которая необходима для использования Предвычисления для состояния исполнительского искусства) не так легко сделать. Я не проверял в последнее время, FWIW, но CPU тщеславие поколение как было ранее столь же быстро на GPU тщеславие из-за родом эксплуатирующих оптимизаций, как экстенсивное предвычисление. Хотя это можно использовать для доступа к PSHUFB небольших таблиц, большие таблицы являются еще одним вопросом. Несмотря на это, нет никакого способа, компилятор будет делать ничего слишком интересного там сама по себе, за возможно оптимизировать некоторые копирования петли, которые будут лучше быть устранены.

(Не то, что я бы отговорить кого-то от попыток, было бы опыт обучения, даже если это не удалось)

котировка
Я просто смотрел на GitHub в фактическом файле заголовка и есть еще один вопрос, чтобы спросить: почему не использовать "ограниченный" C указатели? По моему опыту, что был один из самых простых и дешевых прибыли для достижения путем переключения указателей C на непересекающиеся FORTRAN семантики. Он был стандартизирован так давно, что в настоящее время все это поддерживает.
Наше использование типов уже означает, что составители существующие предположения правила наложения (не указатели различных типов могут псевдоним друг друга за исключением гольца) уже получает много ограничить-х выгоды, как это делает тот факт, что все получает построить в одном модуле компиляции так что компилятор может _see_ фактического отсутствия паразитного низкочастотной большинства вещей ... Я хотел бы использовать ограничение, но до тех пор, около месяца назад ситуации с GCC не была, ограничивающей вслепую прислушивается, даже если компилятор может _directly_ видеть, что значения псевдонимов , и это не дало никаких предупреждений и будет надежно "ошибка компиляции" код. Так ограничивает было что-то безвозмездный footgun безопасности и не инструмент статического анализа у меня не может помочь нам поймать введение ограничения ошибок. Я нытье разработчиков GCC на некоторое время об этом и последние версии развития GCC теперь включают ограниченный статический анализ ограничить использование.

Мы делаем документ, внутренние входы / не переставляется на псевдоним, с надеждой, используя ограничения в будущем.


2112 сейчас офлайн Пожаловаться на 2112   Ответить с цитированием Мультицитирование Сообщения от 2112 Быстрый ответ на сообщение 2112

28 апреля 2017, 6:31:30 PM   # 13
 
 
Сообщения: 1988
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Правильно, с помощью использования целочисленного умножения неоправданно медленно, но вот как раз правильная идея.
Ну, что я имел в виду не ADD / инструкции MUL, но сложение и умножение в коммутативной области. От того, как плакаты в этой теме использовать слово эндоморфизм, я полагаю, что они были вакцинированы для него и имеют иммунитет.
 
(Если вам интересно, вот как мы достигаем эти условные доступы, мы перебираю запись с https://github.com/bitcoin-core/secp256k1/blob/master/src/field_5x52_impl.h#L419 ).
Это более или менее программное обеспечение повторной реализации того, что процессор аппаратного обеспечения при обращении делает строки кэша. Кроме того, что аппаратное обеспечение также делает проверку ECC после чтения и повторно вычисляет ECC, прежде чем писать, даже на самых дешевых процессоров. (ECC будучи код коррекции ошибок).

Кроме того, этот код выглядит как хороший кандидат, чтобы попытаться использовать новый ИМТ (Bit Manipulation Инструкции) доступен в новых процессорах x86.

Ну мы не будем заботиться о векторизации подписания в любом case-- по крайней мере, в Bitcoin земле подписание много сообщений сразу никогда не является узким местом (и на самом деле, если вы разрабатываете что-то новое там, где она есть, merkelize ваших данных и сделать одну сигнатуру (возможно, с агрегированным ключом).  
Это скорее взгляд со стула, где вы не видите необходимости легко векторизации. Как сторонний наблюдатель, а не лично принимал участие в нынешних боях, я могу сразу думать о двух областях:

1) код сервера горнодобывающей промышленности / бассейн очень вероятно, чтобы извлечь выгоду из векторизации (возможно, переменной длины векторов)
2) код, внедренный в портативном / специализированном аппаратном обеспечении или иной объект либо случайные сбои оборудования или преднамеренное введение неисправностей для извлечения секретов. В этом случае векторы фиксированной длиной спаситель:
2а) 2-полосная SIMD, где полезная нагрузка состоит из одной новой подписи и одной известной подписи (из списка задач теста / теста). Это лучший способ действовать в присутствии случайных ошибок.
2b) 4-полосная SIMD где полезная нагрузка два раза выше, каждая операция подписания дублируется, а затем проверяется на равенство в заключении. Это самый лучший способ для обнаружения преднамеренного темпера с помощью аппаратных неисправностей.

Я не сломаюсь слишком много неразглашении, заявив, что многие из этих тайных высоконадежных процессоров внутри выглядят как "Z80 с SIMD" как способ сделать аппаратные средства и его программы трудно взломать. Для тех, кто работает без какого-либо НДА, нацеливание ARM с NEON является отличным ориентиром для написания и тестирования программного кода.

Но давайте говорить проверка: По крайней мере, на x86 стиле SIMD эффективно делать быстрый поиск в таблице (которая необходима для использования Предвычисления для состояния исполнительского искусства) не так легко сделать. Я не проверял в последнее время, FWIW, но CPU тщеславие поколение как было ранее столь же быстро на GPU тщеславие из-за родом эксплуатирующих оптимизаций, как экстенсивное предвычисление. Хотя это можно использовать для доступа к PSHUFB небольших таблиц, большие таблицы являются еще одним вопросом. Несмотря на это, нет никакого способа, компилятор будет делать ничего слишком интересного там сама по себе, за возможно оптимизировать некоторые копирования петли, которые будут лучше быть устранены.

(Не то, что я бы отговорить кого-то от попыток, было бы опыт обучения, даже если это не удалось)
Я не согласен с вами, но я заметил, что там было много неисследованных возможностей для дальнейшей аппаратно-зависимой оптимизации. В частности, все, кажется, своего рода застрял, по существу, одно представление, в котором все слова в bignum находятся рядом друг с другом в памяти. Из моего опыта делает две матрицы переставляет (один до и один после фактического расчета ЕС) могло бы быть чистая прибыль. Промежуточное представление будет тогда иметь все наименее значимые слова bignums рядом друг с другом в памяти)
Наше использование типов уже означает, что составители существующие предположения правила наложения (не указатели различных типов могут псевдоним друг друга за исключением гольца) уже получает много ограничить-х выгоды, как это делает тот факт, что все получает построить в одном модуле компиляции так что компилятор может _see_ фактического отсутствия паразитного низкочастотной большинства вещей ... Я хотел бы использовать ограничение, но до тех пор, около месяца назад ситуации с GCC не была, ограничивающей вслепую прислушивается, даже если компилятор может _directly_ видеть, что значения псевдонимов , и это не дало никаких предупреждений и будет надежно "ошибка компиляции" код. Так ограничивает было что-то безвозмездный footgun безопасности и не инструмент статического анализа у меня не может помочь нам поймать введение ограничения ошибок. Я нытье разработчиков GCC на некоторое время об этом и последние версии развития GCC теперь включают ограниченный статический анализ ограничить использование.

Мы делаем документ, внутренние входы / не переставляется на псевдоним, с надеждой, используя ограничения в будущем.
Спасибо за очень интересный момент данных и его объяснение. По необходимости я в основном работаю с для плати составителей, а не с помощью инструментов GNU.
2112 сейчас офлайн Пожаловаться на 2112   Ответить с цитированием Мультицитирование Сообщения от 2112 Быстрый ответ на сообщение 2112

7 августа 2017, 8:27:35 PM   # 14
 
 
Сообщения: 1442
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Я могу попробовать это снова в будущем с упакованной версии о регистрах YMM / ZMM. В скученно может даже пороть поле 5x52. Как получится...

Я сделал fe_mul_inner из 10x26 на AVX-512, чтобы проверить его. Машина была использована Google облако skylake @ 2ГГц Xeon.

Исходные показатели для fe_mul в ./bench_internal вокруг

~ 30US для ассемблера отгруженного (5x52)
~ 27us без какого-либо ассемблера используется (5x52) и компилятор (GCC) выдача MULXs - который является более эффективным, чем встроенным ASM. (Это верно только для fe_mul и fe_sqr, скалярная асмовый еще лучше.)
~ 51us для поля 10x26, написанной в C
~ 49us для поля 10x26, написанной в C, но с использованием SSE2, чтобы упаковать 100 мулов в 50 мулов.
~ 38us для поля 10x26, написанного в C, за исключением, если я все умножения в массиве AVX2, упакованные на 4.
~ 45us для поля 10x26, написанного в ASM, используя все AVX-512.
~ 38us для поля 10x26 написан на ассемблере, используя AVX-512 для мулов + добавляет, а затем делать все остальное в скалярной части (это то, что размещена ниже)
~ 29us для поля 10x26 написан на ассемблере, за исключением нескольких строк в C (которые не изменяются значительно - 90% + в ассемблере), а затем делать -fprofile генерировать и -fprofile использования, которые каким-то образом получает это + 35% быстрее

Там что-то определенно сдерживает AVX-512 от идти быстрее, чем 27us, который является mulx стандартом, но я должен увидеть, как она идет в других архитектурах и не-VM машин тоже.

Есть 3 фактора:

-производительность ли VM и использование VM в переполненных машинах имеют тенденцию создавать ненормальные сценарии производительности. Я видел инструкцию в профилировщике пробуксовке на 10-15% от всего времени функции и я, как WTF это

-Скалярное код получает импульс процессора (2,1-2,7 ГГц вместо базовой 2GHz) и AVX-512 код получает underclock (1,8 ГГц). От 1.8GHz (AVX-512) до 2,7 ГГц (скалярный код, работающий в целочисленном блоке с турбонаддувом) это разница часы а + 50%. Такого рода перфорация хит не был частью плана, когда речь идет об упаковке вещи вместе

-Наличие 1 или 2 AVX 512 единиц на ядро ​​(??). Из того, что я читал есть различия между i7 / i9, XEON золото / платина и т.д. и т.д .. кошка / Proc / CPUInfo немного неуловимым).



Следующий код (ASM 10x26) находится в диапазоне 38us в VM - который медленнее, чем ASM 5x52 (30US) или GCC-mulx версии 5x52 (27us). Я оставил много комментариев интактных вместо очистки их - как они были вещи, которые я фазирующий путем замены их ассемблере. Первоначально я начал с массивом (ааа [10] [10]) для хранения результатов, а затем постепенно замещаются MEM ссылки на самих регистры, то делали дополнения из регистров и в конечном счете, все сохраненные результаты в другом массиве. Это не очень чистое написано не был он должен быть, как я не нашел работу я ожидал.

В общей сложности, 100 мулов, 81 дополнений, загрузка все из памяти, хранящей результаты и экспорт C + D управлялись начальные значения в чем-то вроде ... 75 инструкции (!), из которых операции с памятью было очень мало. И мулы используются 20, а не 13 (оптимальные), но 13 сценария включает в себя больше упаковки и распаковки, поэтому я оставил его, как это - видеть в профилировщике, что мулы имеют низкую стоимость (2 выданную за один цикл).

VALIGNs были медленными, но они были лучше, чем писать все на память, а затем загружается из правильных адресов. В 2 сложения векторов чередовались делать дополнения параллельно (опять же это может занять 2 добавляет за один цикл). Читаемость немного страдает от этой части, как следствие. Чередование также может быть сделано с передачами и выравниванием, но я оставил его как есть.

Код потребности затирания для xmm16-xmm31, но он играл хорошо с НКУ. Clang аварий (он уже использует xmm16-xmm31 в другом месте и не ожидать, что они будут переписаны). Затирания требует специальной обработки для них с ПЧ определения, которые указывают AVX-512 присутствие в препроцессора.

Мне интересно посмотреть, что он будет делать в, скажем, i9 работает на рабочем столе, или какой-либо будущей avx512 машине, которая не underclock avx512 действие / разгоняет скалярное действие на 30-50% дифф а. Во всяком случае, я думаю, у меня было слишком много времени на моих руках (я думаю, что я написал около 130 вариаций этого сейчас пытается найти неуловимого AVX2 и avx512 производительность, лол).

Код:
SECP256K1_INLINE статической силы secp256k1_fe_mul_inner (uint32_t * г, Const uint32_t * а, Const uint32_t * SECP256K1_RESTRICT б) {
/ * Uint64_t с, д; * /
/ * Uint64_t u0; * /
/ * Uint32_t М, R 0; * /
/ * Uint64_t ааа [10] [10] __attribute__ ((выровнен (64))); */ /*начальный "проходить" был каждый мул результат получать хранится в массиве 10х10. Он был заменен на результирующий массив дополнения - держать все в регистрах * /
    uint64_t ааа [18] __attribute__ ((выровнен (64)));  
/ * INT II; * /
/ * Const uint32_t М = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; * /

  

 __как м__ (  
 

"VPSHUFD $ 0b00010000, 32 (% 1), %% XMM5 \ п" / * B8 до b9 загружен * /
"VPMOVZXDQ 0 (% 1), %% ZMM1 \ п" / * B0 до b7 расширено до четверных слов и помещен соответственно * /

"VPBROADCASTD 0 (% 0), %% ZMM0 \ п" / * А0 загружен в ZMM * /
"VPBROADCASTD 4 (% 0), %% ZMM2 \ п" / * A1 загружен в ZMM * /
"VPBROADCASTD 8 (% 0), %% ZMM8 \ п" / * А2 загружается в ZMM * /
"VPBROADCASTD 12 (% 0), %% ZMM9 \ п" / * А3 загружается в ZMM * /
"VPBROADCASTD 16 (% 0), %% ZMM10 \ п" / * А4 загружены в ZMM * /
"VPBROADCASTD 20 (% 0), %% ZMM20 \ п" / * А5 загружены в ZMM * /
"VPBROADCASTD 24 (% 0), %% ZMM22 \ п" / * А6 загружены в ZMM * /
"VPBROADCASTD 28 (% 0), %% ZMM28 \ п" / * А7 загружены в ZMM * /
"VPBROADCASTD 32 (% 0), %% ZMM29 \ п" / * А8 загружены в ZMM * /
"VPBROADCASTD 36 (% 0), %% ZMM30 \ п" / * А9 загружены в ZMM * /

"VPMULUDQ %% ZMM0, %% ZMM1, %% ZMM3 \ п" / * А [0] [0] к [0] [7] * /
"VPMULUDQ %% ZMM2, %% ZMM1, %% ZMM4 \ п"  / * А [1] [0] к [1] ​​[7] * /
"VPMULUDQ %% ZMM8, %% ZMM1, %% ZMM11 \ п"  / * А [2] [0] к [2] [7] * /
"VPMULUDQ %% ZMM9, %% ZMM1, %% ZMM13 \ п"  / * А [3] [0] к [3] [7] * /
"VPMULUDQ %% ZMM10, %% ZMM1, %% ZMM15 \ п"  / * А [4] [0] к [4] [7] * /

"VPMULUDQ %% XMM0, %% XMM5, %% XMM6 \ п"   / * А [0] [8] к [0] [9] * /
"VPMULUDQ %% XMM2, %% XMM5, %% xmm7 \ п"   / * А [1] [8] к [1] ​​[9] * /
"VPMULUDQ %% XMM8, %% XMM5, %% XMM12 \ п"   / * А [2] [8] к [2] [9] * /
"VPMULUDQ %% XMM9, %% XMM5, %% XMM14 \ п"   / * А [3] [8] к [3] [9] * /
"VPMULUDQ %% XMM10, %% XMM5, %% XMM16 \ п"  / * А [4] [8] к [4] [9] * /

"VPMULUDQ %% XMM20, %% XMM5, %% XMM24 \ п"    / * А [5] [8] к [5] [9] * /
"VPMULUDQ %% XMM22, %% XMM5, %% XMM25 \ п"    / * А [6] [8] к [6] [9] * /
"VPMULUDQ %% XMM28, %% XMM5, %% XMM26 \ п"  / * А [7] [8] к [7] [9] * /
"VPMULUDQ %% XMM29, %% XMM5, %% XMM27 \ п"  / * А [8] [8] к [8] [9] * /
"VPMULUDQ %% XMM30, %% XMM5, %% XMM31 \ п"  / * А [9] [8] к [9] [9] * /

"VPMULUDQ %% ZMM20, %% ZMM1, %% ZMM17 \ п"   / * А [5] [0] к [5] [7] * /
"VPMULUDQ %% ZMM22, %% ZMM1, %% ZMM18 \ п"   / * А [6] [0] к [6] [7] * /
"VPMULUDQ %% ZMM28, %% ZMM1, %% ZMM19 \ п" / * А [7] [0] к [7] [7] * /
"VPMULUDQ %% ZMM29, %% ZMM1, %% ZMM21 \ п" / * А [8] [0] к [8] [7] * /
"VPMULUDQ %% ZMM30, %% ZMM1, %% ZMM23 \ п" / * А [9] [0] к [9] [7] * /



/ * Есть два основных сложение векторных последовательностей.

Нагрузка по вертикали (например: 1 Вектор нагрузок aaa90 к aaa97, представляющих [9] * б [0] к [9] * б [7]), и добавление по горизонтали вправо. Горизонтальное добавление требует
нули в реестре для элементов, которые не требуют дополнительного добавления, или K маски в регистре, чтобы ограничить поля добавлены. В этом случае мы вытягивать нули из zmm28).
 

90 + 81 72 63 54 45 36 27 18 9 (результат сохраняется в ааа [9] [0], если с использованием матрицы MEM)
91 + 82 73 64 55 46 37 28 19     (Результат сохраняется в ааа [9] [1] при использовании матрицы MEM)
92 + 83 74 65 56 47 38 29     (Результат сохраняется в ааа [9] [2], если с использованием матрицы MEM)
93 + 84 75 66 57 48 39     (Результат сохраняется в ааа [9] [3], если с использованием матрицы MEM)  
94 + 85 76 67 58 49     (Результат сохраняется в ааа [9] [4] при использовании матрицы MEM)
95 + 86 77 68 59     (Результат сохраняется в ааа [9] [5] при использовании матрицы MEM)
96 + 87 78 69     (Результат сохраняется в ааа [9] [6], если с использованием матрицы MEM)
97 + 88 79     (Результат сохраняется в ааа [9] [7], если с использованием матрицы MEM)

Вторая последовательность имеет такой вид:

1 + 10                         (Результат сохраняется в ааа [0] [1] при использовании матрицы MEM)
2 + 11       20                     (Результат сохраняется в ааа [0] [2], если с использованием матрицы MEM)
3 + 12       21 30                     (Результат сохраняется в ааа [0] [3], если с использованием матрицы MEM)
4 + 13       22 31 40                     (Результат сохраняется в ааа [0] [4] при использовании матрицы MEM)
5 + 14       23 32 41 50                     (Результат сохраняется в ааа [0] [5] при использовании матрицы MEM)
6 + 15       24 33 42 51 60                     (Результат сохраняется в ааа [0] [6], если с использованием матрицы MEM)
7 + 16       25 34 43 52 61 70                     (Результат сохраняется в ааа [0] [7], если с использованием матрицы MEM)
8 + 17       26 35 44 53 62 71 80 (результат сохраняется в ааа [0] [8], если с использованием матрицы MEM)

Опять же добавление находится справа. Более поздние результаты перезаписать 1-й вертикальный вектор (если они отличны от нуля-добавляющий) - которая хранит все результаты.

Только результат, который остается из векторных дополнений является добавление 89 + 98, которая должна быть сделана распакованы.
00 и 99 WIIL быть непосредственно использованы и не добавляются.

Во всех есть
1) 44 добавляет в первом векторе сделано в 9 вектор добавляет.
2) 36 добавляет во втором векторе сделано в 8 вектор добавляет.

Всего 80 добавок с упаковкой скорости 4,7х. Плюс распакованный один (89 + 98), мы в конечном итоге с 18 добавляет к 81 добавлений (скорость упаковки 4.5x). * /

"VPSRLDQ $ 8, %% XMM27, %% XMM8 \ п"
"VPXORQ %% YMM28, %% YMM28, %% YMM28 \ п" / * Ноль, чтобы вытащить нули в пустых полях вектора * /
"VALIGNQ $ 1, %% ZMM3, %% ZMM6, %% ZMM30 \ п" / * 1 до 8 * /
"VPADDQ %% XMM31, %% XMM8, %% XMM8 \ п" / * А [9] [8] к [9] [9] с 98 + 98 является 89 * /
"VALIGNQ $ 7, %% ZMM28, %% ZMM11, %% ZMM1 \ п" / * 20 до 26 - хотите добавить 20-21-22-23-24-25-26 из второго элемента вперед * /

"VMOVDQA64 %% XMM8, 128 (% 2) \ п"  / * А [9] [8] к [9] [9] с 98 + 98 является 89 * /

"VALIGNQ $ 6, %% ZMM28, %% ZMM13, %% ZMM2 \ п" / * 30 до 35 - хотите добавить 30-31-32-33-34-35 от третьего элемента вперед * /
"VALIGNQ $ 5, %% ZMM28, %% ZMM15, %% ZMM0 \ п" / * 40 до 44 лет - хочу добавить 40-41-42-43-44 с четвертого элемента вперед * /
"VALIGNQ $ 4, %% ZMM28, %% ZMM17, %% ZMM8 \ п" / * 50 до 53 - хотите добавить 50-51-52-53 с пятого элемента вперед * /
"VALIGNQ $ 3, %% ZMM28, %% ZMM18, %% ZMM10 \ п" / * 60 до 62 - хотите добавить 60-61-62 с шестого элемента вперед * /
"VALIGNQ $ 2, %% ZMM28, %% ZMM19, %% ZMM20 \ п" / * 70 до 71 - хотите добавить 70-71 с седьмого элемента вперед * /
"VALIGNQ $ 1, %% ZMM28, %% ZMM21, %% ZMM22 \ п" / * 80 - хотите добавить 80 только на восьмой элемент * /

"VALIGNQ $ 1, %% ZMM21, %% ZMM27, %% ZMM27 \ п" / * 81 до 88 * /
"VALIGNQ $ 2, %% ZMM19, %% ZMM26, %% ZMM26 \ п" / * 72 до 79 * /
"VALIGNQ $ 3, %% ZMM18, %% ZMM25, %% ZMM25 \ п" / * 63 до 69 * /
"VALIGNQ $ 4, %% ZMM17, %% ZMM24, %% ZMM29 \ п"  / * 54 до 59 * /
"VALIGNQ $ 5, %% ZMM15, %% ZMM16, %% ZMM16 \ п" / * 45 до 49 * /
"VALIGNQ $ 6, %% ZMM13, %% ZMM14, %% ZMM14 \ п" / * 36 до 39 * /
"VALIGNQ $ 7, %% ZMM11, %% ZMM12, %% ZMM12 \ п" / * 27 до 29 * /
/ * 18 и 19 влево, как на zmm7 * /
/ *"VALIGNQ $ 1, %% ZMM6, %% ZMM6, %% ZMM24 \ п" * / / * 9 * /
"VPSRLDQ $ 8, %% YMM6, %% YMM24 \ п"     / * 9 * /


"VPADDQ %% ZMM27, %% ZMM23, %% ZMM5 \ п"  / * Добавить на них aaa81 к aaa88 * /
"VPADDQ %% ZMM26, %% ZMM25, %% ZMM25 \ п"  / * Добавить на них aaa72 к aaa79 * /
"VPADDQ %% ZMM29, %% ZMM16, %% ZMM16 \ п"  / * Добавить на них aaa54 к aaa59 * /
"VPADDQ %% ZMM25, %% ZMM5, %% ZMM5 \ п" / * Добавить на них aaa63 к aaa69 * /
"VPADDQ %% ZMM4, %% ZMM30, %% ZMM30 \ п"  / * Добавить на них aaa10 к aaa17 * /
"VPADDQ %% ZMM16, %% ZMM5, %% ZMM5 \ п"  / * Добавить на них aaa45 к aaa49 * /
"VPADDQ %% ZMM12, %% ZMM7, %% ZMM7 \ п"  / * Добавить на них aaa27 к aaa29 * /
"VPADDQ %% ZMM1, %% ZMM30, %% ZMM30 \ п"  / * Добавить на них aaa20 к aaa26 * /
"VPADDQ %% ZMM14, %% ZMM5, %% ZMM5 \ п"  / * Добавить на них aaa36 к aaa39 * /
"VPADDQ %% ZMM2, %% ZMM30, %% ZMM30 \ п"  / * Добавить на них aaa30 к aaa35 * /
"VPADDQ %% ZMM7, %% ZMM5, %% ZMM5 \ п"  / * Добавить на них aaa18 к aaa19 * /
"VPADDQ %% ZMM0, %% ZMM8, %% ZMM8 \ п"  / * Добавить на них aaa40 к aaa44 * /
"VPADDQ %% ZMM10, %% ZMM20, %% ZMM20 \ п"  / * Добавить на них aaa60 к aaa62 * /
"VPADDQ %% ZMM24, %% ZMM5, %% ZMM5 \ п"  / * Добавить на них aaa9 * /
"VPADDQ %% ZMM8, %% ZMM30, %% ZMM30 \ п"  / * Добавить на них aaa50 к aaa53 * /
"VMOVDQA64 %% ZMM5, 64 (% 2) \ п"  / * Aaa90 - aaa97 на ааа [8] ааа [15] * /
"VPADDQ %% ZMM22, %% ZMM20, %% ZMM20 \ п"  / * Добавить 22 на 20 вместо этого, а затем на 30, за меньшие последовательного действия * /
"VPADDQ %% ZMM20, %% ZMM30, %% ZMM30 \ п"

"VMOVDQA64 %% ZMM30, 0 (% 2) \ п"

"MOVQ %% xmm5, %% RDX \ п" / * Д = (uint64_t) ааа [9] [0] * /
"MOVQ %% XMM3, %% RCX \ п" / * С = (uint64_t) ааа [0] [0] * /  

  "мов $ 0x3FFFFFF, %% r11d \ п" / * M * /
  "MOVQ %% RDX, %% г9 \ п"
  "исключающее %% EBX, %% EBX \ п"    
  
  "shrq $ 26, %% RDX \ п"
  "и %% r11d, %% R9D \ п" / * T9 = д&M * /
  "addq 72 (% 2), %% RDX \ п"  / * D = d + (uint64_t) ааа [9]; * /
  
  
    
  "loop_top _% =: \ п"  
    
  "мов %% r11d, %% r10d \ п" / * M * /
  "добавить $ 4, %% EBX \ п" / * Используется для счетчика циклов и памяти адресов в качестве множителя * /
  "и %% EDX, %% r10d \ п" / * И0 = д & M; * /
  "мов %% r10d, %% R8d \ п" / * И0 = д & M; * /
  "IMUL $ 0x3D10, %% r10 \ п" / * U0 * R0 * /
  "мов %% r11d, %% е \ п" / * M * /  
  "shrq $ 26, %% RDX \ п" / * Д >>= 26 * /
  "shlq $ 10, %% r8 \ п" / * * U0 R1 * /
  "addq %% r10, %% RCX \ п" / * С + = и0 * R0; * /
  "и %% ECX, %% е \ п" / * С & M; * /
  "shrq $ 26, %% RCX \ п" / * С >>= 26 * /
  "мы %% EAX, -4 (% 3, %% RBX, 1) \ п" / * Г [II] = с & M; * /
  "addq %% r8, %% RCX \ п" / * С + = и0 * R1 * /
  "CMP $ 36, %% EBX \ п"    / * От г [0] до [r7] есть некоторые дополнительные дополнения, в то время как г [8] не существует - поэтому, когда он достигает г [8] он пропускает их и заканчивается * /
  
  "JE loop_end _% = \ п"
  "addq 72 (2%, %% RBX, 2), %% RDX \ п" / * D + = (uint64_t) ааа [1] [II + 2]; * /
  "addq -8 (% 2, %% RBX, 2), %% RCX \ п"     / * С + = (uint64_t) ааа [0] [II]; * /
   "JMP loop_top _% = \ п"

   "loop_end _% =: \ п"  

  
   "imulq $ 0x3D10, %% RDX, %% r8 \ п"
   "addq %% г9, %% RCX \ п"
   "мов $ 0x3FFFFF, %% r10d \ п"
   "addq %% r8, %% RCX \ п"    / * = С + d * R 0 + г [9]; * /
  
   "andq %% RCX, %% r10 \ п"
   "shlq $ 14, %% RDX \ п"
   "мов %% r10d, 36 (% 3) \ п"  / * R [9] = с & (M >> 4); * /
  
   "shrq $ 22, %% RCX \ п"
   "addq %% RDX, %% RCX \ п"  / * С >>= 22; с + = d * (R1 << 4); * /
  
   "imulq $ 0x3D1, %% RCX, %% RDX \ п"
   "мов 0 (% 3), %% r10d \ п"
   "мов %% r11d, %% R8d \ п"
   "addq %% r10, %% RDX \ п"   / * D = C * (R 0 >> 4) + г [0]; * /

   "shlq $ 6, %% RCX \ п"  
   "andq %% RDX, %% r8 \ п"
   "мов 4 (% 3), %% r10d \ п"
   "мов %% R8d, 0 (% 3) \ п"    / * Г [0] = d & M; * /
  
   "shrq $ 26, %% RDX \ п"  / * Д >>= 26; * /
   "addq %% r10, %% RCX \ п"
   "addq %% RCX, %% RDX \ п"    / * D + = C * (R 1 >> 4) + г [1]; * /
  
   "и %% EDX, %% r11d \ п"
   "мов %% r11d, 4 (% 3) \ п"   / * Г [1] = d & M; * /
  
   "shrq $ 26, %% RDX \ п"  / * Д >>= 26; * /
   "добавить %% EDX, 8 (% 3) \ п" / * Г [2] + = д; * /


:
: "Q"(А), "Q"(Б), "Q"(Ааа), "Q"(р)
: "Память", "% Ракс", "% RBX", "% RCX", "% RDX", "% r8", "% г9", "% r10", "% r11","% XMM0", "% XMM1", "% xmm2", "% XMM3", "% xmm4", "% xmm5", "% xmm6", "% xmm7", "% xmm8", "% xmm9", "% xmm10", "% xmm11", "% xmm12", "% xmm13", "% xmm14", "% xmm15"
);
 
/ * Д = (uint64_t) ааа [0] [9] * /
  / * + (Uint64_t) ааа [1] [8] * /
   / * + (Uint64_t) ааа [2] [7] * /
    / * + (Uint64_t) ааа [3] [6] * /
    / * + (Uint64_t) ааа [4] [5] * /
    / * + (Uint64_t) ааа [5] [4] * /
    / * + (Uint64_t) ааа [6] [3] * /
    / * + (Uint64_t) ааа [7] [2] * /
    / * + (Uint64_t) ааа [8] [1] * /
     / * + (Uint64_t) ааа [9] [0]; * /

    
 / * Г [9] = d & M; * / / * Д >>= 26; * /

 / * С = (uint64_t) ааа [0] [0]; * /

  / * D + = * / / * (uint64_t) ааа [1] [9] * /
   / * + (Uint64_t) ааа [2] [8] * /
   / * + (Uint64_t) ааа [3] [7] * /
    / * + (Uint64_t) ааа [4] [6] * /
    / * + (Uint64_t) ааа [5] [5] * /
   / * + (Uint64_t) ааа [6] [4] * /
 / * + (Uint64_t) ааа [7] [3] * /
  / * + (Uint64_t) ааа [8] [2] * /
    / * + * / / * (Uint64_t) ааа [9]; * / / * Ааа [9] [1] =>ааа [1] [1] =>ааа [9] * /

/ * Для (II = 0; б < 8; II = II + 1)

         {              
    и0 = д & M; d >>= 26; с + = и0 * R0;
    г [II] = с & M; с >>= 26; с + = и0 * R1;
    с + = (uint64_t) ааа [0] [II];    
    D + = (uint64_t) ааа [1] [II + 2];        
           } * /
    
/ * И0 = д & M; d >>= 26; с + = и0 * R0;
    г [8] = с & M; с >>= 26; с + = и0 * R1; * /

    
/ * = С + d * R 0 + г [9]; * /
 / * R [9] = с & (M >> 4); с >>= 22; с + = d * (R1 << 4); * /
  

 / * D = C * (R 0 >> 4) + г [0]; * /

 / * Г [0] = d & M; d >>= 26; * /
    
  / * D + = C * (R 1 >> 4) + г [1]; * /

  / * Г [1] = d & М; * / / * д >>= 26; * /
/ * Г [2] + = д; * /
}


AlexGR сейчас офлайн Пожаловаться на AlexGR   Ответить с цитированием Мультицитирование сообщения от AlexGR Быстрый ответ на сообщение AlexGR

9 декабря 2017, 7:47:40 PM   # 15
 
 
Сообщения: 778
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

После нескольких месяцев работы, в конце концов, я сделал мою библиотеку, чтобы реализовать некоторые функции ECC. Я больше не использовать GMP.

Моя цель состоит в том, чтобы только генерировать так быстро, как возможные открытые ключи закрытых ключей. Поэтому я использую последовательные закрытые ключи.

О полевой операции, я сделал свою версию fe_mul и fe_sqr. Каждый элемент поля просто массив 4 uint64. Производительность довольно хорошо. Я не эталон точного как AlexGR, я могу сказать, что с моим мобильным Intel Xeon E3-1505M v6 KabyLake Я получил (используя только 1 ядро) около 16,5 M PublicKeys / с.

Рассматривая libsecp256k1 теперь я лучше понимаю код. Я отметил, что для скаляр существует представление 4x64 бит, в то время как для поля элемента только 5x52 (или 10x26). Есть некоторые безопасности причины или эти представления делают эффективно быстрее операции? Почему есть только версия ASM из fe_mul и не в fe_add тоже?

Я хотел бы знать, кроме того, если кто-нибудь знает, если это возможно использовать AVX инструкций для ускорения операций с 64 битным представлением.
arulbero сейчас офлайн Пожаловаться на arulbero   Ответить с цитированием Мультицитирование сообщения от arulbero Быстрый ответ на сообщение arulbero

9 декабря 2017, 8:55:33 PM   # 16
 
 
Сообщения: 1442
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Почему есть только версия ASM из fe_mul и не в fe_add тоже?

Из того, что я видел в профилировании, fe_add редко является узким местом, так что, вероятно, что причина. Слишком маленький. Он также должен иметь возможность компилировать в зависимости доступного оборудования и получить SSE / AVX ускорение, делая мультипликатор добавляет в соответствии с инструкцией.

котировка
Я хотел бы знать, кроме того, если кто-нибудь знает, если это возможно использовать AVX инструкций для ускорения операций с 64 битным представлением.

Основная проблема с AVX является отсутствием 128-битного умножения и 128-битного дополнения.

Это не проблема, хотя для 32 битового поля, потому что есть 64-битные мулов / добавляет (которые могут быть обработаны). В теории можно сделать до 8/16 результатов 32bit поле параллельно в том же потоке с AVX2 / 512 - и идти много быстрее, чем 64 бит, но это требует переписывания всех периферического кода, потому что нужно кормить его множественным "" а также "б" чтобы получить множественный "р" - которые, конечно, должны быть использованы другими функциями вне MUL / SQR, и т.д., - которые также должны были бы работать в потоке, как мода, что дело с несколькими входами / выходами, а не один.

(Мое внимание было сосредоточено на использовании AVX2 / 512 на одном 32-разрядного результата поля (один а, один б, один г), чтобы получить его быстрее, что позволяет избежать перезаписи часть - и так как код после умножений и сложений больше последовательно он не в состоянии произвести большую часть SpeedUp. Однако собственно убыстрение AVX2 / 512 зависит от использования несколько "потоки" входов и выходов).
AlexGR сейчас офлайн Пожаловаться на AlexGR   Ответить с цитированием Мультицитирование сообщения от AlexGR Быстрый ответ на сообщение AlexGR

9 декабря 2017, 9:13:11 PM   # 17
 
 
Сообщения: 2366
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Рассматривая libsecp256k1 теперь я лучше понимаю код. Я отметил, что для скаляр существует представление 4x64 бит, в то время как для поля элемента только 5x52 (или 10x26). Есть некоторые безопасности причины или эти представления делают эффективно быстрее операции? Почему есть только версия ASM из fe_mul и не в fe_add тоже?

Сверхполное представление уменьшает количество переносов необходимы между конечностями, поэтому он делает операции быстрее. Fe_add уже должен быть более или менее оптимальным, когда написано в C-- это тривиальная функция отчасти потому, что не нужно обрабатывать любую реализацию на всех.

Вполне возможно, что некоторые другие представления могут быть еще быстрее, особенно при использовании SIMD.
gmaxwell сейчас офлайн Пожаловаться на gmaxwell   Ответить с цитированием Мультицитирование сообщения от gmaxwell Быстрый ответ на сообщение gmaxwell

9 декабря 2017, 10:09:17 PM   # 18
 
 
Сообщения: 778
Цитировать по имени
цитировать ответ
по умолчанию Re: Как правильно использовать secp256k1 библиотеку

Сверхполное представление уменьшает количество переносов необходимы между конечностями, поэтому он делает операции быстрее. Fe_add уже должен быть более или менее оптимальным, когда написано в C-- это тривиальная функция отчасти потому, что не нужно обрабатывать любую реализацию на всех.

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

В случае fe_add я понимаю, что с сверхполным представлением нет несет (но еще одно дополнения).

В случае fe_mul? 64x64 бит = 128 бит, а * B + C + D всегда меньше, чем 2 ^ 128 уже.
Используя представление 52x52, 52x52 составляет 104 бит (еще 2 uint64), единственное преимущество состоит в том, что а * B + C + D + ж < 2 ^ 128? Но есть 5х5 = 25 умножений против 4x4 = 16 умножений.

Кроме того, есть уменьшение по модулю р, и, будучи р почти равна 2 ^ 256, мне кажется, что должно быть быстрее с 4x64 битового представления. Используя представление 4x64, достаточно умножить высокие 4 конечности продукта по 0x1000003d1 и добавить результат на низких 4 конечностях.
arulbero сейчас офлайн Пожаловаться на arulbero   Ответить с цитированием Мультицитирование сообщения от arulbero Быстрый ответ на сообщение arulbero



Как заработать Биткоины?

Bitcoin Wallet * Portefeuille Bitcoin * Monedero Bitcoin * Carteira Bitcoin * Portafoglio Bitcoin * Bitcoin Cüzdan * 比特币钱包

bitcoin-zarabotat.ru
Почта для связи: bitcoin-zarabotat.ru@yandex.ru

3HmAQ9FkRFk6HZGuwExYxL62y7C1B9MwPW