vak: (Default)
[personal profile] vak
Какой размер команды NOP на интеловском процессоре? Правильный ответ: размер любой, от 1 до 9 байт.
Length   Assembly                       Byte Sequence
------------------------------------------------------------------
1 byte   nop                            90
2 bytes  xchg %ax,%ax                   66 90
3 bytes  nopl (%rax)                    0f 1f 00
4 bytes  nopl (%rax,%rax,1)             0f 1f 04 00
5 bytes  nopw (%rax,%rax,1)             66 0f 1f 04 00
6 bytes  nopw 1(%rax,%rax,1)            66 0f 1f 44 00 01
7 bytes  nopl 0x04030201(%rax)          0f 1f 80 01 02 03 04
8 bytes  nopl 0x04030201(%rax,%rax,1)   0f 1f 84 00 01 02 03 04
9 bytes  nopw 0x04030201(%rax,%rax,1)   66 0f 1f 84 00 01 02 03 04

Чтобы жизнь программиста мёдом не казалась. 😀

Date: 2025-01-08 23:09 (UTC)
From: [personal profile] dijifi
А почему?

Скорее всего чтобы гарантировать что определённые опкоды для патчей и инструментирования всегда оставались NOP. Есть и другие формы NOPs которые превратились во всякие прочистки кэшей и хинты.

Date: 2025-01-08 23:34 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Интересно, 9 байтов 0x90 и один 9-байтовый НОП "исполняются" за одно и то же количество тактов или за разное.

Date: 2025-01-08 23:47 (UTC)
From: [personal profile] dijifi
Зависит от скорости Frontend который это всё должен сразу выбрасывать

Date: 2025-01-08 23:56 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Duh. Вот я и спрашиваю, есть ли архитектуры, в которых строка из 0x90 любой длины вплоть до 15 распознаётся как один НОП (ну или максимум как два, если пересекается граница cache line).

Date: 2025-01-09 18:57 (UTC)
From: [personal profile] chabapok
нет что ли более полезных дел у инженеров интела, чем исполнение нопов оптимизировать :)
Скорей всего нет (это предположение). 15 нопов будет.

Это отразится на том, что где-то всередине этих нопов может прийти прерывание. А если ноп написан как 66 0f 1f 84 00 01 02 03 04 то прерывание всередине не может прийти, и соответственно адрес возврата, если прерывание придет, не может быть всередину этой последовательности.

Date: 2025-01-10 13:41 (UTC)
From: [personal profile] sassa_nf
That's not a very practical question. A practical question is whether NOP followed by a string of instructions X can be executed faster than a string of 15 NOPs followed by the same string of instructions X. The answer to that is probably yes, 1 NOP followed by X is faster.

Date: 2025-01-09 09:56 (UTC)
From: [personal profile] chabapok
Любой ноп размером >1байта, может лечь одной ногой в один кешлайн - а другой ногой в другой, который даже не в L3. В худшем случае, например, страничка может лежать в свопе, который на медленном носителе.

Поэтому строго говоря, ноп может выполняться сколь угодно долго. А другие инструкции - и подавно.

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

Размер кешлайна обычно 64 байта, если что.

Date: 2025-01-09 15:49 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Насколько я могу судить, основное применение нопов разной длины - для выравнивания кода до адреса, кратного какой-то степени двойки (например, 8 или 16), а это гарантированно в пределах кешлайна.

Date: 2025-01-09 16:47 (UTC)
From: [personal profile] chabapok
Что именно "это" гарантировано в пределах кэш-лайна?

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

Date: 2025-01-09 17:53 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Что именно "это" гарантировано в пределах кэш-лайна?

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

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


Мой вопрос о скоростях выполнения тоже выражает именно это непонимание.

Date: 2025-01-09 18:50 (UTC)
From: [personal profile] chabapok
> То, что последовательность нопов, вставляемых с упомянутой целью добить адрес следующей команды до ближайшего кратного 8 или 16, не пересекает границу кэш-лайна.

это ж как вставишь - так и будет.

вообще, я плохо понимаю, зачем такое может понадобиться. Но clang ставит странные jmp на аддрес, который идет сразу после этого jmp. Тоже не знаю, зачем это.

> Мой вопрос о скоростях выполнения

насколько я понимаю, в х86 никогда скорости не стандартизировали. И в разных поколениях не гарантируется одинаковость скорости каждой инструкции.

А во многих cpu хоть и написано 1 такт, но по факту бывает больше почему-то. Я на такое не нарывался, но человек который шил какие-то микроконтроллеры мне на такое жаловался. Не знаю, я не вникал.

Возможно это связано с конвеером, но это не точно.
Edited Date: 2025-01-09 18:52 (UTC)

Date: 2025-01-10 13:42 (UTC)
From: [personal profile] sassa_nf
> никто никогда не будет оптимизировать, чтобы ноп лежал по фен шую

You'll be surprised.

Date: 2025-01-10 17:22 (UTC)
From: [personal profile] chabapok
Ладно. А если так:

Кто-то может это делать в академических целях. Но для практических/прикладных - никто никогда

Date: 2025-01-10 19:18 (UTC)
From: [personal profile] sassa_nf
You'll be surprised.

I know JIT compilers that do take into account much finer CPU performance recommendations than just plain cache line alignment.

Date: 2025-01-10 20:13 (UTC)
From: [personal profile] chabapok
это скорей всего по данным, а не по командам. Ну а так, фиг его знает.

Date: 2025-01-11 00:12 (UTC)
From: [personal profile] sassa_nf
I don't know why you insist.

Date: 2025-01-11 15:34 (UTC)
From: [personal profile] chabapok
та нет, я не упираюсь. Если видели такое - ладно, так тому и быть.
Я правда плохо представляю, зачем это может понадобиться, но видимо у людей, которые это делали, какие-то соображения были.

Date: 2025-01-11 16:18 (UTC)
From: [personal profile] sassa_nf
.align pads code with NOPs.

For example, trampolines, bits of code that may need replacing, bits of code where the callee may need to manipulate return point, ....

Date: 2025-01-09 10:09 (UTC)
From: [personal profile] chabapok
а вот эти всякие (%rax) не полезут ли в память? И не будет ли исключения из за чтения по несуществующему аддресу?

Ну и опять же, если аддерсс rax существует но не в L1, то его надо туда подгрузить, возможно вытеснив что-то. Ну то есть, вроде ноп - но может быть задействована целая куча подсистем. Или нет?

Date: 2025-01-10 17:17 (UTC)
From: [personal profile] chabapok
Это можно проверить, "обратившись" через такой ноп к страничке, которая гарантированно не в кеше. И померяв время. Если обращение с подсистеме памяти будет выброшено внутренним декодером, то все исполнится быстро, а если нет, то займет сотни тактов.

По старым временам я бы проверил, но сейчас нет. Времени не всегда на потрындеть хватает.

Date: 2025-01-10 10:25 (UTC)
From: [personal profile] sassa_nf
It's just decoding of modr/m. Like 90 is not really a separate instruction NOP, and there is an equivalent encoding using 87 with an extra byte. Likewise 0F 1F is not the only code that is NOP, and the bytes that follow aren't unique.

Eg 0F 1F C0 = NOP RAX, no addresses involved.
Edited Date: 2025-01-10 10:43 (UTC)

Date: 2025-01-10 10:25 (UTC)
prool: cat (Default)
From: [personal profile] prool
А вот NOP в процессоре 8080 удобный - 0x00. Помню в студеческие годы делали мы дипломный проект на 8080 (то есть на К580) и я писал код, а электроники сразу шили его в ПЗУ и пару раз ошиблись, тогда забили ошибочный код нулями и дальше пошли. (Это было какое-то прошиваемое током нестираемое ПЗУ (EEPROM), его можно было прошиватьк кусочками и можно было прошивать поверх его прошитого. Чистое было все в единицах и прошивка заключалась в сбросе некоторых битов в ноль).

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

Я еще шутку придумал "Что такое программатор? - Это устройство, заменяющее программиста"