<?xml version="1.0" encoding="utf-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Форум программистов и сисадминов Киберфорум - Блоги - Jin X</title>
		<link>https://www.cyberforum.ru/blogs/521524/</link>
		<description>КиберФорум - форум программистов, системных администраторов, администраторов баз данных, компьютерный форум, форум по электронике и бытовой технике, обсуждение софта. Бесплатная помощь в решении задач по программированию и наукам, решение проблем с компьютером, операционными системам</description>
		<language>ru</language>
		<lastBuildDate>Fri, 08 May 2026 06:55:57 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.cyberforum.ru//cyberstatic.net/images/misc/rss.jpg</url>
			<title>Форум программистов и сисадминов Киберфорум - Блоги - Jin X</title>
			<link>https://www.cyberforum.ru/blogs/521524/</link>
		</image>
		<item>
			<title>Как писать ТЗ (техническое задание) для разработчиков ПО?</title>
			<link>https://www.cyberforum.ru/blogs/521524/7358.html</link>
			<pubDate>Fri, 26 Nov 2021 21:54:05 GMT</pubDate>
			<description>*Как писать ТЗ (техническое задание) для разработчиков программного обеспечения?* 
 
*Зачем?...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Как писать ТЗ (техническое задание) для разработчиков программного обеспечения?</b></font></font></div><br />
<font color="DarkRed"><font size="3"><b>Зачем? Давайте я напишу в чате!</b></font></font><br />
<br />
Есть такая поговорка: &quot;<b>без нормального ТЗ результат будет х/з</b>&quot;.<br />
И заказчик, и разработчик заинтересованы в том, чтобы всё было сделано так, как задумывалось. Но к сожалению, даром телепатии разработчики обычно не обладают, и читать мысли заказчика не могут (по крайней мере, я – точно). Если заказчик что-то не описал, значит либо это неважно (т.е. делать этого не нужно, а если нужно, то делай как хочешь), либо важно, но сказать забыл (тогда за это потом придётся доплачивать отдельно, т.к. не было оговорено при согласовании задания).<br />
<br />
Часто бывает так, что заказчик описывает задачу &quot;в общих чертах&quot;, не вдаваясь в детали. Это происходит потому, что либо он не хочет тратить на это время (а разработчик если и хочет, то уж точно не бесплатно), либо не совсем чётко представляет, что ему нужно (не пытался углубляться в детали). И то, и другое нехорошо, потому что в первом случае время потратить всё равно придётся, т.к. нормальный разработчик будет задавать 100500 вопросов о деталях, либо отправит писать ТЗ. Другой же просто сделает всё на своё усмотрение, и потом уже, извините, без претензий, вы не говорили, что надо делать <i>вот так</i>, а не <i>эдак</i>. Во втором случае в процессе работы может всплыть столько нюансов, что либо вас попросят доплатить за то, что вы забыли о них упомянуть, либо вы поймёте, что вам нужно совсем не то, что вы заказали. <font color="Navy"><b>Написание подробного ТЗ заставит вас углубиться в детали, более чётко понять, что вам нужно, и сэкономит время разработчика и ваши финансы.</b></font><br />
<br />
Что касается &quot;описания задачи чате&quot;, то это годится только для совсем простых заданий (с бюджетом, как правило, до 2000-3000 рублей). Если задача более или менее объёмная, то длинные описания в чатах, во-первых, неудобно читать (плохое форматирование, нет иллюстраций, нельзя распечатать). Во-вторых, в чате помимо описания задания будет много лишних сообщений, а собирать по всему чату крупицы ТЗ – занятие не самое весёлое, да и так можно чего-то упустить. Особенно, если ТЗ записано голосом или тем более рассказано по телефону (без записи). Всё должно быть зафиксировано в тексте! И в-третьих, как показывает практика, задание в чате описывается не слишком подробно. Поверьте, <i><b>очень сильно напрягает долгое выяснение нюансов, и очень хочется заложить в бюджет этот час (два, три, пять) диалога с выяснением деталей задания.</b></i><br />
<br />
<font color="darkred"><font size="3"><b>Ок. Как же нужно?</b></font></font><br />
<br />
Создайте документ MS Word, OpenOffice или т.п. А ещё лучше – документ Google Docs, доступ на редактирование которого нужно дать разработчику, чтобы вы вместе могли вносить туда правки (разработчик, например, сможет записать детали, выяснившиеся в процессе общения в чате).<br />
<br />
В документе должно быть:<br />
<ul><li><u>Описание назначения приложения/скрипта</u>: для чего и для кого это нужно, какие функции выполняет и т.п. Будет ли продукт коммерческим (это важно, т.к. он может содержать элементы, например, библиотеки, которые могут быть запрещены для использования в коммерческих продуктах), либо для личного использования, либо это курсовая для учебного заведения.<br />
<br /></li>
<li><u>Сроки выполнения</u> задания. Можно указать максимальный и идеальный (желательный) срок. Почему-то многие забывают указывать сроки, даже когда их спрашиваешь об этом. Если сроки не имеют особого значения, так и напишите.<br />
<br /></li>
<li><u>Рамки бюджета</u>, если у вас есть понимание или какие-то ограничения, за которые нельзя выходить.<br />
<br /></li>
<li>Напишите, <u>требуется ли поддержка</u> приложения после завершения работы (исправление багов, добавление новых функций). В течение какого времени и что должна включать в себя эта поддержка. Далее вы сможете обсудить с разработчиком условия такой поддержки (в рамках текущего бюджета, с абонентской платой или с отдельной оплатой каждого внесённого изменения). <i>По умолчанию подразумевается, что в рамках текущего бюджета поддержка и исправление багов, обнаруженных через какое-то более или менее продолжительное время, не требуется</i> (конечно, вы можете задать несколько вопросов или попросить о мелкой доработке, но не более).<br />
<br /></li>
<li><u>Какой язык, библиотеки, технологии</u> должны/могут быть использованы, если это важно. <u>Под какую платформу</u> (операционную систему) приложение должно работать.<br />
<br /></li>
<li><u>Описание и иллюстрация пользовательского интерфейса</u> (фото рисунков от руки, либо созданный в специализированных программах/сервисах скетч, например, в <a rel="nofollow noopener noreferrer" href="https://moqups.com/" target="_blank" title="https://moqups.com/">moqups.com</a> – там есть большинство необходимых элементов интерфейса, которые удобно создавать, двигать и изменять). Не поленитесь, это поможет многое прояснить. Если приложение консольное, должны быть прописаны тексты, которые пользователь должен/может увидеть.<br />
<br /></li>
<li>Если приложение достаточно сложное, <u>опишите сценарий его использования сначала крупными блоками</u> (без излишней детализации), а в следующем разделе уже начните описывать детали отдельных его частей (см. далее).<br />
<br /></li>
<li><u><b>Максимально подробно и понятным, грамотным языком</b></u> (с запятыми) опишите всё, что нужно сделать:<ul><li>Для чего нужна каждая кнопочка, каждая галочка, каждое поле для ввода. Как должно реагировать приложение на ввод и нажатие на эти элементы.</li>
<li>Откуда берутся исходные данные (это константы, прописанные в коде; генерируются случайным образом; вводятся пользователем; задаются в командной строке; читаются из файла, имя которого вводится пользователем или указывается в командной строке; загружаются из сети, по какому адресу и т.д.).</li>
<li>Какой тип данных используется (числа – целые или вещественные, знаковые/беззнаковые, какого типа/размера; строка – в каком формате; может, данные хранятся в файле в UTF-8, JSON и т.д.).</li>
<li>Что и куда пользователь вводит, как приложение должно реагировать на ввод разных данных.</li>
<li>Как должна происходить обработка ошибок (пользователь ввёл неверную команду или слишком большое/отрицательное число; файл отсутствует или имеет неверный формат; в таблице имеется несколько значений вместо одного, либо оно отсутствует вовсе; два однотипных значения имеют разный размер или тип и т.д.)?</li>
</ul><b>Всё это должно сопровождаться иллюстрациями/скриншотами, текстами, ссылками и т.д.!!!</b><br />
Конечно, совсем очевидные вещи описывать не нужно, но если есть хоть малейшее сомнение, лучше опишите, потому что то, что очевидно вам (как человеку, погружённому в проект), может быть совершенно неочевидно другому.<br />
<br /></li>
<li>Опишите <u>примеры нормальных сценариев</u> использования приложения (если вариантов несколько, то и примеров пусть будет несколько). &quot;Крупными блоками&quot; вы дали описания ранее. Теперь нужно сделать это детализировано и <b>последовательно, по шагам, пункт за пунктом!</b><br />
<br /></li>
<li>Опишите <u>примеры нетипичного использования</u> (неверный ввод, отсутствие нужных файлов и т.д.).<br />
<br /></li>
<li>Если у вас есть <u>примеры входных параметров и ожидаемого результата</u> (например, когда приложение вычисляет какое-то значение или обрабатывает текст), добавьте их в ТЗ для контроля правильности работы приложения. Особенно ценны результаты для нетипичных входных параметров, которые могут привести к неожиданным ошибкам и сбоям.<br />
<br /></li>
<li><u>Примечания, пожелания, приложения...</u> Если вам нужны подробные <u>комментарии</u> по коду, напишите об этом. Если задание содержит <u>работу с API</u>, подразумевает использование <u>математических методов</u>, каких-то <u>стандартов</u> и т.д., приложите документацию/описание или ссылку, если это у вас есть. <i>Чем больше работы (в т.ч. по поиску материала) вы перекладываете на плечи разработчика, тем выше стоимость.</i><br />
<br /></li>
<li>Если у вас есть какие-то <u>дополнительные материалы</u> (файлы данных, готовые модули и пр.), обязательно прикрепите их и опишите в ТЗ.</li>
</ul><b>Крайне важно писать понятно и уделить внимание деталям</b> (очень странно, когда заказчик при первом контакте пишет так, будто они уже неделю обсуждают этот проект с разработчиком).<br />
Если вы не указали, что приложение должно использовать какой-то конкретный метод решения, библиотеку или версию библиотеки и пр., подразумевается, что можно использовать любой метод/библиотеку/версию.<br />
Если вы не указали, что приложение должно быть кроссплатформенным (работать под Windows, Linux, macOS, да ещё и на ARM), обычно подразумевается, что оно должно работать только под Windows на процессорах x86 (если это, конечно, не веб-разработка).<br />
Если вы не указали, что приложение должно быть многопоточным, подразумевается, что оно должно быть однопоточным.<br />
Если вы не описали какие-то функции (например, что некий список можно пополнять, удалять, сортировать), подразумевается, что такие функции реализовывать не требуется.<br />
И т.д.<br />
Я, конечно, задаю вопросы, чтобы прояснить вышеобозначенные моменты, но бывают ситуации, когда что-то действительно кажется очевидным, однако по факту нужно совершенно другое. <i>Например, если заказчик говорит: &quot;Пользователь вводит с клавиатуры число N, а программа должна вывести кол-во простых чисел, не превышающих N&quot;, – то вопрос о многопоточности может даже и в голову не прийти.</i><br />
<br />
<font color="Navy">Хочу ещё раз сакцентировать внимание на том, что <b>проект в представлении заказчика и разработчика может выглядеть совершенно по-разному</b>, если задание к нему описано недостаточно подробно. И <b>если добросовестный разработчик сделал не совсем то, что ожидал заказчик, скорее всего это будет по причине того, что заказчик предоставил недостаточно подробное ТЗ.</b> Если в задании что-то не указано, значит это несущественно. А как же иначе? Это важно понимать, во избежание конфликтов и лишних расходов!</font><br />
<br />
Финальный вариант документа отправляется в чат (или на почту) при окончательном утверждении заказа.<br />
<br />
<font color="DarkRed"><font size="3"><b>И напоследок...</b></font></font><br />
<br />
Будьте добры, перед тем, как отправить ТЗ, прочтите его. Нет ли ошибок? А может, что-то уже перестало быть актуальным? <b>Всё ли понятно</b> (по возможности, дайте почитать кому-то ещё, чтобы выяснить это)?<br />
Что откуда берётся и куда отправляется? Достаточно ли подробно описаны различные сценарии работы? Если сказано, что нужно прочитать файл – понятно ли какой файл (с каким именем)? Что в нём хранится и в какой формате? Приведён ли <i>конкретный</i> пример содержимого этого файла? Если что-то нужно удалить, понятно ли что делать с данными, зависимыми от удаляемых? Если изображение должно вписаться в какую-то область, указано ли – с сохранением пропорций или без? Если мы работаем со звуковыми/графическими/видео файлами, то какие форматы должны поддерживаться (например, wav и mp3, png и jpg, avi и mp4)? И т.д.<br />
<br />
Избегайте фраз вроде &quot;берётся некоторый файл&quot; (какой именно?), &quot;можно сделать такую функцию&quot; (решите уж – <i>нужно</i> или нет... если же вы хотите уточнить бюджет с этой функцией и без неё, так и напишите) и т.п. Помните, что <b>если вас можно понять неправильно – вас скорее всего поймут неправильно.</b><br />
<br />
Если вы не программист, вам может быть сложно учесть все детали или понять, как лучше сделать что-то – это нормально. Так и напишите: &quot;<i>сделайте это на своё усмотрение</i>&quot; или &quot;<i>я не знаю, как лучше это сделать, посоветуйте что-нибудь</i>&quot;.<br />
Как бы хорошо и подробно вы не составили ТЗ, у разработчика, скорее всего, всё равно возникнут некоторые вопросы и потребуется уточнение какие-то нюансов. Однако, их будет значительно меньше, чем при описании задания в чате &quot;в общих чертах&quot; :)<br />
<br />
Разумеется, углубляясь в детали, не нужно доводить всё до абсурда. Т.е. описывая программу деления двух целых чисел, необязательно детализировать всё настолько подробно:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Нажмите сюда, чтобы посмотреть...</div>
				   <div class="spoiler-body">
					   
<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">1. Вывести приглашение на числа &quot;<i>Введите целый числитель: </i>&quot;.<br />
Если введена пустая строка, завершить работу приложения.<br />
Если введено неверное число (буквы, знаки препинания), вывести ошибку &quot;<i>Введено неверное значение.</i>&quot; и завершить работу.<br />
Если введено дробное число, усечь его до целого.<br />
Если введено число в 16-ричной системе счисления с префиксом &quot;<i>0x</i>&quot;, преобразовать его в десятичное.<br />
Если введённое число начинается с цифры <i>0</i>, считать его восьмеричным и преобразовать в десятичное.<br />
Если после числа указаны неверные символы, для распознавания числа использовать цифры до этих символов.<br />
Если введённое число не помещается в тип int, вывести сообщение &quot;<i>Введено слишком большое число.</i>&quot; и завершить работу.<br />
В случае успешного ввода записать число в переменную A.<br />
<br />
2. Вывести приглашение на числа &quot;Введите целый знаменатель: &quot;.<br />
Если введена пустая строка, завершить работу приложения.<br />
Если введено неверное число (буквы, знаки препинания), вывести ошибку &quot;<i>Введено неверное значение.</i>&quot; и завершить работу.<br />
Если введено дробное число, усечь его до целого.<br />
Если введено число в 16-ричной системе счисления с префиксом &quot;<i>0x</i>&quot;, преобразовать его в десятичное.<br />
Если введённое число начинается с цифры <i>0</i>, считать его восьмеричным и преобразовать в десятичное.<br />
Если после числа указаны неверные символы, для распознавания числа использовать цифры до этих символов.<br />
Если введённое число не помещается в тип int, вывести сообщение &quot;<i>Введено слишком большое число.</i>&quot; и завершить работу.<br />
Если введён ноль, вывести ошибку &quot;<i>Деление на ноль невозможно.</i>&quot; и завершить работу.<br />
В случае успешного ввода записать число в переменную B.<br />
<br />
3. Вывести сообщение &quot;<i>Частное от деления = </i>&quot; и частное от деления числа A на B.<br />
<br />
4. Вывести сообщение &quot;<i>Для завершения нажмите Enter.</i>&quot;.<br />
Ожидать нажатия на клавишу Enter.</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table>:D В данном случае это будет чрезмерным усложнением и только увеличит стоимость, т.к. разработчику придётся обрабатывать все описанные вами случаи именно так, как вы указали.
				   </div>
			   </div>Не нужно описывать уж совсем очевидные вещи (если они действительно очевидные и способы решения этих вопросов для вас особо не важны). В данном примере достаточно просто написать так: &quot;<i>Предусмотреть обработку ввода неверных данных и деления на ноль с выводом соответствующих сообщений</i>&quot;.<br />
<br />
<font color="Navy">И, пожалуйста, проявите уважение к читателю и потратьте время на форматирование документа: заголовки, отступы, выделения и пр. Не помешает и проверка на ошибки правописания (клавиша F7 в MS Word). Возможно, вам придётся показать его не одному человеку. Поверьте, хорошее ТЗ вызывает уважение и даже немного удивление, т.к. к сожалению, встречается не так часто, как хотелось бы ;)</font></div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/7358.html</guid>
		</item>
		<item>
			<title>Пара нюансов при создании службы (Windows Service) и не только</title>
			<link>https://www.cyberforum.ru/blogs/521524/5745.html</link>
			<pubDate>Tue, 26 Mar 2019 13:27:44 GMT</pubDate>
			<description>*Пара нюансов при создании службы (Windows Service) и не только* 
 
Пишу службу (Windows Service)...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Пара нюансов при создании службы (Windows Service) и не только</b></font></font></div><br />
Пишу службу (Windows Service) на <b>Delphi</b> через <b>VCL</b>. В том же EXE-шнике делаю конфигуратор с оконным интерфейсом.<br />
Получается так:<ul><li>При запуске с опцией <b>/install</b> служба устанавливается (встроенная фича <b>TServiceApplication</b>).</li>
<li>При запуске с опцией <b>/uninstall</b> служба удаляется (встроенная фича <b>TServiceApplication</b>).</li>
<li>При запуске с опцией <b>/config</b> запускается конфигуратор.</li>
<li>Запуск службы происходит по специальной схеме (через тот же EXE-шник). Это внутренняя кухня модуля [<b>Vcl.</b>]<b>SvcMgr</b>.</li>
</ul>Если вырезать интимные подробности, DPR-файл выглядит примерно так:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="739011728"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="739011728" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">program</span> ServiceTest<span class="sy1">;</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; System<span class="sy1">.</span><span class="me1">SysUtils</span><span class="sy1">,</span>
&nbsp; Vcl<span class="sy1">.</span><span class="me1">Forms</span><span class="sy1">,</span>
&nbsp; Vcl<span class="sy1">.</span><span class="me1">SvcMgr</span><span class="sy1">,</span>
&nbsp; MyService <span class="kw1">in</span> <span class="st0">'MyService.pas'</span><span class="sy1">,</span>
&nbsp; ConfigForm <span class="kw1">in</span> <span class="st0">'ConfigForm.pas'</span><span class="sy1">;</span>
&nbsp;
<span class="co2">{$R *.RES}</span>
&nbsp;
<span class="kw1">begin</span>
&nbsp; <span class="kw1">if</span> <span class="kw3">FindCmdLineSwitch</span><span class="br0">&#40;</span><span class="st0">'CONFIG'</span><span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="co1">// Запуск конфигуратора</span>
&nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">Forms</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">Initialize</span><span class="sy1">;</span>
&nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">Forms</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">MainFormOnTaskbar</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">True</span><span class="sy1">;</span>
&nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">Forms</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">CreateForm</span><span class="br0">&#40;</span>TFormConfig<span class="sy1">,</span> FormConfig<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">Forms</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">Run</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span>
&nbsp; <span class="kw1">else</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="co1">// Запуск сервиса или установщика сервиса</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> Vcl<span class="sy1">.</span><span class="me1">SvcMgr</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">DelayInitialize</span> <span class="kw1">or</span> Vcl<span class="sy1">.</span><span class="me1">SvcMgr</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">Installing</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">SvcMgr</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">Initialize</span><span class="sy1">;</span>
&nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">SvcMgr</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">CreateForm</span><span class="br0">&#40;</span>TMyService<span class="sy1">,</span> MyService<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; Vcl<span class="sy1">.</span><span class="me1">SvcMgr</span><span class="sy1">.</span><span class="me1">Application</span><span class="sy1">.</span><span class="me1">Run</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div><div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6773.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><font size="3"><b>Проблема №1</b></font><br />
<br />
Оказывается, в <b>VCL</b> нет встроенных средств для запуска службы. Службу можно установить, а запускаться она будет только после перезагрузки компьютера. Довольно странно, но факт.<br />
Решить эту проблему через WinAPI (если класс нашей службы называется <b>TMyService</b>):<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="845538071"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="845538071" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Запуск (Start = True) или остановка (Start = False) службы (метод наследника TService).</span>
<span class="kw1">procedure</span> TMyService<span class="sy1">.</span><span class="me1">StartStopService</span><span class="br0">&#40;</span>Start<span class="sy1">:</span> <span class="kw4">Boolean</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; SvcMgr<span class="sy1">,</span> Svc<span class="sy1">:</span> SC_HANDLE<span class="sy1">;</span>
&nbsp; P<span class="sy1">:</span> <span class="kw4">PChar</span><span class="sy1">;</span>
&nbsp; SS<span class="sy1">:</span> TServiceStatus<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// Открываем диспетчер управления службами (SCM)</span>
&nbsp; SvcMgr <span class="sy1">:</span><span class="sy3">=</span> OpenSCManager<span class="br0">&#40;</span><span class="kw1">nil</span><span class="sy1">,</span> <span class="kw1">nil</span><span class="sy1">,</span> STANDARD_RIGHTS_REQUIRED<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> SvcMgr &lt;&gt; <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="co1">// Открываем службу с именем Name (это свойство объекта класса-наследника TService)</span>
&nbsp; &nbsp; Svc <span class="sy1">:</span><span class="sy3">=</span> OpenService<span class="br0">&#40;</span>SvcMgr<span class="sy1">,</span> <span class="kw4">PChar</span><span class="br0">&#40;</span>Name<span class="br0">&#41;</span><span class="sy1">,</span> SERVICE_ALL_ACCESS<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> Svc &lt;&gt; <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; <span class="co1">// Запуск или остановка?</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> Start <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; P <span class="sy1">:</span><span class="sy3">=</span> <span class="kw1">nil</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; StartService<span class="br0">&#40;</span>Svc<span class="sy1">,</span> <span class="nu0">0</span><span class="sy1">,</span> P<span class="br0">&#41;</span><span class="sy1">;</span> &nbsp;<span class="co1">// запускаем службу</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">FillChar</span><span class="br0">&#40;</span>SS<span class="sy1">,</span> <span class="kw3">SizeOf</span><span class="br0">&#40;</span>SS<span class="br0">&#41;</span><span class="sy1">,</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ControlService<span class="br0">&#40;</span>Svc<span class="sy1">,</span> SERVICE_CONTROL_STOP<span class="sy1">,</span> SS<span class="br0">&#41;</span><span class="sy1">;</span> &nbsp;<span class="co1">// останавливаем службу</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; CloseServiceHandle<span class="br0">&#40;</span>Svc<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; CloseServiceHandle<span class="br0">&#40;</span>SvcMgr<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Если нам нужно запускать службу сразу после её установки, делаем так:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="619770132"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="619770132" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw1">procedure</span> TMyService<span class="sy1">.</span><span class="me1">ServiceAfterInstall</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> TService<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; StartStopService<span class="br0">&#40;</span><span class="kw2">True</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Представьте себе, остановки при удалении (деинсталляции) службы тоже не происходит, поэтому делаем ещё и так:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="483702237"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="483702237" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw1">procedure</span> TMyService<span class="sy1">.</span><span class="me1">ServiceBeforeUninstall</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> TService<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; StartStopService<span class="br0">&#40;</span><span class="kw2">False</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><font size="3"><b>Проблема №2</b></font><br />
<br />
Каким же образом сообщить службе об изменении конфигурации (чтобы она прочитала её заново – из реестра или с диска)? Проще всего – создать глобальное именованное событие (<a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/ru-ru/windows/desktop/api/synchapi/nf-synchapi-createeventw" target="_blank" title="https://docs.microsoft.com/ru-ru/windows/desktop/api/synchapi/nf-synchapi-createeventw">CreateEvent</a>) и через него сигнализировать (<a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/ru-ru/windows/desktop/api/synchapi/nf-synchapi-setevent" target="_blank" title="https://docs.microsoft.com/ru-ru/windows/desktop/api/synchapi/nf-synchapi-setevent">SetEvent</a>) из конфигуратора службе (которая будет ждать его, либо периодически проверять, через <a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject" target="_blank" title="https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject">WaitForSingleObject</a>). Но тут нас поджидает засада: при попытке открыть из конфигуратора событие (<a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/ru-ru/windows/desktop/api/synchapi/nf-synchapi-openeventw" target="_blank" title="https://docs.microsoft.com/ru-ru/windows/desktop/api/synchapi/nf-synchapi-openeventw">OpenEvent</a>), созданное службой, мы получим ошибку запрета доступа (<a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows/desktop/api/errhandlingapi/nf-errhandlingapi-getlasterror" target="_blank" title="https://docs.microsoft.com/en-us/windows/desktop/api/errhandlingapi/nf-errhandlingapi-getlasterror">GetLastError</a> = <a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/ru-ru/windows/desktop/Debug/system-error-codes--0-499-" target="_blank" title="https://docs.microsoft.com/ru-ru/windows/desktop/Debug/system-error-codes--0-499-">ERROR_ACCESS_DENIED</a>).<br />
<br />
Это происходит из-за того, что объект (событие) создан &quot;системой&quot; (службы запускаются от имени &quot;системы&quot;), а открывается администратором (если конфигуратор находится в том же EXE – установить/удалить службу может только администратор) или даже обычным пользователем (если конфигуратор находится в другом EXE-шнике). Тоже самое будет при попытке открыть обычным пользователем объект, созданный администратором.<br />
<br />
Что же делать? Сначала я решил пойти по странному пути: создать объект в конфигураторе, а в службе периодически пытаться открыть его, и после успешного открытия начать проверять состояние (&quot;система&quot; может открыть объект, созданный администратором или обычным пользователем). Но потом эта идея мне показалась костыльной, и я решил разобраться, как создать объект в службе, не защищённый от доступа админов и обычных юзеров.<br />
<br />
Вот так это делается (в службе):<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="133418958"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="133418958" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Создать событие с именем Name в глобальном пространстве имён, доступный любым процессам.</span>
<span class="kw1">function</span> CreateUnprotectedEvent<span class="br0">&#40;</span><span class="kw1">const</span> Name<span class="sy1">:</span> <span class="kw4">String</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">THandle</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; SA<span class="sy1">:</span> TSecurityAttributes<span class="sy1">;</span>
&nbsp; SD<span class="sy1">:</span> TSecurityDescriptor<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span><span class="sy1">;</span>
&nbsp; <span class="co1">// Создаем дескриптор безопасности</span>
&nbsp; <span class="kw1">if</span> InitializeSecurityDescriptor<span class="br0">&#40;</span><span class="sy2">@</span>SD<span class="sy1">,</span> SECURITY_DESCRIPTOR_REVISION<span class="br0">&#41;</span> <span class="kw1">and</span>
&nbsp; &nbsp; &nbsp;<span class="co1">// DACL не установлен, объект не защищён</span>
&nbsp; &nbsp; &nbsp;SetSecurityDescriptorDacl<span class="br0">&#40;</span><span class="sy2">@</span>SD<span class="sy1">,</span> <span class="kw2">True</span><span class="sy1">,</span> <span class="kw1">nil</span><span class="sy1">,</span> <span class="kw2">False</span><span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="co1">// Настраиваем атрибуты безопасности, передавая указатель на дескриптор безопасности</span>
&nbsp; &nbsp; SA<span class="sy1">.</span><span class="me1">nLength</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">SizeOf</span><span class="br0">&#40;</span>SA<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; SA<span class="sy1">.</span><span class="me1">lpSecurityDescriptor</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="sy2">@</span>SD<span class="sy1">;</span>
&nbsp; &nbsp; SA<span class="sy1">.</span><span class="me1">bInheritHandle</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">False</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="co1">// Создаём событие</span>
&nbsp; &nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> CreateEvent<span class="br0">&#40;</span><span class="sy2">@</span>SA<span class="sy1">,</span> <span class="kw2">True</span><span class="sy1">,</span> <span class="kw2">False</span><span class="sy1">,</span> <span class="kw4">Pointer</span><span class="br0">&#40;</span><span class="st0">'Global\'</span> <span class="sy3">+</span> Name<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>(разумеется, при необходимости создания нескольких событий нет смысла создавать и настраивать несколько дескрипторов и атрибутов безопасности, можно использовать одни и те же; при завершении работы ничего, кроме события, закрывать или освобождать не нужно)<br />
<br />
Как вы понимаете, это всё можно делать не только при создании служб и не только для создания событий. Если вам не нравится взаимодействие через события, и вы хотите иметь возможность передавать какие-то данные, можете создать, к примеру, <a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows/desktop/memory/creating-named-shared-memory" target="_blank" title="https://docs.microsoft.com/en-us/windows/desktop/memory/creating-named-shared-memory">разделяемую память</a>. В общем, простор для творчества есть :)</div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5745.html</guid>
		</item>
		<item>
			<title>DateTimePicker – либо дата, либо время... или нет</title>
			<link>https://www.cyberforum.ru/blogs/521524/5729.html</link>
			<pubDate>Thu, 14 Mar 2019 18:00:11 GMT</pubDate>
			<description>*DateTimePicker – либо дата, либо время... или нет?* 
 
Изображение:...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>DateTimePicker – либо дата, либо время... или нет?</b></font></font><br />
<br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6762.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><font size="4"><b>Что не так?</b></font><br />
<br />
На днях я столкнулся с такой проблемой. В <font color="DarkSlateGray"><b>Delphi</b></font> (и <font color="DarkSlateGray"><b>C++Builder</b></font>) имеется компонент класса <font color="DarkSlateGray"><b>TDateTimePicker</b></font>, позволяющий пользователю вполне удобным образом выбирать дату или время. Ключевой момент: дату <b><i>ИЛИ</i></b> время. Что именно – определяется опубликованным (published) свойством <font color="DarkSlateGray"><b>Kind</b></font>, которое может принимать значение <font color="DarkSlateGray"><b>dtkDate</b></font> или <font color="DarkSlateGray"><b>dtkTime</b></font>. Однако компонент имеет также опубликованное свойство <font color="DarkSlateGray"><b>Format</b></font>, которое позволяет задавать свой формат отображения даты и времени, причём записать туда можно сразу и дату, и время. К примеру, вот в таком формате: <font color="DarkSlateGray"><b>dd-MMM-yyyy, HH:mm:ss</b></font> (отображаться это будет так: <font color="DarkSlateGray"><b>14-мар-2019, 15:08:37</b></font>). Прикол в том, что пользователь может менять как дату, так и время (вне зависимости от значения свойства <font color="DarkSlateGray"><b>Kind</b></font>), однако обновляться при этом будет только значение либо свойства <font color="DarkSlateGray"><b>Date</b></font>, либо свойства <font color="DarkSlateGray"><b>Time</b></font>. Неожиданно? Если внимательно читать документацию, то нет. Учитывая, что это стандартный контрол Windows, это поведение абсолютно нормально.<br />
<br />
Что же делать, если мы хотим дать пользователю возможность выбирать и дату, и время?<ul><li>Вариант 1: установить два компонента <font color="DarkSlateGray"><b>DateTimePicker</b></font> (один с <font color="DarkSlateGray"><b>Kind = dtkDate</b></font>, другой с <font color="DarkSlateGray"><b>Kind = dtkTime</b></font>) и читать из них отдельно дату (<font color="DarkSlateGray"><b>Date</b></font>) и время (<font color="DarkSlateGray"><b>Time</b></font>) ответственно.</li>
<li>Вариант 2: создать собственный компонент на основе <font color="DarkSlateGray"><b>DateTimePicker</b></font>.</li>
<li>Вариант 3: &quot;вмешаться&quot; в работу <font color="DarkSlateGray"><b>DateTimePicker</b></font>, создав <a href="https://www.cyberforum.ru/cpp-builder/thread1368916.html">класс-перехватчик</a> (т.е. класс-потомок с тем же именем, оставив оригинальный класс в покое) и заставить форму использовать его вместо оригинального класса.</li>
</ul>Вам решать, какой вариант выбрать. Лично я пошёл по третьему пути (тем более, что у меня уже расставлено несколько <font color="DarkSlateGray"><b>DateTimePicker</b></font>'ов на форме, которые заменять на двойные + менять код было в лом).<br />
<br />
Рассказываю подробнее и по шагам :)<ol style="list-style-type: decimal"><li>Выбираем на всех компонентах, хранящих <i>дату+время</i> (или только <i>дату</i>), у свойства <font color="DarkSlateGray"><b>Kind</b></font> значение <font color="DarkSlateGray"><b>dtkDate</b></font> (там, где только <i>время</i>, оставляем <font color="DarkSlateGray"><b>dtkTime</b></font>).<br />
<br /></li>
<li>Перед(!) объявлением класса формы объявляем класс <font color="DarkSlateGray"><b>TDateTimePicker</b></font> как потомок <font color="DarkSlateGray"><b>Vcl.ComCtrls.TDateTimePicker</b></font> (в Delphi до версий XE включительно родительский класс будет называться <font color="DarkSlateGray"><b>ComCtrls.TDateTimePicker</b></font>). Ещё раз: объявить класс нужно <b><i>ДО</i></b> класса формы, на котором расположены компоненты.<br />
<br />
Если у вас несколько форм, на которых используется <font color="DarkSlateGray"><b>DateTimePicker</b></font>, создайте отдельный модуль (<font color="DarkSlateGray"><b>unit</b></font>), а потом добавляйте его в список <font color="DarkSlateGray"><b>uses</b></font> модуля каждой формы, но обязательно <b><i>после</i> <font color="DarkSlateGray">Vcl.ComCtrls</font></b> (<font color="DarkSlateGray"><b>ComCtrls</b></font>). В общем-то, это можно сделать и для одной формы – тут уж как вам удобнее.<br />
<br /></li>
<li>В создаваемом классе создаём метод <font color="DarkSlateGray"><b>SetTimeFromCaption</b></font>, который будет читать время из <font color="DarkSlateGray"><b>Caption</b></font> (т.е. из окна в виде текста), преобразовывать его в <font color="DarkSlateGray"><b>TDateTime</b></font> и записывать в свойство <font color="DarkSlateGray"><b>Time</b></font>.<br />
<br /></li>
<li>Перекрываем динамический (dynamic) метод <font color="DarkSlateGray"><b>Change</b></font>. Этот метод вызывается при изменении содержимого компонента. Внутри делаем проверку <font color="DarkSlateGray"><b>Kind = dtkDate</b></font>, и в случае совпадения вызываем метод <font color="DarkSlateGray"><b>SetTimeFromCaption</b></font> и <font color="DarkSlateGray"><b>inherited</b></font>.</li>
</ol><br />
<font size="4"><b>Код в студию!</b></font><br />
<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="375357794"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="375357794" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
</pre></td><td class="de1"><pre class="de1"><span class="kw1">type</span>
&nbsp; <span class="co1">// Класс-перехватчик, позволяющий читать изменение и даты, и времени в TDateTimePicker</span>
&nbsp; <span class="co1">// ВАЖНО: При изменении свойства Format может потребоваться изменение PickerDateTimeSeparator и PickerTimeSeparator.</span>
&nbsp; TDateTimePicker <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>Vcl<span class="sy1">.</span><span class="me1">ComCtrls</span><span class="sy1">.</span><span class="me1">TDateTimePicker</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">class</span> <span class="kw1">constructor</span> Create<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> Change<span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> SetTimeFromCaption<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">const</span>
&nbsp; &nbsp; &nbsp; PickerDateTimeSeparator <span class="sy3">=</span> <span class="st0">' '</span><span class="sy1">;</span> &nbsp;<span class="co1">// разделитель между датой и временем (строка)</span>
&nbsp; &nbsp; &nbsp; PickerTimeSeparator <span class="sy3">=</span> <span class="st0">':'</span><span class="sy1">;</span> &nbsp; &nbsp; &nbsp;<span class="co1">// разделитель часов, минут и секунд (символ)</span>
&nbsp; &nbsp; <span class="kw1">class</span> <span class="kw1">var</span> FmtSettings<span class="sy1">:</span> TFormatSettings<span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; <span class="co1">// Далее идёт объявление класса формы</span>
&nbsp;
<span class="sy1">.</span> <span class="sy1">.</span> <span class="sy1">.</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="sy1">.</span> <span class="sy1">.</span> <span class="sy1">.</span>
&nbsp;
<span class="co1">// Конструктор класса: настройка параметров (один раз для всех объектов)</span>
<span class="kw1">class</span> <span class="kw1">constructor</span> TDateTimePicker<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; FmtSettings <span class="sy1">:</span><span class="sy3">=</span> TFormatSettings<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
&nbsp; FmtSettings<span class="sy1">.</span><span class="me1">TimeSeparator</span> <span class="sy1">:</span><span class="sy3">=</span> PickerTimeSeparator<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="co1">// Обновление времени, если Kind = dtkDate</span>
<span class="kw1">procedure</span> TDateTimePicker<span class="sy1">.</span><span class="me1">Change</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">if</span> Kind <span class="sy3">=</span> dtkDate <span class="kw1">then</span> SetTimeFromCaption<span class="sy1">;</span>
&nbsp; <span class="kw1">inherited</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="co1">// Установить время, исходя из текста в окне DateTimePicker'а</span>
<span class="kw1">procedure</span> TDateTimePicker<span class="sy1">.</span><span class="me1">SetTimeFromCaption</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; NewTime<span class="sy1">:</span> <span class="kw4">TDateTime</span><span class="sy1">;</span>
&nbsp; TimeStr<span class="sy1">:</span> <span class="kw4">String</span><span class="sy1">;</span>
&nbsp; SepPos<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; TimeStr <span class="sy1">:</span><span class="sy3">=</span> Caption<span class="sy1">;</span>
&nbsp; <span class="co1">// Удаляем всё до последнего разделителя PickerDateTimeSeparator (вместе с разделителем)</span>
&nbsp; <span class="kw1">repeat</span>
&nbsp; &nbsp; SepPos <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">Pos</span><span class="br0">&#40;</span>PickerDateTimeSeparator<span class="sy1">,</span> TimeStr<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> SepPos <span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">then</span> Break<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw3">Delete</span><span class="br0">&#40;</span>TimeStr<span class="sy1">,</span> <span class="nu0">1</span><span class="sy1">,</span> SepPos <span class="sy3">+</span> <span class="kw3">Length</span><span class="br0">&#40;</span>PickerDateTimeSeparator<span class="br0">&#41;</span> <span class="sy3">-</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">until</span> <span class="kw2">False</span><span class="sy1">;</span>
&nbsp; <span class="co1">// Преобразуем строку в формат времени</span>
&nbsp; <span class="kw1">if</span> <span class="kw3">TryStrToTime</span><span class="br0">&#40;</span>TimeStr<span class="sy1">,</span> NewTime<span class="sy1">,</span> FmtSettings<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; Time <span class="sy1">:</span><span class="sy3">=</span> NewTime<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Согласен, используемый в <font color="DarkSlateGray"><b>SetTimeFromCaption</b></font> метод выглядит несколько костыльно. Но другого способа получения времени из <font color="DarkSlateGray"><b>DateTimePicker</b></font> при значении <font color="DarkSlateGray"><b>Kind = dtkDate</b></font> я, к сожалению, не знаю.<br />
<font color="DarkSlateGray"><b><font color="Red">Знаете? Поделитесь в комментариях! ;)</font></b></font><br />
<br />
<font size="4"><b>Несколько нюансов</b></font><br />
<ul><li>Как написано в комментариях, при изменении формата даты/времени (свойства <font color="DarkSlateGray"><b>Format</b></font>) необходимо скорректировать значения констант <font color="DarkSlateGray"><b>PickerDateTimeSeparator</b></font> и <font color="DarkSlateGray"><b>PickerTimeSeparator</b></font> (здесь важен разделитель между датой и временем, а также между часами, минутами, секундами).<br />
<br /></li>
<li>Манипуляции с объектом класса <font color="DarkSlateGray"><b>TFormatSettings</b></font> нужны для того, чтобы предотвратить проблемы с преобразованием строки, содержащей время, если системный разделитель времени будет отличаться от символа <font color="DarkSlateGray"><b>PickerTimeSeparator</b></font> (в данном случае двоеточия). Дело в том, что символ двоеточия в <font color="DarkSlateGray"><b>DateTimePicker.Format</b></font> означает именно двоеточие, в отличие, например, от функции <font color="DarkSlateGray"><b>DateTimeToString</b></font> модуля <font color="DarkSlateGray"><b>System.SysUtils</b></font>, в котором двоеточие означает системный разделитель часов и минут (установленный настройках операционной системы).<br />
<br />
Сначала я хотел обойтись без конструктора класса и создания объекта <font color="DarkSlateGray"><b>FmtSettings</b></font>, просто меняя и восстанавливая значение общих настроек <font color="DarkSlateGray"><b>FormatSettings.TimeSeparator</b></font> внутри <font color="DarkSlateGray"><b>SetTimeFromCaption</b></font>. Но потом решил, что это колхоз. Представьте ситуацию, что у вас многопоточное приложение, и дополнительный поток использует функции вроде <font color="DarkSlateGray"><b>Format</b></font>, <font color="DarkSlateGray"><b>DateTimeToStr</b></font>, <font color="DarkSlateGray"><b>StrToDateTime</b></font> и т.п., для преобразования даты/времени в строку или обратно. И в этот самый момент наш код меняет <font color="DarkSlateGray"><b>FormatSettings.TimeSeparator</b></font>. Появляются баги, а вы не понимаете откуда (причём, баги не у вас, а у других пользователей, у которых вместо двоеточия в ОС используется, например, точка). Ситуация маловероятная, но любой нормальный программист должен учитывать и такое :)<br />
<br /></li>
<li>В методе <font color="DarkSlateGray"><b>SetTimeFromCaption</b></font> я оставляю строку именно после <b><i>последнего вхождения</i></b> <font color="DarkSlateGray"><b>PickerDateTimeSeparator</b></font> в <font color="DarkSlateGray"><b>Caption</b></font>, чтобы можно было использовать тот же разделитель ещё и где-то раньше (например, число и месяц тоже могут отделяться пробелом, либо вы можете добавить день недели, отделённый запятой или пробелом). Всё же, время обычно указывается в самом конце и не содержит символов-разделителей вроде запятой, пробела и т.п.<br />
<br /></li>
<li>Если всё сделано и настроено правильно <font color="DarkSlateGray"><b>TryStrToTime</b></font> всегда будет возвращать <font color="DarkSlateGray"><b>True</b></font>. Однако, если вы хотите отлавливать проблемные ситуации, создайте ещё один метод (скажем, <font color="DarkSlateGray"><b>TimeFromCaptionFailure</b></font>) и вызывайте его из <font color="DarkSlateGray"><b>SetTimeFromCaption</b></font> в случае ошибки преобразования.<br />
<br /></li>
<li>В компоненте <font color="DarkSlateGray"><b>DateTimePicker</b></font> ранних версий <font color="DarkSlateGray"><b>Delphi</b></font> изменить время при установленном значении <font color="DarkSlateGray"><b>Kind = dtkDate</b></font> нельзя (пользователь не сможет ввести цифры, а нажатие на стрелки вверх-вниз ничего не изменят). Однако при значении <font color="DarkSlateGray"><b>Kind = dtkTime</b></font> можно менять и дату, и время. В этом случае вам придётся преобразовывать строку, содержащую не время, а дату. Это может оказаться немного сложнее (поскольку строка может содержать название месяцев, а порядок расположения дней, месяцев и лет может отличаться на разных компьютерах). Если есть желание написать такой код, welcome! :) Начиная с <font color="DarkSlateGray"><b>Delphi 2009</b></font> таких проблем нет.</li>
</ul></div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5729.html</guid>
		</item>
		<item>
			<title>Проверка числа на простоту – ускоряемся!</title>
			<link>https://www.cyberforum.ru/blogs/521524/5712.html</link>
			<pubDate>Wed, 27 Feb 2019 22:29:43 GMT</pubDate>
			<description>*Проверка числа на простоту – ускоряемся!* 
 
Самый простой способ проверки числа N на простоту –...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Проверка числа на простоту – ускоряемся!</b></font></font></div><br />
Самый простой способ проверки числа N на простоту – проверить его делимость на все числа от 2 до корня из N.<br />
<br />
<div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="957932938"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="957932938" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Тест простоты числа n</span>
<span class="kw4">bool</span> is_prime<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> n<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="co1">// Проверяем, что число больше единицы (простое всегда больше)</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy1">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на числа от 2 до корня из n:</span>
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="kw3">div</span> <span class="sy1">=</span> <span class="nu0">2</span>, max_div <span class="sy1">=</span> <span class="kw3">sqrt</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="sy4">;</span> <span class="kw3">div</span> <span class="sy1">&lt;=</span> max_div<span class="sy4">;</span> <span class="sy2">++</span><span class="kw3">div</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy2">%</span> <span class="kw3">div</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Число простое</span>
&nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy4">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Но этот код слишком медленный. Первое, что приходит на ум для ускорения – исключить из списка делителей чётные числа, сократив таким образом количество итераций вдвое (по сути же, нам важно проверить делимость только на другие простые числа, а простые числа не бывают чётными, кроме 2).<br />
<br />
Проверим делимость числа на 2, а затем на все нечётные, начиная с 3:<br />
<div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="222496663"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="222496663" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="kw4">bool</span> is_prime2<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> n<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="co1">// Проверяем, что число больше 1, а также частный случай простого числа (2)</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy1">&lt;=</span> <span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>n <span class="sy1">==</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на 2</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>n <span class="sy3">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на нечётные числа, начиная с 3:</span>
&nbsp; <span class="co1">// 3, 5, 7, 9, 11, 13, 15, 17, 19, 21...</span>
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="kw3">div</span> <span class="sy1">=</span> <span class="nu0">3</span>, max_div <span class="sy1">=</span> <span class="kw3">sqrt</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">div</span> <span class="sy1">&lt;=</span> max_div<span class="sy4">;</span>
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">div</span> <span class="sy2">+</span><span class="sy1">=</span> <span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy2">%</span> <span class="kw3">div</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Число простое</span>
&nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy4">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Надеюсь, никого не смущает запись <code class="inlinecode">n &amp; 1</code> вместо <code class="inlinecode">n % 2</code>? Да, конечно, умный компилятор сам заменит <b>%</b> на <b>&amp;</b>, но я хочу указать это явно. Если вас это напрягает, замените :)<br />
<br />
Этот код тоже далёк от совершенства, поскольку мы можем исключить числа, делящиеся не только на 2, но и на 3, сократив кол-во итераций ещё в 1.5 раза (а в сравнении с первым вариантом – в 3 раза). Чтобы это сделать, нам нужно увеличивать делитель то на 2, то на 4. Для этого будем проделывать с &quot;дельтой&quot; операцию <code class="inlinecode">xor 6</code>. Проверим: <b>2 xor 6 = 4</b>, <b>4 xor 6 = 2</b>. Всё до гениальности просто! Цикл начнём с 5.<br />
<br />
Let's do it:<br />
<div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="544597474"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="544597474" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Тест простоты числа n</span>
<span class="kw4">bool</span> is_prime3<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> n<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="co1">// Проверяем, что число больше 1, а также частные случаи простых чисел (2 и 3)</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy1">&lt;=</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>n <span class="sy1">&gt;=</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на 2 и 3</span>
&nbsp; <span class="co1">// p.s. При оптимизации нормальными компиляторами с опцией -O2 деление (взятие остатка от деления)</span>
&nbsp; <span class="co1">// на константу будет выполняться быстрее, чем на переменную с заранее неизвестным значением</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>n <span class="sy3">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">3</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на числа, не делящиеся на 2 и 3, начиная с 5</span>
&nbsp; <span class="co1">// (с приращением то на 2, то на 4): 5, 7, 11, 13, 17, 19, 23, 25, 29, 31...</span>
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="kw3">div</span> <span class="sy1">=</span> <span class="nu0">5</span>, delta <span class="sy1">=</span> <span class="nu0">2</span>, max_div <span class="sy1">=</span> <span class="kw3">sqrt</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">div</span> <span class="sy1">&lt;=</span> max_div<span class="sy4">;</span>
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">div</span> <span class="sy2">+</span><span class="sy1">=</span> delta, delta <span class="sy3">^</span><span class="sy1">=</span> <span class="nu0">6</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> &nbsp;<span class="co1">// delta ^= 6 меняет значение delta с 2 на 4 и наоборот</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy2">%</span> <span class="kw3">div</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Число простое</span>
&nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy4">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>На этом можно было бы остановиться (и для большинства случаев такого варианта будет достаточно). Но мы всё же продолжим издеваться над математикой!<br />
<br />
Исключим числа, делящиеся на 5, получив прирост ещё примерно на 25% (или в 3.75 раза в сравнении с первым вариантом). Но здесь нам придётся использовать массив значений <b>delta</b>, т.к. двумя числами (как в предыдущем случае – 2 и 4) мы уже не обойдёмся. Нам понадобится 8 чисел: <b>{ 4, 2, 4, 2, 4, 6, 2, 6 }</b>, которые будут повторяться. И начинать цикл мы будет с 7.<br />
<br />
Барабанная дробь :smoke:<br />
<div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="53729935"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="53729935" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Тест простоты числа n</span>
<span class="kw4">bool</span> is_prime5<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> n<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="co1">// Проверяем, что число больше 1, а также частные случаи простых чисел (2, 3 и 5)</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy1">&lt;=</span> <span class="nu0">5</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>n <span class="sy1">&gt;=</span> <span class="nu0">2</span> <span class="sy3">&amp;&amp;</span> n <span class="sy3">!</span><span class="sy1">=</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на 2, 3 и 5</span>
&nbsp; <span class="co1">// p.s. При оптимизации нормальными компиляторами с опцией -O2 деление (взятие остатка от деления)</span>
&nbsp; <span class="co1">// на константу будет выполняться быстрее, чем на переменную с заранее неизвестным значением</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>n <span class="sy3">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">3</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">5</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на остальные числа, не делящиеся на 2, 3 и 5, начиная с 7</span>
&nbsp; <span class="co1">// (с приращением, взятым из массива delta): 7, 11, 13, 17, 19, 23, 29, 31, 37...</span>
&nbsp; <span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> delta<span class="br0">&#91;</span><span class="nu0">8</span><span class="br0">&#93;</span> <span class="sy1">=</span> <span class="br0">&#123;</span> <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span> <span class="br0">&#125;</span><span class="sy4">;</span> &nbsp;<span class="co1">// массив приращений</span>
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="kw3">div</span> <span class="sy1">=</span> <span class="nu0">7</span>, idx <span class="sy1">=</span> <span class="nu0">0</span>, max_div <span class="sy1">=</span> <span class="kw3">sqrt</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="sy4">;</span> &nbsp;<span class="co1">// idx - индекс в массиве delta</span>
&nbsp; &nbsp; <span class="kw3">div</span> <span class="sy1">&lt;=</span> max_div<span class="sy4">;</span>
&nbsp; &nbsp; <span class="kw3">div</span> <span class="sy2">+</span><span class="sy1">=</span> delta<span class="br0">&#91;</span>idx<span class="br0">&#93;</span>, idx <span class="sy1">=</span> idx<span class="sy2">+</span><span class="nu0">1</span> <span class="sy3">&amp;</span> <span class="nu0">7</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> &nbsp;<span class="co1">// увеличиваем индекс на 1 с остатком от деления на 8</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy2">%</span> <span class="kw3">div</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Число простое</span>
&nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy4">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Да, здесь, как и раньше, нам придётся проверять делимость на 2, 3 и 5 вручную. Но это даже к лучшему: при оптимизации нормальными компиляторами с опцией <b>-O2</b> деление (или взятие остатка от деления) на константу будет выполняться быстрее, чем на переменную с заранее неизвестным значением (как в цикле).<br />
<br />
Кроме того, я специально использовал проверку вида <code class="inlinecode">...(n % 3 == 0 &amp;&amp; n != 3)...</code>, а не вынес <code class="inlinecode">if (n == 2 || n == 3 || n == 5) { return true; }</code> в начало, т.к. такой вариант должен работать быстрее (правда, тесты хоть и показывают прирост, но мизерный).<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6750.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><font size="3"><b>Хотите ещё?</b></font><br />
<br />
Можно, это даст ещё приращение на 10-15%, но для исключения чисел, делящихся на 7 массив <b>delta</b> будет состоять уже из 48 чисел (цикл начинается с 11):<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="682538041"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="682538041" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Тест простоты числа n</span>
<span class="kw4">bool</span> is_prime7<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> n<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="co1">// Проверяем, что число больше 1, а также частные случаи простых чисел (2, 3, 5 и 7)</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy1">&lt;=</span> <span class="nu0">10</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>n <span class="sy1">==</span> <span class="nu0">2</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">3</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">5</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">7</span><span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на 2, 3, 5 и 7</span>
&nbsp; <span class="co1">// p.s. При оптимизации нормальными компиляторами с опцией -O2 деление (взятие остатка от деления)</span>
&nbsp; <span class="co1">// на константу будет выполняться быстрее, чем на переменную с заранее неизвестным значением</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>n <span class="sy3">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">3</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">5</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">7</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на остальные числа, не делящиеся на 2, 3, 5 и 7, начиная с 11</span>
&nbsp; <span class="co1">// (с приращением, взятым из массива delta): 11, 13, 17, 19, 23, 29, 31, 37, 41, 43...</span>
&nbsp; <span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> delta<span class="br0">&#91;</span><span class="nu0">48</span><span class="br0">&#93;</span> <span class="sy1">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span> <span class="br0">&#125;</span><span class="sy4">;</span> &nbsp;<span class="co1">// массив приращений</span>
&nbsp;
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="kw3">div</span> <span class="sy1">=</span> <span class="nu0">11</span>, idx <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span>, max_div <span class="sy1">=</span> <span class="kw3">sqrt</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="sy4">;</span> &nbsp;<span class="co1">// idx - индекс в массиве delta</span>
&nbsp; &nbsp; <span class="kw3">div</span> <span class="sy1">&lt;=</span> max_div<span class="sy4">;</span>
&nbsp; &nbsp; <span class="kw3">div</span> <span class="sy2">+</span><span class="sy1">=</span> delta<span class="br0">&#91;</span>idx<span class="br0">&#93;</span>, idx <span class="sy1">=</span> <span class="br0">&#40;</span>idx <span class="sy1">==</span> <span class="nu0">47</span> <span class="sy4">?</span> <span class="nu0">0</span> <span class="sy4">:</span> idx <span class="sy2">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> &nbsp;<span class="co1">// увеличиваем индекс с остатком от деления на 48</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy2">%</span> <span class="kw3">div</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Число простое</span>
&nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy4">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
Для исключения чисел, делящихся ещё и на 11, массив <b>delta</b> будет состоять уже из 480 чисел =-O (цикл начинается с 13).<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="165783482"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="165783482" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Тест простоты числа n</span>
<span class="kw4">bool</span> is_prime11<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> n<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="co1">// Проверяем, что число больше 1, а также частные случаи простых чисел (2, 3, 5, 7 и 11)</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy1">&lt;=</span> <span class="nu0">12</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>n <span class="sy1">==</span> <span class="nu0">2</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">3</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">5</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">7</span> <span class="sy3">||</span> n <span class="sy1">==</span> <span class="nu0">11</span><span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на 2, 3, 5, 7 и 11</span>
&nbsp; <span class="co1">// p.s. При оптимизации нормальными компиляторами с опцией -O2 деление (взятие остатка от деления)</span>
&nbsp; <span class="co1">// на константу будет выполняться быстрее, чем на переменную с заранее неизвестным значением</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>n <span class="sy3">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">3</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">5</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">7</span> <span class="sy1">==</span> <span class="nu0">0</span> <span class="sy3">||</span> n <span class="sy2">%</span> <span class="nu0">11</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Проверяем делимость на остальные числа, не делящиеся на 2, 3, 5, 7 и 11, начиная с 13</span>
&nbsp; <span class="co1">// (с приращением, взятым из массива delta): 13, 17, 19, 23, 29, 31, 37, 41, 43, 47...</span>
&nbsp; <span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> delta<span class="br0">&#91;</span><span class="nu0">480</span><span class="br0">&#93;</span> <span class="sy1">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">14</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">12</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>,
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>,
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">12</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">12</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">10</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>,
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">10</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">10</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">6</span>,
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">12</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">12</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">10</span>, <span class="nu0">6</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>,
&nbsp; &nbsp; <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">12</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">10</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">14</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>,
&nbsp; &nbsp; <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">8</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">6</span>, <span class="nu0">2</span>, <span class="nu0">6</span>, <span class="nu0">4</span>, <span class="nu0">2</span>, <span class="nu0">4</span>, <span class="nu0">12</span>, <span class="nu0">2</span>, <span class="nu0">12</span> <span class="br0">&#125;</span><span class="sy4">;</span> &nbsp;<span class="co1">// массив приращений</span>
&nbsp;
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="kw3">div</span> <span class="sy1">=</span> <span class="nu0">13</span>, idx <span class="sy1">=</span> <span class="nu0">0</span>, max_div <span class="sy1">=</span> <span class="kw3">sqrt</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="sy4">;</span> &nbsp;<span class="co1">// idx - индекс в массиве delta</span>
&nbsp; &nbsp; <span class="kw3">div</span> <span class="sy1">&lt;=</span> max_div<span class="sy4">;</span>
&nbsp; &nbsp; <span class="kw3">div</span> <span class="sy2">+</span><span class="sy1">=</span> delta<span class="br0">&#91;</span>idx<span class="br0">&#93;</span>, idx <span class="sy1">=</span> <span class="br0">&#40;</span>idx <span class="sy1">==</span> <span class="nu0">479</span> <span class="sy4">?</span> <span class="nu0">0</span> <span class="sy4">:</span> idx <span class="sy2">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> &nbsp;<span class="co1">// увеличиваем индекс с остатком от деления на 480</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n <span class="sy2">%</span> <span class="kw3">div</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span><span class="sy4">;</span> <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; <span class="co1">// Число простое</span>
&nbsp; <span class="kw1">return</span> <span class="kw2">true</span><span class="sy4">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
<hr style="height:1px;border:0;color:#909090;background:#909090" /><br />
Мой спич был бы не полным, если бы я не привёл результаты теста скорости.<br />
Итак, запускаем проверку чисел от 0 до 10'000'000 на простоту на моём домашнем компьютере (Intel Core i5-2500K / Windows 10 x64).<br />
Я использовал компиляторы <b>GCC</b> (g++) и <b>Clang</b> с ключом оптимизации <b>-O2</b> для платформ x86 и x64.<br />
Результаты между различными компиляторами и платформами оказались настолько близкими (с расхождением порядка 1%), что я решил не разделять их, а объединить в одну таблицу.<br />
Здесь указано значение в секундах, доля и ускорение относительно первого варианта.<br />
<br />
<div align="center"><table cellspacing="1" cellpadding="5" class="stg_table tborder"><tbody><tr class="alt2"><td><div align="center"><b>Вариант</b></div></td><td><div align="center"><b>Время</b></div></td><td><div align="center"><b>%</b></div></td><td><div align="center"><b>Ускорение</b></td></tr><tr class="alt1"><td><a rel="nofollow noopener noreferrer" href="https://tio.run/##jVLbattAEH3XVxwUSiWSEMWPlpxf6A8EgirL7oK1cqRVKYSAE@gFHAj0uVDoS1/dNKKmjt1fmP2hOLOWVdkkgSDY1e7MnDnn7ETD4X4/ipY7QkaDohsjEGmusjhMjqzmLkpC9W7rQokkPrKsIheyj1x12@0oLZS/PDgA/aBSX@hL0D89ooX55fVSj6E/01Rf0IwmkNbbNB1A5CfDjKGcQuaiL@MuhFSQrnVmAQbru4GgG0Yc6Wsq6W6PUQxgA7YA/eKcmb7SX6gEJ93SlOYc/cQ9nU0WJnzDRSX95qTJVqHLHUUPjkTQwaGLM2SxKjKJXjjIYx/n1nOUwFglE5nSXdVIX4H7Tzb1GgfQMplM9y@fRjTX1@CaP5BtRu6lGbZd6Ir36KC1hyT8cFId8tNMOdL1VzGmuY742N3ljTkzUK3iVQXQgfeUFjR6fjY@blnF4XWVyorYt86XhlUSCuk07/NVj9mKBd1uFOux/lhrZ18q0YevPc@Dw9Dr4fjG2mf8sY00cWsHVs/PSj2ft6CqMvLkprj/UyPd@how84cgMGUBbNj@6r5S2kTtY3ksObamX4/qI7Ye@DFnNDdDwZS4nFdD62miPDGeofoCuhxdofmPudVdbHOqDhVl27h/H/UGYT9f7r9pPQA" target="_blank" title="https://tio.run/##jVLbattAEH3XVxwUSiWSEMWPlpxf6A8EgirL7oK1cqRVKYSAE@gFHAj0uVDoS1/dNKKmjt1fmP2hOLOWVdkkgSDY1e7MnDnn7ETD4X4/ipY7QkaDohsjEGmusjhMjqzmLkpC9W7rQokkPrKsIheyj1x12@0oLZS/PDgA/aBSX@hL0D89ooX55fVSj6E/01Rf0IwmkNbbNB1A5CfDjKGcQuaiL@MuhFSQrnVmAQbru4GgG0Yc6Wsq6W6PUQxgA7YA/eKcmb7SX6gEJ93SlOYc/cQ9nU0WJnzDRSX95qTJVqHLHUUPjkTQwaGLM2SxKjKJXjjIYx/n1nOUwFglE5nSXdVIX4H7Tzb1GgfQMplM9y@fRjTX1@CaP5BtRu6lGbZd6Ir36KC1hyT8cFId8tNMOdL1VzGmuY742N3ljTkzUK3iVQXQgfeUFjR6fjY@blnF4XWVyorYt86XhlUSCuk07/NVj9mKBd1uFOux/lhrZ18q0YevPc@Dw9Dr4fjG2mf8sY00cWsHVs/PSj2ft6CqMvLkprj/UyPd@how84cgMGUBbNj@6r5S2kTtY3ksObamX4/qI7Ye@DFnNDdDwZS4nFdD62miPDGeofoCuhxdofmPudVdbHOqDhVl27h/H/UGYT9f7r9pPQA">is_prime</a></div></td><td><div align="center">7.50</div></td><td><div align="center">100%</div></td><td><div align="center">1x</td></tr><tr class="alt2"><td><a rel="nofollow noopener noreferrer" href="https://tio.run/##nVPbattAEH3XVwwubSWsOJJDKbXk/EJ/IBBUWXYF1trVpRRKIEkpLTgQmudCoS99VS4qaR27vzD7Q3VntFYkkwZKJdjVnJ05e/bsyJ9Ot0a@v3oQCn@cDQJww0mSxoEX7Wo15kde@nIDSMMo2NW0LAnFCJJ00Ov5kyx1VtvbgF@xkEfyGPCXPMQlf9J4LGcgP@C1PMI55iC0F5PJGMJkfxoTlZ6JJByJYAChSEEY2lsNgLm@MAVeEOOhPMUCb0xiYcKabAl4TjlzeSI/YgG2CcRPKTn@xO8EUGJeiljIGf4ArpHvGKSgKREvm6w56F2DRIRD0AW4fegawKIA4iDNYsFon1GHwAPtPrmAVzTN8Rpv1D7yBHBB7N01N9E8AttgLot2qNiH3jgJnP8hpqEgiz6tD1w0jmSWGRyX8yl5ATs9tcOOCU9MeGrCMxNs8tAmwCbEJsgmrGt3Oh1KHU5i2LytQfga@lwfeW/2VZC8ilNdlNaUD6Nk4TphA243nFVeP1SM9/jRMPtb3QDNayy02ztK4yxwtIMVy4y8UOh1Y52RNxeUfdUoljP5vrKLvGWLl2A/tiwLdKJed/Vnsm9OL10F5kZlSdm3dHTLoclVVQ6026J5uNt2F0YFA/CPA67LZS60oKXsUSetV1t7Yk/Q2lp@9Y/dUWsBNcQcF9xeJInKaWRZfxfapwqW@g9yabVkc@5qq3ZpcaQCJbnF7v/2h2NvlKy2nnf/AA" target="_blank" title="https://tio.run/##nVPbattAEH3XVwwubSWsOJJDKbXk/EJ/IBBUWXYF1trVpRRKIEkpLTgQmudCoS99VS4qaR27vzD7Q3VntFYkkwZKJdjVnJ05e/bsyJ9Ot0a@v3oQCn@cDQJww0mSxoEX7Wo15kde@nIDSMMo2NW0LAnFCJJ00Ov5kyx1VtvbgF@xkEfyGPCXPMQlf9J4LGcgP@C1PMI55iC0F5PJGMJkfxoTlZ6JJByJYAChSEEY2lsNgLm@MAVeEOOhPMUCb0xiYcKabAl4TjlzeSI/YgG2CcRPKTn@xO8EUGJeiljIGf4ArpHvGKSgKREvm6w56F2DRIRD0AW4fegawKIA4iDNYsFon1GHwAPtPrmAVzTN8Rpv1D7yBHBB7N01N9E8AttgLot2qNiH3jgJnP8hpqEgiz6tD1w0jmSWGRyX8yl5ATs9tcOOCU9MeGrCMxNs8tAmwCbEJsgmrGt3Oh1KHU5i2LytQfga@lwfeW/2VZC8ilNdlNaUD6Nk4TphA243nFVeP1SM9/jRMPtb3QDNayy02ztK4yxwtIMVy4y8UOh1Y52RNxeUfdUoljP5vrKLvGWLl2A/tiwLdKJed/Vnsm9OL10F5kZlSdm3dHTLoclVVQ6026J5uNt2F0YFA/CPA67LZS60oKXsUSetV1t7Yk/Q2lp@9Y/dUWsBNcQcF9xeJInKaWRZfxfapwqW@g9yabVkc@5qq3ZpcaQCJbnF7v/2h2NvlKy2nnf/AA">is_prime2</a></div></td><td><div align="center">3.80</div></td><td><div align="center">51%</div></td><td><div align="center">2.0x</td></tr><tr class="alt1"><td><a rel="nofollow noopener noreferrer" href="https://tio.run/##nVTtbhJBFP2/T3GDqbIppUCtxsL2FXwBY4Ow4CYwILsYE9ukpfErNJL428TEP/6lpGuxfL3CzAuJ587sdsFaY2xSZufOvWfOvefOrbTbW/VKZXnHE5VGt@pSyWv5QcctN/etxFZploPna4bAa7r7ltX1PVEnP6ju7VVa3aC43N4m@VWG6kT1SC7UsZzzJ357qk/qnRyrEzmRQxLWs1arQZ5/0O4AKt0VvlcXbpU8EZCwrdcWEWN9YQg5AuKxGshQTjNAYcAEbE7yHD4Tdabey5DyGQI@XIbySn6HAY5DTWKm@rxFjDploxyvUFR99SbGDOWE0gXC@Y4NHl6N0oJKDnbEvIg6btDtCLbuO1SwizAeWbcxJnnBiHIsp9FVZyRn4GhuMGHtrJ81sSA1B62e9h/LS5B/i3XMMXOcT0Ecuepspmy@gv9ULuAzUQNd62O48JE6MVgcH8oftPW4EJMJgQYjpcH0UofxLlJriP8rEGTZ1gLUwI6yZP765pmJwNpTp1BCnXIAx41AcMHC4GzAWcNzwB59XYRjQIaspqmRBlxw1Xivr5tBpo86CS4CJzXjGNILV2ZkGs2Ugr0AovF0bnIaaQeZ7lLeJsehHB0ekqAN2tE76BlrWSs3fLf4PzImXZ3R1CJH5PyBaZisE721E9Mc63XACe6aS9OcK3fkmLNF@HUmpFveoGRWNvftPdrN0MMM5dH3eYDn@ftRhgr4LuCogO@dfDabxRW1VofWX1rVe0kOI1TdRlDGJ9Cb5VcHxu6/6ARpodtb/7EVzyByWDNvOgYiRnrq0AOuLqeVWMgoywXlDvlNsMgRRShE2ZFp@yGUONd9jYbUt5onuWH43yLkypv8loyKlZkkQ@v6KQedrlu0jpZclGbZE@lkBH1Cd43gffGXaQHJ55S/l8vlIGIvnn@f@U3y22E57VgAPeFQ3VwRS8lEFWlzU8TThZO7HozCjs1EPGKpVOKwEqUoZRQwmSanqSfiicBZRD@exjfY5lgNPE5@JaCEcPwyrT8TdRDBVP@BLk41WvEmt/iWFO/MxlBOcfV/VmqNct1fYlD9Ag" target="_blank" title="https://tio.run/##nVTtbhJBFP2/T3GDqbIppUCtxsL2FXwBY4Ow4CYwILsYE9ukpfErNJL428TEP/6lpGuxfL3CzAuJ587sdsFaY2xSZufOvWfOvefOrbTbW/VKZXnHE5VGt@pSyWv5QcctN/etxFZploPna4bAa7r7ltX1PVEnP6ju7VVa3aC43N4m@VWG6kT1SC7UsZzzJ357qk/qnRyrEzmRQxLWs1arQZ5/0O4AKt0VvlcXbpU8EZCwrdcWEWN9YQg5AuKxGshQTjNAYcAEbE7yHD4Tdabey5DyGQI@XIbySn6HAY5DTWKm@rxFjDploxyvUFR99SbGDOWE0gXC@Y4NHl6N0oJKDnbEvIg6btDtCLbuO1SwizAeWbcxJnnBiHIsp9FVZyRn4GhuMGHtrJ81sSA1B62e9h/LS5B/i3XMMXOcT0Ecuepspmy@gv9ULuAzUQNd62O48JE6MVgcH8oftPW4EJMJgQYjpcH0UofxLlJriP8rEGTZ1gLUwI6yZP765pmJwNpTp1BCnXIAx41AcMHC4GzAWcNzwB59XYRjQIaspqmRBlxw1Xivr5tBpo86CS4CJzXjGNILV2ZkGs2Ugr0AovF0bnIaaQeZ7lLeJsehHB0ekqAN2tE76BlrWSs3fLf4PzImXZ3R1CJH5PyBaZisE721E9Mc63XACe6aS9OcK3fkmLNF@HUmpFveoGRWNvftPdrN0MMM5dH3eYDn@ftRhgr4LuCogO@dfDabxRW1VofWX1rVe0kOI1TdRlDGJ9Cb5VcHxu6/6ARpodtb/7EVzyByWDNvOgYiRnrq0AOuLqeVWMgoywXlDvlNsMgRRShE2ZFp@yGUONd9jYbUt5onuWH43yLkypv8loyKlZkkQ@v6KQedrlu0jpZclGbZE@lkBH1Cd43gffGXaQHJ55S/l8vlIGIvnn@f@U3y22E57VgAPeFQ3VwRS8lEFWlzU8TThZO7HozCjs1EPGKpVOKwEqUoZRQwmSanqSfiicBZRD@exjfY5lgNPE5@JaCEcPwyrT8TdRDBVP@BLk41WvEmt/iWFO/MxlBOcfV/VmqNct1fYlD9Ag">is_prime3</a></div></td><td><div align="center">2.52</div></td><td><div align="center">34%</div></td><td><div align="center">3.0x</td></tr><tr class="alt2"><td><a rel="nofollow noopener noreferrer" href="https://tio.run/##nVXbTttAEH33V0xTQWMRQhKuxQm/0A8oCLlOAEvJhsZOhVSQIKg3BTVSnytV6ktfaYRLgCT8wu4PlZ7ZtXMRUFV9iPc2c/bMmdmJt78/v@t5d0994VWb5QoV/XoQNipubcMa73k1N9yb2gj9WmXDspqBL3YpCMvr6169GTp3Cwskv8tInagWyVt1LIc8xbel2qQ@yJ46kTfynIT1ql6vkh9s7zcAlW6KwN8VlTL5IiRhW28tIsb6xhCyC8Rj1ZGR7GeAwoBjsCHJn7C5UWfqo4wonyHgw@RcXstf2IDhuSYxUG1ewked8qbsTVBUbfUuwYzkDaULGVokmCzboOLvUFpQsYQVMTWiRiVsNgTvbpSoQLOzJOhJiZZsB8dH1mP0SV4wvOzJfnzvGckBCI@uM5772SBr3EFyCJot7dKTlwjmPcYeuw1x3kcgiF1H1@fta9j35S1sblRHa38MEz5SJwaL/SN5RfMvCgmfCGjYpDTIXmo3XsXZO8fvGhw5jVMOqmPHgXII@uaB8cDYUqfIjDplB/brguAtJwpnHQ4clh22aGsdjgEZcXaNTBrwloXjtb5ugLR91kGwCBzUgH1ID6xM1xSekYKtAKLxdGyyHycSOZulvE2lEuXo8BCJm4H2k6tlvUKqkzTvuNWg4vxPXhMJRzmKJp5BRnOPfSHKJ@ZpZJmqCW3HofT02GERVg2VNOvBVdxjRYAwihZOcS6NHFCIuFqAf4JFFxeUK9XQtddpNUN5vJv8In48f56hAuYFjIvYX1zNZrO4Lgjd0PfIq4sgpNGL9fbchkF6ubZFJYi2lGHqo@@KnqzQkWPEm@DwEPUr3LRTb9B0Tyj7b4ANcn75AJNchmruwbbZDV43wrSwDTyfz5NWimW9Zn2604FHhq5@x4yAdx2DOaO9uVIcE/C2klvxncujeFa5NPgyVHfX5F0nB5qaYpi6nVOZN49v4jkN2e7@gzLma5qH6TozJvZHCnKi2fwYN8SJzisja9Stwkaz4lhHdyxozfVFetxov6BIurC@@EtPBNMh5Z/lcjmUXSvp8l@503AAnEU7SZ7u45woB0PReDk0NyeSBsrBjdq/sJNtIv4joWKR3YqUopTJiYl0fJraFJsCZzH95D/nHtscpx4th98@KMEdX6b1MNESPJjqP9DFqUZz7nNLbknxyiwM5RSr/9vbqbq7wR3a7x8" target="_blank" title="https://tio.run/##nVXbTttAEH33V0xTQWMRQhKuxQm/0A8oCLlOAEvJhsZOhVSQIKg3BTVSnytV6ktfaYRLgCT8wu4PlZ7ZtXMRUFV9iPc2c/bMmdmJt78/v@t5d0994VWb5QoV/XoQNipubcMa73k1N9yb2gj9WmXDspqBL3YpCMvr6169GTp3Cwskv8tInagWyVt1LIc8xbel2qQ@yJ46kTfynIT1ql6vkh9s7zcAlW6KwN8VlTL5IiRhW28tIsb6xhCyC8Rj1ZGR7GeAwoBjsCHJn7C5UWfqo4wonyHgw@RcXstf2IDhuSYxUG1ewked8qbsTVBUbfUuwYzkDaULGVokmCzboOLvUFpQsYQVMTWiRiVsNgTvbpSoQLOzJOhJiZZsB8dH1mP0SV4wvOzJfnzvGckBCI@uM5772SBr3EFyCJot7dKTlwjmPcYeuw1x3kcgiF1H1@fta9j35S1sblRHa38MEz5SJwaL/SN5RfMvCgmfCGjYpDTIXmo3XsXZO8fvGhw5jVMOqmPHgXII@uaB8cDYUqfIjDplB/brguAtJwpnHQ4clh22aGsdjgEZcXaNTBrwloXjtb5ugLR91kGwCBzUgH1ID6xM1xSekYKtAKLxdGyyHycSOZulvE2lEuXo8BCJm4H2k6tlvUKqkzTvuNWg4vxPXhMJRzmKJp5BRnOPfSHKJ@ZpZJmqCW3HofT02GERVg2VNOvBVdxjRYAwihZOcS6NHFCIuFqAf4JFFxeUK9XQtddpNUN5vJv8In48f56hAuYFjIvYX1zNZrO4Lgjd0PfIq4sgpNGL9fbchkF6ubZFJYi2lGHqo@@KnqzQkWPEm@DwEPUr3LRTb9B0Tyj7b4ANcn75AJNchmruwbbZDV43wrSwDTyfz5NWimW9Zn2604FHhq5@x4yAdx2DOaO9uVIcE/C2klvxncujeFa5NPgyVHfX5F0nB5qaYpi6nVOZN49v4jkN2e7@gzLma5qH6TozJvZHCnKi2fwYN8SJzisja9Stwkaz4lhHdyxozfVFetxov6BIurC@@EtPBNMh5Z/lcjmUXSvp8l@503AAnEU7SZ7u45woB0PReDk0NyeSBsrBjdq/sJNtIv4joWKR3YqUopTJiYl0fJraFJsCZzH95D/nHtscpx4th98@KMEdX6b1MNESPJjqP9DFqUZz7nNLbknxyiwM5RSr/9vbqbq7wR3a7x8">is_prime5</a></div></td><td><div align="center">2.02</div></td><td><div align="center">27%</div></td><td><div align="center">3.7x</td></tr><tr class="alt1"><td><a rel="nofollow noopener noreferrer" href="https://tio.run/##nVXbbtNAEH33V4yCCrHqhjhJ01In8Al8AEXIOGlrKXFK7CAkqNSm4qYiIvGMhMQLryXCNG2T9Bd2f4hyZtdOnLYgxEOyu@OZM5czO@vt7q5se97lLT/wWr1Gk2p@J4y6Tbd935jLvLYb7SwIIr/dvG8YvdAPtimMGhsbXqcXOZd375L4KmJ5IPskLuS@mPIW/315RPKtGMkDcS6OKTCedjot8sMnu11A5XtB6G8HzQb5QUSBabw0iBjrC0OIIRD35UDEYmwBhQHnYFMS36FzLj/IdyIm2yLgQ@VYnImfEEDxWAUxkUd8hI08ZKEYZUKUR/J1ihmLc8qXLCpbtErQWjMRjb9F@YBqdbKLJnF4RN1m1OsGLK7XqUSvXpHalWe71dluzXRgsmf8KS0SP9itGIlxEs8HEhMkkg1DG@8WwoJGQPxTZNBXViNxgjzfYB2x5RTfx8gRZVGJj1l8Bv2xuIDOuRwoWvahwp/kgcZi@1ic0srDUhpSDDQIKY94T5QZnxJij/E7Q5jM8IKBHJhJrpyF8jzRFlj78hCkyUM2YLshArxgDvFtwLlDc8AaR6oU@4CMmXhdKQV4wbXjs3I3AaMfVRJcBE5qwjakFq7MUPekLgVrAUThqdzEOCEYVN4m22TGipq7JdCZPa0unNbUCf2Q9sKW2wqbzv8QnRZ0xlicuS@WyiSxRYnec9S6SFebRKlybiO1Drgqtq3DyXOFuOVHXCOgzPKHVcKuLhBqRtw/8HGAwxBOGs1W5JobALPIhjsbrux7FpWwL2EtQ16GrIK1Ui4UCvAZRm7ke@R1gjCi2R33dtyuhntUWX9M9eQ6IYuKlfxX1aa6KLkirKby9YxayVJYFSWtZrCyoNW/esK/XUwW2nM0kZla3FTCUyZ8q9OlxUnW8J8jPa6Y33iB3Qp2bffFEy0Pn3WjfGBqD6ywQoo1ZvmMqRouchDroqkEGQHDKAFzZrLlelJZ4D1O3ebVUqfKGj1A824o8TIanTuXneMqDnVbqsYB3bpXs9GoEZG59FNWuH7tdUdW1lVEemgu6Tr84aZkxuK3@UjPvB0iNmazNur2mo6xd8nFbbt@kJ8/FZ/QuUNo//jLVEeoU7LvFItF3IV@@k595oHIGTClZkqkeolQvKKDpaatHFpeDtLxz8nNHrDATMVE/BRSrcZmNcpRTrOjM51/zW0GmwG@JeGnr@a1aIvcBJiMPKIQEszxz2HdHCg/UBzqP4SLrwrNuR5b6iXHJ33QIee4@r@8rZa7HV7ilfgN" target="_blank" title="https://tio.run/##nVXbbtNAEH33V4yCCrHqhjhJ01In8Al8AEXIOGlrKXFK7CAkqNSm4qYiIvGMhMQLryXCNG2T9Bd2f4hyZtdOnLYgxEOyu@OZM5czO@vt7q5se97lLT/wWr1Gk2p@J4y6Tbd935jLvLYb7SwIIr/dvG8YvdAPtimMGhsbXqcXOZd375L4KmJ5IPskLuS@mPIW/315RPKtGMkDcS6OKTCedjot8sMnu11A5XtB6G8HzQb5QUSBabw0iBjrC0OIIRD35UDEYmwBhQHnYFMS36FzLj/IdyIm2yLgQ@VYnImfEEDxWAUxkUd8hI08ZKEYZUKUR/J1ihmLc8qXLCpbtErQWjMRjb9F@YBqdbKLJnF4RN1m1OsGLK7XqUSvXpHalWe71dluzXRgsmf8KS0SP9itGIlxEs8HEhMkkg1DG@8WwoJGQPxTZNBXViNxgjzfYB2x5RTfx8gRZVGJj1l8Bv2xuIDOuRwoWvahwp/kgcZi@1ic0srDUhpSDDQIKY94T5QZnxJij/E7Q5jM8IKBHJhJrpyF8jzRFlj78hCkyUM2YLshArxgDvFtwLlDc8AaR6oU@4CMmXhdKQV4wbXjs3I3AaMfVRJcBE5qwjakFq7MUPekLgVrAUThqdzEOCEYVN4m22TGipq7JdCZPa0unNbUCf2Q9sKW2wqbzv8QnRZ0xlicuS@WyiSxRYnec9S6SFebRKlybiO1Drgqtq3DyXOFuOVHXCOgzPKHVcKuLhBqRtw/8HGAwxBOGs1W5JobALPIhjsbrux7FpWwL2EtQ16GrIK1Ui4UCvAZRm7ke@R1gjCi2R33dtyuhntUWX9M9eQ6IYuKlfxX1aa6KLkirKby9YxayVJYFSWtZrCyoNW/esK/XUwW2nM0kZla3FTCUyZ8q9OlxUnW8J8jPa6Y33iB3Qp2bffFEy0Pn3WjfGBqD6ywQoo1ZvmMqRouchDroqkEGQHDKAFzZrLlelJZ4D1O3ebVUqfKGj1A824o8TIanTuXneMqDnVbqsYB3bpXs9GoEZG59FNWuH7tdUdW1lVEemgu6Tr84aZkxuK3@UjPvB0iNmazNur2mo6xd8nFbbt@kJ8/FZ/QuUNo//jLVEeoU7LvFItF3IV@@k595oHIGTClZkqkeolQvKKDpaatHFpeDtLxz8nNHrDATMVE/BRSrcZmNcpRTrOjM51/zW0GmwG@JeGnr@a1aIvcBJiMPKIQEszxz2HdHCg/UBzqP4SLrwrNuR5b6iXHJ33QIee4@r@8rZa7HV7ilfgN">is_prime7</a></div></td><td><div align="center">1.75</div></td><td><div align="center">23%</div></td><td><div align="center">4.3x</td></tr><tr class="alt2"><td><a rel="nofollow noopener noreferrer" href="https://tio.run/##nVfdbuJGFL7nKY6otgXFYbEhxhtg@wh9gO5qRYFkLYFJsalW6kZKiPqnrIrU60qVetPbFC1dNgHyCuMXavqdGdv4B9O0F@CZM3O@852f8Rx3z84OT7vdh09spzuY9PrUskeuN@53hs8LW1l32PFeJwSePew/LxQmru2ckuv1jo@7o4nXfHj6lMTvYuFf@lMS9/6F2PAQ/1P/mvwfxNK/FHfihpzCV6PRgGz31dkYUKWJ49qnTr9HtuORUy58WyBirN8YQsyBeOHPxEKsNKAw4BZsQ@JP7Lnz3/k/igXpGgEfW27ErfgLAmy8kSTW/jVPoeNfsVAsYxT9a/@7EHMh7qhkaFTT6EijBmGjrpfByD6hkkOtNulGmZgi0bjvTcYOi9ttMujtW5KjWjQ6ikaNaAS0JrTPC3leknjPLMRSrAJ670is4VealQI4q7gVhQKXNnBqKjWX4gNc/x7PJWtvsL6C24iUjMWKxbfYvxL32HPnz2SmLrCFl/xLhcX6C/GRDr8wQloLoEFIJXD@INV4FuT6Br9bUOWkJxT8WTnwlz2RltdKA8@pf4U8@leswHpzELzntGJtxv5j54x3XMtwXABywbWgoiUB7zl@PJfm1kjyz9IJDgI7tWYdkg@OzFyVqQoF7wKIxJO@iVWQb2T2U9LLnLaqSuATZDc@O0rMGomZrsspqiWslJPOwO03/0/uw/hGCVzETpQmHQt0EbGf2AkVs111I7ezu0v5nHGg9JqiVOKg8cFYctiAFIUEWkHCVcwQRuKSgp1LTOYw1OsPvE75GGAa6Q38nmlkYGzgWYPZGmR1POuQ1RuVSgU2Xa/j2V3qjhzXo@hN0H3dGSu4L@tW9SW1gxNX19gb/JtyYGoJSUpohnIrtk3@Syy9HkPSq6FKCnO7pqR6WiC3ScC4yUeyUVMzDpkAy5KJ4wVKWTpxG8pXI4dMsBDpWrG1lFllJkxDNgHGDkLxMJg70pSJm5VkuJOOFbO7zdsWLIdLysGdVWNtbSTrLRudrGt5lRkELUnI3FvGVirLVhZO0eFFM0kvj4yZF5b8lKZ8zD9QUWQklpW0bebW5p48mem4ZXOfomP@Sw1LsJ11aD6GS3JX@sjved3oRs6Z0tNvJGvfgTL/w6svipuZKfg9B9zcXZWxg8CQiTdGophTZBJrwcvWSJ3T/Wz2nKmAhW7QeVPdpbGraNcN9pHv3JPRmJLtZs/@BpcLX1h27w1G4DzsvHmlxO7XY6/klJUBXj8keWfyPXvLF@U8eQMu1JUl/WMENIsBWDOSHbSDew14L0OrJflo41J8Rp@jgTiW8gO0Htw8sHU0R3PVGch7G7etahfidGTTFmvDNrwh24ippgDXquSk2tonKhA53UqsW/1j23jHOnyxKETdsDee9JuF8weO7rBjO6VtQ/8LOoc5dr/f03uD64b0z6rVKnqRafg18Sv3qOwC57QcZlJ@L3DSmni0lFaTDg6csEFn56LPDKccion4g4VaLVZrUZGKKj/K0@1q8YXzwsFaQD/8tsmwrXIZoFnlrhGUoI5/prWbKOqtylQfQRerEq2Z5RZaKfJMTRTlIkf/7@7JoHPqPqBx/wc" target="_blank" title="https://tio.run/##nVfdbuJGFL7nKY6otgXFYbEhxhtg@wh9gO5qRYFkLYFJsalW6kZKiPqnrIrU60qVetPbFC1dNgHyCuMXavqdGdv4B9O0F@CZM3O@852f8Rx3z84OT7vdh09spzuY9PrUskeuN@53hs8LW1l32PFeJwSePew/LxQmru2ckuv1jo@7o4nXfHj6lMTvYuFf@lMS9/6F2PAQ/1P/mvwfxNK/FHfihpzCV6PRgGz31dkYUKWJ49qnTr9HtuORUy58WyBirN8YQsyBeOHPxEKsNKAw4BZsQ@JP7Lnz3/k/igXpGgEfW27ErfgLAmy8kSTW/jVPoeNfsVAsYxT9a/@7EHMh7qhkaFTT6EijBmGjrpfByD6hkkOtNulGmZgi0bjvTcYOi9ttMujtW5KjWjQ6ikaNaAS0JrTPC3leknjPLMRSrAJ670is4VealQI4q7gVhQKXNnBqKjWX4gNc/x7PJWtvsL6C24iUjMWKxbfYvxL32HPnz2SmLrCFl/xLhcX6C/GRDr8wQloLoEFIJXD@INV4FuT6Br9bUOWkJxT8WTnwlz2RltdKA8@pf4U8@leswHpzELzntGJtxv5j54x3XMtwXABywbWgoiUB7zl@PJfm1kjyz9IJDgI7tWYdkg@OzFyVqQoF7wKIxJO@iVWQb2T2U9LLnLaqSuATZDc@O0rMGomZrsspqiWslJPOwO03/0/uw/hGCVzETpQmHQt0EbGf2AkVs111I7ezu0v5nHGg9JqiVOKg8cFYctiAFIUEWkHCVcwQRuKSgp1LTOYw1OsPvE75GGAa6Q38nmlkYGzgWYPZGmR1POuQ1RuVSgU2Xa/j2V3qjhzXo@hN0H3dGSu4L@tW9SW1gxNX19gb/JtyYGoJSUpohnIrtk3@Syy9HkPSq6FKCnO7pqR6WiC3ScC4yUeyUVMzDpkAy5KJ4wVKWTpxG8pXI4dMsBDpWrG1lFllJkxDNgHGDkLxMJg70pSJm5VkuJOOFbO7zdsWLIdLysGdVWNtbSTrLRudrGt5lRkELUnI3FvGVirLVhZO0eFFM0kvj4yZF5b8lKZ8zD9QUWQklpW0bebW5p48mem4ZXOfomP@Sw1LsJ11aD6GS3JX@sjved3oRs6Z0tNvJGvfgTL/w6svipuZKfg9B9zcXZWxg8CQiTdGophTZBJrwcvWSJ3T/Wz2nKmAhW7QeVPdpbGraNcN9pHv3JPRmJLtZs/@BpcLX1h27w1G4DzsvHmlxO7XY6/klJUBXj8keWfyPXvLF@U8eQMu1JUl/WMENIsBWDOSHbSDew14L0OrJflo41J8Rp@jgTiW8gO0Htw8sHU0R3PVGch7G7etahfidGTTFmvDNrwh24ippgDXquSk2tonKhA53UqsW/1j23jHOnyxKETdsDee9JuF8weO7rBjO6VtQ/8LOoc5dr/f03uD64b0z6rVKnqRafg18Sv3qOwC57QcZlJ@L3DSmni0lFaTDg6csEFn56LPDKccion4g4VaLVZrUZGKKj/K0@1q8YXzwsFaQD/8tsmwrXIZoFnlrhGUoI5/prWbKOqtylQfQRerEq2Z5RZaKfJMTRTlIkf/7@7JoHPqPqBx/wc">is_prime11</a></div></td><td><div align="center">1.60</div></td><td><div align="center">21%</div></td><td><div align="center">4.7x</div></td></tr></tbody></table></div><br />
Используйте ссылки в таблице выше, посмотреть и протестировать код на платформе <a rel="nofollow noopener noreferrer" href="https://tio.run" target="_blank" title="https://tio.run">Try It Online</a>.<br />
<br />
<font color="Blue">Исходники с тестовым кодом (более полным, чем на tio.run) прикреплены к статье в виде архива.</font><br />
<br />
На этом всё.<br />
<font color="DarkRed"><b>Если вы знаете более быстрые варианты <i>точного</i> определения простоты числа, буду рад, если поделитесь в комментариях ;)</b></font><br />
<br />
<hr style="height:1px;border:0;color:#909090;background:#909090" /><br />
<b>update 04.03.2019</b>: добавлены функции <b>is_prime7</b>, <b>is_prime11</b> (в спойлерах), тип изменён на <code class="inlinecode">unsigned int</code>. Архив перезалит.</div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5299&amp;d=1551718278">is_prime.zip</a> (6.6 Кб, 896 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5712.html</guid>
		</item>
		<item>
			<title>«Карла и Джек – слаженный дуэт» или «Караоке Home Edition»</title>
			<link>https://www.cyberforum.ru/blogs/521524/5499.html</link>
			<pubDate>Sat, 27 Oct 2018 06:44:41 GMT</pubDate>
			<description>*«Карла и Джек – слаженный дуэт» или «Караоке Home Edition»* 
 
Коля любит Олю, Оля любит мамбу, а...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>«Карла и Джек – слаженный дуэт» или «Караоке Home Edition»</b></font></font></div><br />
Коля любит Олю, Оля любит мамбу, а я люблю петь &#127908;. Громко, долго и &quot;с огоньком&quot;. От зарубежного рока (преимущественно) до... <s>русской попсы</s> ладно, не будем углубляться, потому как речь в этой статье пойдёт не столько обо мне, сколько о реализации данного процесса своими силами.<br />
<br />
<font size="4"><b>Любители пева</b></font><br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6543.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
Караоке-ресторан – дело хорошее, но это не всегда удобно, тем более, что сие развлечение можно организовать и дома при наличии достаточного технического оснащения.<br />
Так что, если вы тоже любите затянуть нотку повыше, вам понадобятся:<ul><li><b>Компьютер с</b> некоторыми установленными <b>программами</b> (о которых ниже).</li>
<li><b>Звуковая карта/USB-аудиоинтерфейс с поддержкой ASIO</b>. В крайнем случае можно воспользоваться драйвером <a rel="nofollow noopener noreferrer" href="http://www.asio4all.org" target="_blank" title="http://www.asio4all.org">ASIO4ALL</a>, правда, я его использовал очень давно, ещё с картой SB а-ля AWE32 и не проверял в связке с описываемым ниже софтом, поэтому не знаю, будет ли он работать и с какими задержками – если попробуете, отпишитесь в комментах, плиз. В принципе, JACK (это прога такая, см. ниже) может работать и без него, но большие задержки в этом случае неминуемы – петь в таких условиях будет нереально ужасно %-), а с ASIO4ALL хоть есть шанс на спасение. I have <a rel="nofollow noopener noreferrer" href="https://www.muztorg.ru/product/A063906" target="_blank" title="https://www.muztorg.ru/product/A063906">Focusrite Scarlett 2i4</a> (ссылка на 2-е поколение, хотя у меня 1-е... зато я успел урвать его вместе с миком, когда всё это счастье стоило в 2 раза дешевле :D).</li>
<li><b>Вокальный динамический микрофон</b>. Не Defender за 500 руб, а что-нибудь получше, иначе такое караоке будет не в радость ни вам, ни ближнему вашему. Желательно также, чтобы микрофон имел [супер]кардиоидную диаграмму направленности, а не был всенаправленным, иначе будете ловить обратку (свист). Конденсаторный микрофон я бы для караоке тоже брать не стал (а если на вашей звуковухе нет фантомного питания 48 В, то о нём вообще лучше пока забыть). I have <a rel="nofollow noopener noreferrer" href="https://www.muztorg.ru/product/18433" target="_blank" title="https://www.muztorg.ru/product/18433">Shure beta 58a</a> (классика, собственно, как и более приемлемый по цене <a rel="nofollow noopener noreferrer" href="https://www.muztorg.ru/product/16906" target="_blank" title="https://www.muztorg.ru/product/16906">Shure SM58</a> (есть вариант <a rel="nofollow noopener noreferrer" href="https://www.muztorg.ru/product/16932" target="_blank" title="https://www.muztorg.ru/product/16932">с переключателем вкл/выкл</a>); кстати, эти 2 микрофона чаще других мелькают в телеке). Думаю, и ежу понятно, что разъём кабеля (который, к слову, обычно покупается отдельно) должен подходить к разъёму вашей звуковухи, учитывая балансность (обычно используется XLR или балансный TRS 6.35 мм (&#188;&quot;), он же большой джек, которых в &quot;игровых&quot; звуковухах типа Creative Sound Blaster нет, а проф/полупроф быть непременно должны).</li>
<li><b>Акустическая система</b> (активная, либо с отдельно стоящим усилителем). Компьютерные колонки среднего калибра (50+ Вт) тоже сгодятся, но для полного счастья (вам же нужно полное?) лучше иметь что-то получше. К сожалению, моё счастье тоже неполное, но этот недочёт я обязательно исправлю :-[.</li>
<li><b>Минусовки</b>, скаченные, например, с <a rel="nofollow noopener noreferrer" href="http://x-minus.me" target="_blank" title="http://x-minus.me">x-minus.me</a> (там обычно всё есть), <a rel="nofollow noopener noreferrer" href="https://b-track.ru" target="_blank" title="https://b-track.ru">b-track.ru</a>, <a rel="nofollow noopener noreferrer" href="http://muzmix.com" target="_blank" title="http://muzmix.com">muzmix.com</a> или... <a rel="nofollow noopener noreferrer" href="https://vk.com" target="_blank" title="https://vk.com">vk.com</a> (со словами &quot;минус&quot;, &quot;minus&quot;, &quot;караоке&quot;, &quot;karaoke&quot;, &quot;instrumental&quot;; надеюсь, о существовании браузерного плагина <a rel="nofollow noopener noreferrer" href="http://vkopt.net" target="_blank" title="http://vkopt.net">VkOpt</a>, который поможет скачать аудио, вы знаете?) Есть ещё варианты, о которых я расскажу чуть позже ;)</li>
</ul>Шутить про хорошее настроение и компанию (при желании) я уж не буду – с этим, думаю, вы разберётесь сами. Акустические характеристики и отделку комнаты тоже опустим :)<br />
<br />
<font size="4"><b>Давай помягче!</b></font><br />
<br />
С хардом мы более или менее разобрались, теперь перейдём к софту. Хм, а что, замечательного &quot;проигрывателя Windows Media&quot; недостаточно? =-O Во-первых, нам нужно выводить наши поступающие  в микрофон голосовые вибрации наружу (в колонки), чтобы радовать соседей. Но с этим многие аудиоинтерфейсы справляются и без софта; хотя я не знаю, что у вас за звуковуха. Во-вторых, чтобы придать голосу объёма (и почувствовать себя как минимум Фредди Меркьюри, требующим продолжение <s>банкета</s> шоу, или Энрико Карузо в кафедральном соборе – смотря кто вам ближе) необходимо наложить полтонны ревера, дилея подлиннее <s>и тремоло</s>.<br />
<br />
Вариантов тут несколько, но я расскажу об одном (а вы можете поделиться своими в комментах... вы же поделитесь?) Для &quot;придания объёма&quot; и чтоб &quot;просто баловаться&quot; по полной я вообще хотел купить вокальный процессор вроде <a rel="nofollow noopener noreferrer" href="https://www.muztorg.ru/product/A038000" target="_blank" title="https://www.muztorg.ru/product/A038000">TC Helicon VoiceLive Play</a>), но ради экономии 20 килорублей решил сперва поинтересоваться софтовыми вариантами реализации предоставляемых этим девайсом фич. И вот что я нашёл (вернее, подсказали):<ul><li><a rel="nofollow noopener noreferrer" href="http://jackaudio.org/downloads/" target="_blank" title="http://jackaudio.org/downloads/"><b>JACK Audio Connection Kit</b></a> (Windows, Linux, macOS; freeware). <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/JACK_Audio_Connection_Kit" target="_blank" title="https://ru.wikipedia.org/wiki/JACK_Audio_Connection_Kit">Википедия</a> называет его &quot;звуковым сервер-демоном&quot; :D. По факту же это нечто вроде драйвера, предоставляющего API-интерфейс для соединения хардовых и софтовых устройств. С его помощью можно соединить вход и выход с минимальной задержкой. Но нам же нужны ещё спецэффекты! С помощью JACK'а их тоже можно &quot;подрубить&quot; где-то посередине, осталось их только где-то взять.</li>
<li><a rel="nofollow noopener noreferrer" href="https://github.com/falkTX/Carla/releases" target="_blank" title="https://github.com/falkTX/Carla/releases"><b>Carla</b></a> (Windows, Linux, macOS; freeware). Хост аудиоплагинов. Нам он пригодится для подключения в цепь VST-плагинов.</li>
<li><b>VST-плагин</b> для добавления вокальных эффектов. Например, <a rel="nofollow noopener noreferrer" href="https://www.izotope.com/en/products/mix/nectar.html" target="_blank" title="https://www.izotope.com/en/products/mix/nectar.html"><b>iZotope Nectar</b></a> (Windows, macOS(?); shareware). В общем-то, всего 200 баксов (ой, пардон, 199) и лицензия ваша! :yahoo: Но сначала его можно try-нуть!</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.aimp.ru/?do=download" target="_blank" title="http://www.aimp.ru/?do=download"><b>AIMP</b></a> (Windows; freeware). Аудиоплеер (для воспроизведения минусовок). Опционально. Нравится &quot;проигрыватель Windows Media&quot; – не вопрос, пользуйтесь. Если у вас не Windows – подберите удобный вам плеер сами.</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.karafun.com/apps/" target="_blank" title="https://www.karafun.com/apps/"><b>KaraFun Player</b></a> (Windows, macOS; freemium). Караоке-плеер. Тоже опционально. Воспроизводит файлы формата KFN, CDG (а также MP3, KAR и многие другие) – караоке-файлы, содержащие в себе минусовки формата MP3 и синхронизированные тексты (KFN – всё в одном файле, CDG – дополнение к MP3); их можно найти на торрентах, купить на сайтах вроде <a rel="nofollow noopener noreferrer" href="http://karafun-karaoke.ru" target="_blank" title="http://karafun-karaoke.ru">этого</a> (не пользовался) и пр. Основной функционал программы бесплатен, но по подписке открывается доступ к официальной караоке-базе.</li>
</ul><br />
<font size="4"><b>Что теперь со всем этим добром делать?</b></font><br />
<br />
Покупки сделаны. Железяки соединены. Софт установлен. Минусовки скачены. Компьютер включен. Микрофон в руке. Рот открыт.<br />
Стоп, стоп, стоп! Закройте рот и положите микрофон. Сначала нужно настроить софт. Повторяйте за мной.<ol style="list-style-type: decimal"><li><b>Запускаем JACK</b>.<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6455.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
<ul><li>Нажимаем на кнопку &quot;<font color="DarkSlateGray"><b>Setup</b></font>&quot;. Проверяем драйвер и интерфейс (устройство). У меня на Windows выбран драйвер (<code class="inlinecode">Driver</code>) &quot;<i>portaudio</i>&quot; (он идёт с JACK'ом в комплекте), интерфейс (<code class="inlinecode">Interface</code>) – &quot;<i>ASIO::Focusrite USB ASIO</i>&quot; (у вас будет свой, но <font color="DarkRed"><b>обязательно должно быть выбрано ASIO</b></font>, иначе будут очень большие задержки, т.е. слышать себя вы будете не сразу, а после &quot;небольшой&quot; паузы; соседи будут думать, что у вас проблемы с чувством ритма, хотя дело совсем не в вас). <code class="inlinecode">Sample rate</code> – пусть будет <i>48000</i> Гц (можете выбрать 96000, если руки чешутся), <code class="inlinecode">Frames/Period</code> (кол-во семплов на цикл ввода-вывода аудио) я поставил на <i>32</i> (попробуйте так же, но <font color="DarkRed"><b>если будут проблемы – потрескивания, – увеличьте этот параметр, остальное трогать не надо</b></font>). Настройка кол-ва циклов на буфер (<code class="inlinecode">Periods/Buffer</code>) мне недоступна (там стоит <i>2</i>). Справа снизу на основании этих данных будет указана задержка (<code class="inlinecode">Latency</code>); значение 1.33 миллисекунды меня вполне устраивает :) (задержки до 10 мс незаметны на слух (почти), но больше 20 мс уже создают дискомфорт). Галочка напротив <code class="inlinecode">Realtime</code> у меня стоит (хотя я её отключал – всё работает, но хуже не будет). Остальные настройки нас не интересуют (а если интересуют, копайтесь сами на свой страх и риск или читайте мануалы). Нажимаем &quot;<font color="DarkSlateGray"><b>OK</b></font>&quot; для сохранения настроек. Больше эти манипуляции нам не понадобятся, настройки автоматически подгрузятся при следующем запуске.<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6734.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br /></li>
<li>Нажимаем на &quot;<font color="DarkSlateGray"><b>Start</b></font>&quot;. Говорим в микрофон и... ничего не слышим. Может, нужно громче кричать, дуть, стучать ладонью? Прибавить громкость микрофона (чувствительность аудиовхода)! Не помогает. Наверное, мы не включили колонки! :facepalm: Нет, включили. Прибавим громкость на всю! Тишина... <font color="DarkSlateGray"><b>Jin X</b></font> нас обманул! :angry: Столько денег и времени потрачено впустую! :cry: Расслабьтесь, никакого обмана. Мы пока ещё не соединили устройства друг с другом. Сначала верните громкость на прежнее место (а лучше сделайте ещё тише) и положите микрофон подальше от колонок, иначе после подключения ваш мозг взорвётся от обратной свистящей связи.<br />
<br />
Посмотрите на главное окно JACK'а, там есть кнопка &quot;<font color="DarkSlateGray"><b>Connect</b></font>&quot;. Если нажать на неё, откроется окно соединений; слева и справа вы увидите порты и клиентов (я буду называть их каналами) для ввода-вывода, которые можно соединять между собой. Если не видите, то либо не нажали на &quot;<font color="DarkSlateGray"><b>Start</b></font>&quot;, либо нужно просто раскрыть группу каналов. Группа &quot;<i>system</i>&quot; – это основные входы и выходы звуковой карты. Каждый канал (левый, правый и пр.) отображается отдельно. Если вы соедините (drag'n'drop) <code class="inlinecode">capture_1</code> сразу с <code class="inlinecode">playback_1</code> и с <code class="inlinecode">playback_2</code> (при условии, что микрофон воткнут в первый разъём звуковухи), то услышите себя в колонках. Нет смысла соединять <code class="inlinecode">capture_1</code> с <code class="inlinecode">playback_1</code>, а <code class="inlinecode">capture_2</code> с <code class="inlinecode">playback_2</code>, иначе вы услышите себя только в одной колонке, потому что у вас моно-источник звука (микрофон), и он воткнут в один разъём аудиокарты; соединяйте <code class="inlinecode">capture_1</code> с обоими аудиовыходами. Если вы снова себя не слышите, самое время кричать, дуть, стучать, включать колонки, прибавлять громкости и чувствительности... Ну что ж, побаловались и хватит. Отсоединяем (кнопкой &quot;<font color="DarkSlateGray"><b>Disconnect All</b></font>&quot;).<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6542.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div></li>
</ul><br /></li>
<li><b>Запускаем Carla</b> (JACK должен быть включен – кнопка &quot;<font color="DarkSlateGray"><b>Start</b></font>&quot;).<br />
<br />
<ul><li>В окне соединений JACK'а (кнопка &quot;<font color="DarkSlateGray"><b>Connect</b></font>&quot;) появится группа &quot;<i>Carla</i>&quot;. Не появилась? Тогда жмите на кнопку &quot;<font color="DarkSlateGray"><b>Configure Carla</b></font>&quot; на панели инструментов (или ищите такой пункт в меню &quot;<i>Settings</i>&quot;), затем переходите на вкладку &quot;<i>Engine</i>&quot; и в поле <code class="inlinecode">Audio driver</code> выбирайте &quot;<i>JACK</i>&quot;. В поле <code class="inlinecode">Process mode</code> пусть будет &quot;<i>Patchbay</i>&quot;. Перейдите заодно и на вкладку &quot;<i>Paths</i>&quot; и проверьте – имеется ли в списке путь к папке с вашем VST-плагином (iZotope Nectar или что вы там установили?) или к одной из её родительских папок (не забудьте выбрать &quot;<i>VST</i>&quot; в выпадающем списке над списком путей). Сохраняем настройки. Перезапускаем Carla.<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6458.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br /></li>
<li><font color="DarkSlateGray"><b>Переходим к JACK'у</b></font>, а конкретно к окну соединений (кнопка &quot;<font color="DarkSlateGray"><b>Connect</b></font>&quot; – последний раз повторяю). Соединяем <code class="inlinecode">system/capture_1</code> сразу с 2-мя каналами: <code class="inlinecode">Carla/audio-in1</code> и <code class="inlinecode">Carla/audio-in2</code> (можно перетащить канал <code class="inlinecode">capture_1</code> сразу на группу <code class="inlinecode">Carla</code>). Затем соединяем <code class="inlinecode">Carla/audio-out1</code> с <code class="inlinecode">system/playback_1</code>, а <code class="inlinecode">Carla/audio-out2</code> – с <code class="inlinecode">system/playback_2</code>. См. скриншот.<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6457.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br /></li>
<li><font color="DarkSlateGray"><b>Возвращаемся к Carla.</b></font> Обращаем внимание на центральное поле. Сверху есть 2 вкладки: &quot;<i>Rack</i>&quot; и &quot;<i>Patchbay</i>&quot;. Выбираем &quot;<font color="DarkSlateGray"><b>Rack</b></font>&quot; (в общем-то, она уже и так должна быть активна). Чуть выше жмём кнопку &quot;<font color="DarkSlateGray"><b>Add Plugin</b></font>&quot;. Выбираем нужный плагин, затем &quot;<font color="DarkSlateGray"><b>Add Plugin</b></font>&quot;. Если плагина нет, воспользуйтесь кнопкой &quot;<font color="DarkSlateGray"><b>Refresh</b></font>&quot; и затем &quot;<font color="DarkSlateGray"><b>Scan</b></font>&quot; (галочка напротив &quot;<i>VST</i>&quot; должна быть установлена). После добавления плагина в верхней части рабочего поля должна появиться rack-панель плагина. При желании можно добавлять сколько угодно плагинов.<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6459.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
К настройке плагинов перейдём чуть позже, а пока нажмите на вкладку &quot;<font color="DarkSlateGray"><b>Patchbay</b></font>&quot; и переместитесь (с помощью ползунков, средней кнопки мыши или карты в левом нижнем углу) к панелям с устройствами. Соединяем поканально &quot;<i>Audio Input</i>&quot; с &quot;<i>iZotope Nectar 2</i>&quot; (или какой плагин у вас установлен?), а &quot;<i>iZotope Nectar 2</i>&quot; – с &quot;<i>Audio Output</i>&quot;. Т.к. в JACK на оба входа <code class="inlinecode">Carla/audio-in</code> идёт <code class="inlinecode">system/capture_1</code>, то мы можем использовать и левый (<code class="inlinecode">Left</code>) и правый (<code class="inlinecode">Right</code>) выводы &quot;<i>Audio Input</i>&quot;, но я всё равно использую один левый (ниже расскажу почему; в общем-то, нетрудно догадаться, что присоединить один левый канал можно как в настройках соединений JACK, так и в Patchbay Carla, либо и там, и там – эффект будет один и тот же). Теперь вы снова должны услышать себя в колонках (надеюсь, вы не додумались положить микрофон рядом с динамиком?) :)<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6460.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
Вернёмся ко вкладке &quot;<font color="DarkSlateGray"><b>Rack</b></font>&quot; и настроим плагин. Для этого можно либо крутить ручки rack-панели плагина, либо нажать на шестерёнку, чтобы открыть его графический интерфейс. Что касается Nectar, то вариант с шестерёнкой, уверен, вам понравится больше. Здесь вы сможете выбрать уже готовый preset, либо настроить параметры самостоятельно (лично мне удобнее это делать в режиме &quot;<i>Advanced</i>&quot;, переключиться на который можно кнопкой &quot;<font color="DarkSlateGray"><b>Overview</b></font>&quot;, расположенной внизу слева). Для регулировки общего (мастер) соотношения &quot;<i>Dry/Wet</i>&quot; (необработанного и обработанного звука), а также громкости (&quot;<i>Volume</i>&quot;) воспользуйтесь соответствующими регулировками в правой части rack-панели плагина (картинка выше).<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6461.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div></li>
</ul><br /></li>
<li>Если вы не хотите испытывать радость настройки всей этой системы каждый раз, рекомендую сохранить конфигурацию с помощью кнопки &quot;<font color="DarkSlateGray"><b>Save</b></font>&quot; на панели управления Carla. В следующий раз вам нужно будет лишь:<ul><li>запустить <b>JACK</b> и нажать на &quot;<font color="DarkSlateGray"><b>Start</b></font>&quot;;</li>
<li>запустить <b>Carla</b>, нажать &quot;<font color="DarkSlateGray"><b>Open</b></font>&quot;, выбрать сохранённый файл и шлёпнуть &quot;<font color="DarkSlateGray"><b>Открыть</b></font>&quot;.</li>
<li>включить плеер (&quot;AIMP&quot;, &quot;KaraFun Player&quot; или чудесный &quot;проигрыватель Windows Media&quot; :D) и петь в своё удовольствие!</li>
</ul><br />
Всё! Файл с расширением CARXP содержит настройки соединений JACK'а, настройки Carla: соединений Patchbay, все панели Rack (список добавленных плагинов) и настройки VST-плагинов.<br />
Разве это не здорово?! :bravo:</li>
</ol><br />
<font size="4"><b>А как же нюансы?</b></font><br />
<br />
Нюансы есть, куда же без них? Расскажу о некоторых:<ul><li>Нюанс номер раз. Если вы будете использовать несколько VST-плагинов, то соединять их можно как последовательно (т.е. <i>Audio Input &#8594; Plugin1 &#8594; Plugin2 &#8594; Audio Output</i>), так и параллельно (<i>Audio Input &#8594; Plugin1 &#8594; Audio Output</i>; <i>Audio Input &#8594; Plugin2 &#8594; Audio Output</i>). Разница в том, что при последовательном соединении отключение одного (любого) из плагинов (кнопочкой вкл/выкл на rack-панели) приведёт к обрыву всей цепи и отключению звука (голоса) с микрофона. При параллельном соединении такое будет только в том случае, если вы отключите ВСЕ плагины. Можно, конечно, соединить ещё и <i>Audio Input &#8594; Audio Output</i> напрямую, но тогда будет подмешиваться необработанный голос, громкость которого даже не получится отрегулировать отдельно. Кроме того, при последовательном соединении каждый следующий плагин будет получать не &quot;сырой&quot; голос, а обработанный предыдущим. При параллельном соединении каждый плагин будет обрабатывать &quot;сырой&quot; голос, а затем выводить его на микшер, при этом (АХТУНГ!) громкость будет выше, чем при последовательном соединении, т.к. звук будет суммироваться с выводов каждого плагина (при отключении отдельных плагинов громкость, соответственно, будет снижаться). Лично мне последовательное соединение кажется более логичным. А для отключения можно использовать функцию &quot;<font color="DarkSlateGray"><b>Bypass</b></font>&quot;, которая вызывается через меню по нажатию правой кнопкой мыши на rack-панели плагина (при этом ручка &quot;<i>Dry/Wet</i>&quot; будет выкручена максимально влево, и плагин будет просто пропускать звук дальше, не искажая его).<br />
<br /></li>
<li>Нюанс номер два. По идее, можно обойтись вообще без JACK'а (WHAT??? &gt;:o). Для этого в настройках Carla (&quot;<i>Configure Carla</i>&quot; &#8594; &quot;<i>Engine</i>&quot; &#8594; &quot;<i>Audio driver</i>&quot;) нужно выбрать &quot;<i>ASIO</i>&quot;. Но! Лично у меня в этом случае (как ни парадоксально) возникают артефакты (в частности, если петь/говорить близко к микрофону, внезапно возникает шум как при сильном перегрузе). Тем не менее, именно на такой всякий случай (если вдруг по какой-то причине мне понадобится использовать именно ASIO-драйвер в Carla) я и соединил только левый &quot;<i>Audio Input</i>&quot; с VST-плагином в Patchbay).<br />
<br /></li>
<li>Нюанс номер три (от Капитана Очевидности, очень просил передать). Иногда у Carla бывают <s>особые дни</s> глюки (например, на плагин не поступает звук, хотя всё настроено правильно). Просто перезапустите её. Одну либо вместе с JACK'ом. И <s>ваши волосы будут мягкими и шелковистыми</s> всё должно встать на свои места.</li>
</ul><br />
<font size="4"><b>Дополнение <font color="Gray">(добавлено 21.01.2019)</font></b></font><br />
<ul><li>Если вы хотите подключить 2 микрофона (да ещё и петь в оба), делайте так:<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6733.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
(оба <code class="inlinecode">system/capture_1</code> и <code class="inlinecode">system/capture_2</code> соединяются с обоими <code class="inlinecode">Carla/audio-in1</code> и <code class="inlinecode">Carla/audio-in2</code>). В Carla ничего менять не надо (т.к. оба канала – левый и правый – содержат одно и то же).<br />
p.s. На самом деле, вариантов соединения тут много, так что просто сделайте так и не парьтесь. Помните только, что при смене кол-ва микрофонов (вернее, при загрузке нового файла с параметрами Carla) программу JACK лучше перезапустить (иначе старые соединения тоже останутся).<br />
<br /></li>
<li>Просто напоминание: если будут потрескивания (или сильный треск), увеличьте значение параметра <code class="inlinecode">Frames/Period</code> в настройках JACK и перезапустите его.</li>
</ul><br />
<font size="4"><b>Теперь точно спою!</b></font><br />
<br />
Как я уже говорил, это далеко не единственный способ организовать караоке дома, но на мой взгляд, способ довольно удобный. Настроив раз, можно быстро запустить и пользоваться во благо процветания отечественной (и не только) музыкальной культуры! :rose:<br />
Радостного вам пения, мой вокальный друг! И побольше подпевающих (а не стучащих по батареям) фанатов за стенами ;)</div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5499.html</guid>
		</item>
		<item>
			<title><![CDATA[Простое, но недокументирова&shy;­нное определение производителя процессора (Intel / AMD)]]></title>
			<link>https://www.cyberforum.ru/blogs/521524/5488.html</link>
			<pubDate>Sun, 14 Oct 2018 17:58:02 GMT</pubDate>
			<description>*Простое, но недокументированное определение производителя процессора (Intel / AMD)* 
...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Простое, но недокументированное определение производителя процессора (Intel / AMD)</b></font></font><br />
<br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6366.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
Обычно для определения производителя процессора используется инструкция <code class="inlinecode">cpuid</code> (функция <b>eax=0</b>):<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="334177402"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="334177402" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1">&nbsp; <span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp; <span class="kw1">cpuid</span> &nbsp;<span class="co1">; get vendor id string in ebx:edx:ecx</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">6C65746Eh</span> &nbsp;<span class="co1">; 'ntel' (full string is 'GenuineIntel')</span>
&nbsp; <span class="kw1">je</span> <span class="sy1">.</span>Intel
&nbsp; <span class="kw1">cmp</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">444D4163h</span> &nbsp;<span class="co1">; 'cAMD' (full string is 'AuthenticAMD')</span>
&nbsp; <span class="kw1">je</span> <span class="sy1">.</span>AMD
<span class="sy1">.</span>another<span class="sy1">:</span></pre></td></tr></table></div></td></tr></tbody></table></div>(я записал цифрами, т.к. компиляторы по-разному трактуют строки: в <b>fasm</b> и <b>NASM</b> можно записать <code class="inlinecode">'ntel'</code> для Intel, а вот в <b>MASM</b> придётся набирать задом наперёд <code class="inlinecode">'letn'</code>).<br />
<br />
Но есть один недокументированный способ, который описан в приложенных файлах к книге Криса Касперски &quot;Техника отладки программ без исходных текстов&quot; (немного в другом виде и коде, нежели у меня, но суть та же).<br />
<br />
Смысл в том, что несмотря на то, что в мануалах <b>Intel</b> и <b>AMD</b> написано, что инструкция <code class="inlinecode">div</code> (и <code class="inlinecode">idiv</code>) возвращает флаг <b>ZF</b> неопределённым, тем не менее, <b>Intel</b> его не меняет, а <b>AMD</b> всегда выставляет в 0 (вне зависимости от результата, тестовые программы можно посмотреть <a href="https://www.cyberforum.ru/asm-beginners/thread2263371.html">здесь</a>).<br />
<br />
Посему при необходимости (для обфускации или при сильно ограниченных ресурсах) можно сократить код до следующих строк:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="897692617"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="897692617" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">&nbsp; <span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; ZF = 1</span>
&nbsp; <span class="kw1">div</span> <span class="kw4">esp</span> &nbsp;<span class="co1">; esp is always &gt; 0</span>
&nbsp; <span class="kw1">jz</span> <span class="sy1">.</span>Intel &nbsp;<span class="co1">; on any div/idiv operation ZF flag will not be changed on Intel but will be cleared on AMD</span>
<span class="sy1">.</span>AMD<span class="sy1">:</span></pre></td></tr></table></div></td></tr></tbody></table></div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=7403&amp;d=1695205155">CPUVendorTest.zip</a> (2.3 Кб, 282 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5488.html</guid>
		</item>
		<item>
			<title>За что я люблю Assembler?</title>
			<link>https://www.cyberforum.ru/blogs/521524/5362.html</link>
			<pubDate>Fri, 27 Jul 2018 14:58:32 GMT</pubDate>
			<description>*За что я люблю Assembler?* 
 
*Оговорочки* 
 
Хочу сразу оговориться, что правильно говорить не...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>За что я люблю Assembler?</b></font></font></div><br />
<font size="4"><b>Оговорочки</b></font><br />
<br />
Хочу сразу оговориться, что правильно говорить не &quot;<b><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Ассемблер" target="_blank" title="https://ru.wikipedia.org/wiki/Ассемблер">ассемблер</a></b>&quot; (assembler), а &quot;<b><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Язык_ассемблера" target="_blank" title="https://ru.wikipedia.org/wiki/Язык_ассемблера">язык ассемблера</a></b>&quot; (assembly language), потому как ассемблер – это транслятор кода на языке ассемблера (т.е. по сути, программа <b><a rel="nofollow noopener noreferrer" href="http://masm32.com/" target="_blank" title="http://masm32.com/">MASM</a></b>, <b><a rel="nofollow noopener noreferrer" href="http://old-dos.ru/files/file_683.html" target="_blank" title="http://old-dos.ru/files/file_683.html">TASM</a></b>, <b><a rel="nofollow noopener noreferrer" href="https://flatassembler.net/" target="_blank" title="https://flatassembler.net/">fasm</a></b>, <b><a rel="nofollow noopener noreferrer" href="https://www.nasm.us" target="_blank" title="https://www.nasm.us">NASM</a></b>, <b><a rel="nofollow noopener noreferrer" href="http://www.terraspace.co.uk/uasm.html" target="_blank" title="http://www.terraspace.co.uk/uasm.html">UASM</a></b>, <b><a rel="nofollow noopener noreferrer" href="http://www.gnu.org/software/binutils/" target="_blank" title="http://www.gnu.org/software/binutils/">GAS</a></b> и пр., которая компилирует исходный текст на языке ассемблера в объектный или исполняемый файл). Тем не менее, из соображения краткости многие, говоря &quot;<font color="DarkSlateGray"><b>ассемблер</b></font>&quot; (<font color="DarkSlateGray"><b>асм, asm</b></font>), подразумевают именно &quot;<font color="DarkSlateGray"><b>язык ассемблера</b></font>&quot;. Синтаксис различных диалектов (к примеру, <font color="DarkSlateGray"><b>MASM, fasm, GAS</b></font>), включая директивы, стандартные макросы и пр. структурные элементы, могут отличаться довольно существенно. Мнемоники (имена) инструкций (команд) одного и того же процессора одинаковы почти во всех диалектах (заметным исключением среди популярных ассемблеров является разве что <font color="DarkSlateGray"><b>GAS</b></font>, где к именам инструкций могут добавляться суффиксы, обозначающие размер обрабатываемых ими данных, что бывает довольно удобно, но там есть и другие нюансы, сбивающие с толку программиста, привыкшего к классическому ассемблеру, к примеру, иной порядок указания операндов, хотя это лечится специальной директивной).<br />
<br />
Поскольку ассемблер – самый низкоуровневый язык программирования, практически невозможно написать код, который корректно компилировался бы для разных архитектур процессоров (например, <font color="DarkSlateGray"><b>x86</b></font> и <font color="DarkSlateGray"><b>ARM</b></font>), для разных режимов одного и того же процессора (16-битный код <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Реальный_режим" target="_blank" title="https://ru.wikipedia.org/wiki/Реальный_режим">реального режима</a>, 32-битный код <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Защищённый_режим" target="_blank" title="https://ru.wikipedia.org/wiki/Защищённый_режим">защищённого режима</a>, 64-битный код <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/X86-64" target="_blank" title="https://ru.wikipedia.org/wiki/X86-64">long mode</a>; а ещё можно захотеть генерировать код как с использованием различных технологий вроде <b><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/SSE" target="_blank" title="https://ru.wikipedia.org/wiki/SSE">SSE</a></b>, <b><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/AVX" target="_blank" title="https://ru.wikipedia.org/wiki/AVX">AVX</a></b> или <b><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Расширение_системы_команд_AES" target="_blank" title="https://ru.wikipedia.org/wiki/Расширение_системы_команд_AES">AES-NI</a></b>, так и без них) и для разных операционных систем (<font color="DarkSlateGray"><b>Windows, Linux, MS-DOS</b></font>). Хотя иногда можно встретить &quot;универсальный&quot; код (например, отдельные библиотеки), скажем, <i>для 32- и 64-битного кода ОС Windows</i> (или даже <i>для Windows и Linux</i>), но это бывает нечасто :pardon:. Ведь каждая строка кода на ассемблере (не считая управляющих директив, макросов и тому подобного) – это отдельная инструкция процессора, для которого пишется этот код, и сделать кроссплатформенный вариант можно только с помощью макросов и условных директив препроцессора (получая в итоге порой весьма нетривиальные конструкции, довольно сложные для понимания).<br />
<br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6314.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
<font size="4"><b>Откуда растут ноги?</b></font><br />
<br />
Ассемблером я увлёкся лет в 12-13, и он меня изрядно &quot;затянул&quot;. Почему?<ul><li>Во-первых, экономия памяти (дисковой и оперативной) и погоня за скоростью в те DOS-овские времена далёких 90-х годов были довольно актуальными темами.<br />
<br /></li>
<li>Во-вторых (и это более существенно), на ассемблере можно было делать много того, что сделать на языках высокого уровня (<font color="DarkSlateGray"><b>ЯВУ</b></font>, на путайте с Java) затруднительно или не так эффективно. К примеру, мне очень нравилось писать <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Резидентная_программа" target="_blank" title="https://ru.wikipedia.org/wiki/Резидентная_программа">резидентные программы</a> в моём любимом формате <font color="DarkSlateGray"><b>DOS COM</b></font>, которые я приносил другу и устраивал ему всякие &quot;сюрпризы&quot; (программы могли инсталлироваться в загрузчик <b><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Главная_загрузочная_запись" target="_blank" title="https://ru.wikipedia.org/wiki/Главная_загрузочная_запись">MBR</a></b> или прописываться в файл <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/AUTOEXEC.BAT" target="_blank" title="https://ru.wikipedia.org/wiki/AUTOEXEC.BAT">autoexec.bat</a> и запускаться при следующей загрузке системы). Про вирусы я больше читал, чем писал (и дальше моего компьютера они не уходили). Немного увлекался <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Демосцена" target="_blank" title="https://ru.wikipedia.org/wiki/Демосцена">демосценой</a> (правда, в демопати так и не участвовал, больше смотрел и пробовал реализовать различные элементы).</li>
</ul>Но с тех пор прошло уже больше 2-х десятков лет, и сейчас экономия памяти (особенно дисковой) уже не так актуальна, да и скорости современных процессоров для выполнения повседневных задач вполне хватает (популярность <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Сверхвысокоуровневый_язык_программирования" target="_blank" title="https://ru.wikipedia.org/wiki/Сверхвысокоуровневый_язык_программирования">языков сверхвысокого уровня</a> подтверждает это, хотя <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Закон_Вирта" target="_blank" title="https://ru.wikipedia.org/wiki/Закон_Вирта">закон Вирта</a> никто не отменял :D). А современные компиляторы зачастую могут оптимизировать код по скорости лучше человека, не так ли? Что же может привлекать программиста в ассемблере, ведь исходники на нём гораздо более объёмные, а на разработку требуется больше времени и внимания (чтобы не наделать ошибок)?<br />
<br />
<font size="4"><b>Перейдём к сути!</b></font><br />
<br />
Приведу свои доводы относительно того, чем так хорош ассемблер.<ol style="list-style-type: decimal"><li>Ассемблер даёт полный контроль над кодом и обладает большей гибкостью, чем любой другой язык программирования (даже <font color="DarkSlateGray"><b>C/C++</b></font>). И речь тут отнюдь не об &quot;injection&quot; (внедрении кода в адресное пространство другого процесса) и не о вирусах, троянах и пр. нечисти (это всё, кстати, можно написать и на многих ЯВУ). На асме мы можем конструировать нашу программу, размещая блоки кода и данных как нам вздумается. Каждый генерируемый байт будет таким, каким мы хотим его видеть. Без лишнего runtime-кода стандартных библиотек. Что же касается демосцены, то написать, скажем, <i>intro</i>, уместив исполняемый файл в 256 байт [<a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=53816" target="_blank" title="http://www.pouet.net/prod.php?which=53816">1</a>, <a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=67698" target="_blank" title="http://www.pouet.net/prod.php?which=67698">2</a>, <a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=60879" target="_blank" title="http://www.pouet.net/prod.php?which=60879">3</a>, <a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=66380" target="_blank" title="http://www.pouet.net/prod.php?which=66380">4</a>] (а то и <a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=53871" target="_blank" title="http://www.pouet.net/prod.php?which=53871">128</a>, <a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=8697" target="_blank" title="http://www.pouet.net/prod.php?which=8697">64</a>, <a rel="nofollow noopener noreferrer" href="http://www.pouet.net/prod.php?which=66857" target="_blank" title="http://www.pouet.net/prod.php?which=66857">32</a> или даже ещё меньше) на чём-то отличном от ассемблера вы вряд ли сможете.<br />
<br /></li>
<li>На ассемблере можно написать ВСЁ, он всемогущ! :D Попробуйте создать MBR-<a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Загрузчик_операционной_системы" target="_blank" title="https://ru.wikipedia.org/wiki/Загрузчик_операционной_системы">загрузчик</a> на <font color="DarkSlateGray"><b>C</b></font> или на чём-то ещё – вряд ли это у вас получится. Работа с железом на низком уровне, программирование чипсетов – это всё ассемблер. Различные антиотладочные приёмы тоже гораздо веселее писать на ассемблере (либо с использованием ассемблера). Или, скажем, нечто <a rel="nofollow noopener noreferrer" href="http://blog.rewolf.pl/blog/?p=102" target="_blank" title="http://blog.rewolf.pl/blog/?p=102">вроде этого</a>. Для <font color="DarkSlateGray"><b>C/C++</b></font> имеются <a rel="nofollow noopener noreferrer" href="https://software.intel.com/sites/landingpage/IntrinsicsGuide/" target="_blank" title="https://software.intel.com/sites/landingpage/IntrinsicsGuide/">интринсики</a> – встроенные функции для генерации отдельных инструкций процессора (есть ли что-то подобное для других языков программирования – не знаю). Но их частое использование загромождает код (не проще ли тогда писать на чистом ассемблере?) А их отсутствие не позволяет нам контролировать генерируемый компилятором код (при этом, к слову говоря, <font color="DarkSlateGray"><b>GNU C/C++, Intel C/C++</b></font> и <font color="DarkSlateGray"><b>Clang</b></font> будут генерировать разный код; и даже один и тот же компилятор с разными настройками типа <font color="DarkSlateGray"><b>-O</b></font> и др. выдаст различный результат).<br />
<br /></li>
<li>Получаемый код даже самого умного и навороченного компилятора, как правило, можно оптимизировать (как по скорости, так и по размеру). А ещё можно <a href="https://www.cyberforum.ru/blogs/521524/blog5122.html">изощриться</a> и использовать неочевидные комбинации, сделав код короче и быстрее. Этим можно, конечно, заняться и на других языках, но на ассемблере больше простора для творчества. <font color="#CC0000"><b>Это особый кайф, азарт, челлендж</b></font> в некотором роде! :) К тому же, разве не прикольно написать программу, выполняющую полезные функции, весом менее 10 Кб? Для сравнения: <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Visual_Component_Library" target="_blank" title="https://ru.wikipedia.org/wiki/Visual_Component_Library">VCL</a>-программа на <font color="DarkSlateGray"><b>Delphi 10.2 Tokyo</b></font>, создающая пустое окно без какого-либо полезного функционала, весит в release-версии целых 2 Мб (а в debug-версии... кхм, 11 Мб). На <font color="DarkSlateGray"><b>C++Builder 10.2 Tokyo</b></font> release-версия такой же программы, не требующая внешних библиотек, получится размером &#8776; 2.7 Мб. Аналогичная программа на <font color="DarkSlateGray"><b>fasm</b></font> будет занимать всего пару килобайт.<br />
<br /></li>
<li>Обычно одна строка кода на ЯВУ разворачивается в несколько (или даже десяток) инструкций процессора. А знаете ли вы о том, что некоторые инструкции процессора Intel требуют несколько строк для реализации на ЯВУ (на том же <font color="DarkSlateGray"><b>C/C++</b></font>, если не использовать интринсики)? Если не знаете, просто поверьте на слово, а я напишу об этом в следующей статье :victory:</li>
</ol>Справедливости ради скажу, что писать всегда на ассемблере – занятие не очень разумное с точки зрения времени, усилий, вероятности допустить ошибку и кроссплатформенности. Не так часто нам требуется полный контроль кода и столь уж жёсткая оптимизация, когда экономия пары тактов процессора имеет критически решающее значение. Но иногда использование ассемблера действительно оправдано (<a rel="nofollow noopener noreferrer" href="https://www.agner.org/optimize/#asmlib" target="_blank" title="https://www.agner.org/optimize/#asmlib">пример</a>). Часто ассемблер хорошо использовать в виде вставок в код на ЯВУ (посмотрите RTL-модули <font color="DarkSlateGray"><b>Delphi</b></font>, там этого добра в изобилии). Да и использование интринсиков, как правило, не имеет смысла (и опасно) без знания инструкций ассемблера.<br />
<br />
<font size="4"><b>Быть или не быть?</b></font><br />
<br />
Так, нужно ли изучать ассемблер современному программисту? Если вы уже не новичок, и у вас серьёзные амбиции, то <a href="https://www.cyberforum.ru/low-level/thread2208389.html#a_books">изучение ассемблера</a>, внутреннего устройства операционных систем и функционирования железа (особенно процессоров, памяти), а также использование различных <a href="https://www.cyberforum.ru/low-level/thread2208389.html#a_instruments">инструментов</a> для дизассемблирования, отладки и анализа кода полезно тем, кто хочет писать эффективные программы. Иначе будет сложно в полной мере понять, <a rel="nofollow noopener noreferrer" href="https://habr.com/post/339962/" target="_blank" title="https://habr.com/post/339962/">что происходит &quot;под капотом&quot;</a> любимого компилятора (хотя бы в общих чертах) и какой приём стоит предпочесть. Необязательно погружаться слишком глубоко в эту тему, если вы пишете на <font color="DarkSlateGray"><b>Python</b></font> или <font color="DarkSlateGray"><b>JavaScript</b></font>. А вот если ваш язык – <font color="DarkSlateGray"><b>C++</b></font>, лучше изучить ассемблер более глубоко. Вместе с тем, необходимо помнить не только о <i>тактике</i>, но и о <i>стратегии</i>, поэтому не менее важно изучать и алгоритмы, правильный подбор которых зачастую более важен для создания эффективных программ, нежели низкоуровневая оптимизация.<br />
<br />
Если вы решили изучить ассемблер и окунуться в низкоуровневое программирование, вам будет полезна моя <a href="https://www.cyberforum.ru/blogs/521524/blog5173.html">подборка литературы</a> и <a href="https://www.cyberforum.ru/blogs/521524/blog5176.html">инструментов</a>.<br />
<br />
To be continued... ;)</div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5362.html</guid>
		</item>
		<item>
			<title>Системные вызовы в Linux</title>
			<link>https://www.cyberforum.ru/blogs/521524/5351.html</link>
			<pubDate>Wed, 18 Jul 2018 09:14:04 GMT</pubDate>
			<description>*Системные вызовы в Linux* 
 
В Linux, в отличие от Windows, прямые системные вызовы используются...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Системные вызовы в Linux</b></font></font></div><br />
В Linux, в отличие от Windows, прямые системные вызовы используются довольно часто. По меньшей мере, консольные приложения, написанные на ассемблере, порой содержат лишь системные вызовы, без обращений к функциям библиотек. Причём, этот механизм (как и номера функций(!)) различается для кода 32- и 64-битной разрядности (кстати, в Linux существует ещё и <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/X32_ABI" target="_blank" title="https://ru.wikipedia.org/wiki/X32_ABI">x32 ABI</a> – это, попросту говоря, 64-битный код с 32-битными указателями).<br />
<br />
Давайте разберёмся...<br />
<br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6276.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
<font size="3"><b>32-битный код (x86 <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Двоичный_интерфейс_приложений" target="_blank" title="https://ru.wikipedia.org/wiki/Двоичный_интерфейс_приложений">ABI</a>, архитектура i386)</b></font><br />
<br />
Для приложений x86 имеется 2 варианта вызова системных функций:<ul><li>Через прерывание 80h (<code class="inlinecode">int 0x80</code>).</li>
<li>Через инструкцию <code class="inlinecode">sysenter</code>.</li>
</ul><b>Системный вызов через прерывание 80h</b><br />
<br />
Наиболее распространённый (хотя и более медленный), поскольку осуществляется проще и поддерживается любым процессором 386+.<ol style="list-style-type: decimal"><li>В регистр <b>EAX</b> загружается номер функции.</li>
<li>Параметры (зависящие от функции) загружаются в регистры <b>EBX</b> (первый параметр), <b>ECX</b> (второй), <b>EDX</b> (третий), <b>ESI</b> (четвёртый), <b>EDI</b> (пятый), <b>EBP</b> (шестой, хотя насколько я знаю, больше 5 параметров не используется).</li>
<li>Осуществляется вызов прерывания: <code class="inlinecode">int 0x80</code>.</li>
</ol><div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="733861970"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="733861970" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; <span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span>function_number
&nbsp; <span class="kw1">mov</span> <span class="kw4">ebx</span><span class="sy1">,</span>param_1 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span>param_2 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">edx</span><span class="sy1">,</span>param_3 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">esi</span><span class="sy1">,</span>param_4 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">edi</span><span class="sy1">,</span>param_5 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ebp</span><span class="sy1">,</span>param_6 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">int</span> <span class="nu0">0x80</span> &nbsp;<span class="co1">; вызов!</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Системный вызов через инструкцию <font size="3"><font face="Courier New">sysenter</font></font></b><br />
<br />
Осуществляется быстрее, но немного сложнее и поддерживается только процессорами Pentium II и старше (а что, у кого-то более старый? :D)<ol style="list-style-type: decimal"><li>В регистр <b>EAX</b> загружается номер функции.</li>
<li>Параметры (зависящие от функции) загружаются в регистры <b>EBX</b> (первый параметр), <b>ECX</b> (второй), <b>EDX</b> (третий), <b>ESI</b> (четвёртый), <b>EDI</b> (пятый).</li>
<li>В стек заносится <i>адрес возврата</i> и регистры <b>ECX</b>, <b>EDX</b>, <b>EBP</b> (именно в таком порядке).</li>
<li>В регистр <b>EBP</b> загружается значение <b>ESP</b>.</li>
<li>Выполняется инструкция <code class="inlinecode">sysenter</code>.</li>
</ol>
			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Зачем нужны такие сложности?</div>
				   <div class="spoiler-body">
					   Дело в том, что инструкция <code class="inlinecode">sysenter</code>, осуществляющая вход (переключение) в режим ядра, заносит в регистры <b>EIP</b> и <b>ESP</b> определённые значения (предварительно загруженные системой в специальные <b>MSR</b>-регистры), не сохраняя нигде адреса возврата и старого значения <b>ESP</b>. Поэтому вызывающему коду необходимо делать это самостоятельно (чтобы продолжить своё выполнение), и вполне логично сохранять их именно в стеке. Инструкция выхода из режима ядра (переключения в режим пользователя) <code class="inlinecode">sysexit</code> загружает в <b>ESP</b> значение регистра <b>ECX</b>, а в <b>EIP</b> – значение регистра <b>EDX</b>, поэтому эти регистры, во избежание их порчи, также необходимо сохранять (в стеке). Ну и для того, чтобы передать ядру указатель стека пользовательской программы (оно же изменяется инструкцией <code class="inlinecode">sysenter</code>, см. выше), значение <b>ESP</b> записывается в <b>EBP</b>, предварительно сохранив последний.<br />
Однако, если системные функции заканчивались бы просто инструкцией <code class="inlinecode">sysexit</code>, было бы логичнее сохранять адрес возврата последним, чтобы ядро выполняло:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="748247179"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="748247179" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ebp</span>
<span class="kw1">pop</span> <span class="kw4">ebp</span>
<span class="kw1">pop</span> <span class="kw4">edx</span>
<span class="kw1">sysexit</span> &nbsp;<span class="co1">; возврат в нашу программу</span></pre></td></tr></table></div></td></tr></tbody></table></div>А нашей программе нужно было бы совершать восстановление сохранённых регистров из стека, выполнив следующие инструкции:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="657451955"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="657451955" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="kw1">pop</span> <span class="kw4">edx</span>
<span class="kw1">pop</span> <span class="kw4">ecx</span></pre></td></tr></table></div></td></tr></tbody></table></div>Но тут создатели системы решили слегка упростить жизнь программистам и осуществлять выход из режима ядра (<code class="inlinecode">sysexit</code>) не сразу обратно в пользовательскую программу, а в промежуточную процедуру, которая делает следующее:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="849615371"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="849615371" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw1">pop</span> <span class="kw4">ebp</span>
<span class="kw1">pop</span> <span class="kw4">edx</span>
<span class="kw1">pop</span> <span class="kw4">ecx</span>
<span class="kw1">ret</span> &nbsp;<span class="co1">; возврат в нашу программу</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="862856743"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="862856743" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">&nbsp; <span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span>function_number
&nbsp; <span class="kw1">mov</span> <span class="kw4">ebx</span><span class="sy1">,</span>param_1 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span>param_2 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">edx</span><span class="sy1">,</span>param_3 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">esi</span><span class="sy1">,</span>param_4 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">edi</span><span class="sy1">,</span>param_5 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">push</span> <span class="sy1">.</span><span class="kw1">ret</span> &nbsp;<span class="co1">; адрес возврата</span>
&nbsp; <span class="kw1">push</span> <span class="kw4">ecx</span> &nbsp; <span class="co1">; сохранение этих регистров требуется системой</span>
&nbsp; <span class="kw1">push</span> <span class="kw4">edx</span>
&nbsp; <span class="kw1">push</span> <span class="kw4">ebp</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ebp</span><span class="sy1">,</span><span class="kw4">esp</span>
&nbsp; <span class="kw1">sysenter</span> &nbsp;<span class="co1">; вызов!</span>
<span class="sy1">.</span><span class="kw1">ret</span><span class="sy1">:</span></pre></td></tr></table></div></td></tr></tbody></table></div><font size="3"><b>64-битный код (x64 и x32 ABI, архитектура x86-64)</b></font><br />
<br />
Здесь всё несколько проще (за исключением странной очерёдности использования регистров для передачи параметров).<ol style="list-style-type: decimal"><li>В регистр <b>RAX</b> загружается номер функции.</li>
<li>Параметры (зависящие от функции) загружаются в регистры <b>RDI</b> (первый параметр), <b>RSI</b> (второй), <b>RDX</b> (третий), <b>R10</b> (четвёртый), <b>R8</b> (пятый), <b>R9</b> (шестой).</li>
<li>Выполняется инструкция <code class="inlinecode">syscall</code> <i>(не путайте с <code class="inlinecode">sysenter</code> – это две разные инструкции!)</i></li>
</ol><i>Внимание! Значения регистров <b>RCX</b> и <b>R11</b> при выполнении системного вызова уничтожаются!</i><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Почему это происходит?</div>
				   <div class="spoiler-body">
					   Дело в том, что инструкция входа в режим ядра <code class="inlinecode">syscall</code> сохраняет в регистре <b>RCX</b> значение <b>RIP</b>, а в <b>R11</b> – значение регистра флагов (указатель стека <b>RSP</b> при этом не меняется) и переходит к выполнению функции ядра (адрес которой хранится в специальном <b>MSR</b>-регистре). Инструкция <code class="inlinecode">sysret</code> же выполняет всё наоборот: восстанавливает <b>RIP</b> из регистра <b>RCX</b> и регистр флагов (почти весь) из регистра <b>R11</b>.<br />
Поскольку в x64 кол-во регистров довольно много, а <b>RCX</b> и <b>R11</b> не участвуют для передачи параметров, создатели системы решили не заморачиваться с сохранением этих регистров (возможно, заодно и для ускорения системного вызова и возврата).<br />
Почему используются именно эти 2 регистра? :facepalm: Спросите об этом у специалистов Intel (и заодно про <code class="inlinecode">sysexit</code>) – потом расскажете :D<br />
<br />
Что же касается странной очерёдности использования регистров для передачи параметров, то здесь ситуация такова. В соответствии с соглашением о вызовах в 64-битной Linux параметры функций заносятся в регистры в следующем порядке: <b>RDI</b>, <b>RSI</b>, <b>RDX</b>, <b>RCX</b>, <b>R8</b>, <b>R9</b>. Однако поскольку регистр <b>ECX</b> имеет специальное назначение при системном вызове (сохраняет <b>RIP</b>), его заменили на другой свободный регистр – <b>R10</b>.
				   </div>
			   </div><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="903642389"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="903642389" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; <span class="kw1">mov</span> <span class="kw4">rax</span><span class="sy1">,</span>function_number
&nbsp; <span class="kw1">mov</span> <span class="kw4">rdi</span><span class="sy1">,</span>param_1 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">rsi</span><span class="sy1">,</span>param_2 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">rdx</span><span class="sy1">,</span>param_3 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">r10</span><span class="sy1">,</span>param_4 &nbsp;<span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">r8</span><span class="sy1">,</span>param_5 &nbsp; <span class="co1">; если есть</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">r9</span><span class="sy1">,</span>param_6 &nbsp; <span class="co1">; если есть</span>
&nbsp; <span class="kw1">syscall</span> &nbsp;<span class="co1">; вызов! (регистры RCX и R11 будут уничтожены)</span></pre></td></tr></table></div></td></tr></tbody></table></div>Схема работы <b>x64</b> и <b>x32 ABI</b> (напомню, что x32 – это 64-битный код с 32-битными указателями) одинаковая, разве что для <b>x32</b> есть несколько дополнительных функций.<br />
<br />
<br />
<font size="3"><b>Возврат результата системных вызовов</b></font><br />
<br />
Системные вызовы, как и [почти] все библиотечные функции возвращают результат в регистре <b>EAX</b> (<b>RAX</b>).<br />
Все остальные регистры сохраняются (разумеется, кроме <b>RCX</b> и <b>R11</b> в x64 и x32).<br />
<br />
<br />
<font size="3"><b>Реализация механизма системных вызовов</b></font><br />
<br />
В <b>MASM</b> и <b>fasm</b> имеется директива (макрос) <code class="inlinecode">invoke</code>, <code class="inlinecode">cinvoke</code> для вызова функций WinAPI, а как насчёт Linux? Для Linux чаще всего используют ассемблеры <b>NASM</b> и <b>GAS</b>.<br />
Для <b>NASM</b> есть проект <a rel="nofollow noopener noreferrer" href="https://sourceforge.net/projects/nasmx/" target="_blank" title="https://sourceforge.net/projects/nasmx/">NASMX</a>, включающий в себя 3 include-файла, в которых описан 1 макрос <b>syscall</b>, номера функций для x86 и x64 (про доп.функции x32 забыли) и константы с кодами ошибок и т.п. Для <b>GAS</b>, как я понимаю, можно использовать стандартные Linux'овские include'ы, а про макросы я ничего не знаю (знаете – напишите мне).<br />
<br />
<hr style="height:1px;border:0;color:#909090;background:#909090" /><br />
<font color="DarkRed"><font size="3"><b>Мои макросы системных вызовов для NASM</b></font></font><br />
<br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6278.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Предлагаю вам несколько написанных мной include-файлов для <b>NASM</b> с различными макросами системных вызовов для 32- и 64-битного кода, а также примеры их использования.<br />
<br />
Основные файлы:<ul><li><b>linux_syscall.inc</b> – универсальный include, автоматически определяющий разрядность кода и включающий соответствующие .inc и .mac файлы.</li>
<li><b>linux_syscall_32.inc</b> – include, включающий все необходимые .inc и .mac файлы для 32-битного кода.</li>
<li><b>linux_syscall_64.inc</b> – include, включающий все необходимые .inc и .mac файлы для 64-битного кода.</li>
</ul>Для файла <font color="DarkSlateGray"><b>linux_syscall.inc</b></font> наличие <font color="DarkSlateGray"><b>linux_syscall_32.inc</b></font> и <font color="DarkSlateGray"><b>linux_syscall_64.inc</b></font> не требуется, зато для всех этих 3-х include'ов требуется наличие следующих файлов (которые можно подключать и по-отдельности, без указанных выше файлов):<ul><li><b>linux_sysfunc_32.inc</b> – номера функций системных вызовов для 32-битного кода (x86).</li>
<li><b>linux_syscall_32.mac</b> – макросы системных вызовов для 32-битного кода (x86).</li>
<li><b>linux_sysfunc_64.inc</b> – номера функций системных вызовов для 64-битного кода (x64 и x32).</li>
<li><b>linux_syscall_64.mac</b> – макросы системных вызовов для 64-битного кода (x64 и x32).</li>
<li><b>linux_syscall_fn.mac</b> – именованные макросы для некоторых функций системных вызовов (см. ниже).</li>
<li><b>linux_const.inc</b> – константы с кодами ошибок, хендлами для стандартного (консольного) ввода-вывода и пр.</li>
</ul><br />
<b>Как этим пользоваться?</b><br />
<br />
Всё предельно просто :)<ol style="list-style-type: decimal"><li>Подключаем в заголовке нашего исходника один из основных include-файлов: <b>linux_syscall.inc</b> (для кода любой разрядности) или <b>linux_syscall_32.inc</b>, <b>linux_syscall_64.inc</b> (для 32- и 64-битного кода соответственно):<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="146009462"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="146009462" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw5">%include</span> <span class="st0">'linux_syscall.inc'</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В основном коде используем макросы <b>lsyscall</b>, <b>lsyscallr</b>, <b>$lsyscall</b> и/или <b>$lsyscallr</b>, указывая по порядку номер функции и соответствующие ей параметры через запятую:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="415000930"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="415000930" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">lsyscall sys_read<span class="sy1">,</span> STDIN_FILENO<span class="sy1">,</span> buffer<span class="sy1">,</span> bufsize &nbsp;<span class="co1">; читаем данные из консоли в буфер buffer</span>
lsyscall sys_write<span class="sy1">,</span> STDOUT_FILENO<span class="sy1">,</span> <span class="sy1">,</span> <span class="kw4">eax</span> &nbsp;<span class="co1">; выводим прочитанные данные на консоль</span>
lsyscall sys_exit<span class="sy1">,</span> <span class="nu0">0</span> &nbsp;<span class="co1">; выходим из программы</span>
<span class="co1">; более подробные комментарии, включая причину пропуска одного из параметров в sys_write, см. чуть ниже,</span>
<span class="co1">; в следующем примере</span></pre></td></tr></table></div></td></tr></tbody></table></div>Либо используем именованные макросы (описанные в файле <font color="DarkSlateGray"><b>linux_syscall_fn.mac</b></font>, который включается автоматически при включении <font color="DarkSlateGray"><b>linux_syscall.inc</b></font>, <font color="DarkSlateGray"><b>linux_syscall_32.inc</b></font> или <font color="DarkSlateGray"><b>linux_syscall_64.inc</b></font>) для работы с отдельными функциями системных вызовов Linux. На данный момент там описаны только макросы для работы с консолью и для выхода из программы: <b>lsys_con_read</b> (и <b>lsys_con_read_r</b>), <b>lsys_con_write</b> (и <b>lsys_con_write_r</b>), <b>lsys_err_write</b> (и <b>lsys_err_write_r</b>) и <b>lsys_exit</b>:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="735814695"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="735814695" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1">lsys_con_read buffer<span class="sy1">,</span> bufsize &nbsp;<span class="co1">; читаем до bufsize байт из консоли (по умолчанию с клавиатуры) в buffer,</span>
&nbsp; <span class="co1">; результат (кол-во прочитанных байт) возвращается в EAX (-1 при ошибке)</span>
lsys_con_write <span class="sy1">,</span> <span class="kw4">eax</span> &nbsp;<span class="co1">; выводим EAX байт на консоль (по умолчанию на экран) из буфера buffer</span>
&nbsp; <span class="co1">; здесь запятая в начале – это не отделение имени макроса от параметров, а пропуск первого параметра</span>
&nbsp; <span class="co1">; (buffer), который отсутствует из-за того, что его значение такое же, как и в предыдущей функции,</span>
&nbsp; <span class="co1">; а системные вызовы не меняют никакие регистры, кроме EAX.</span>
&nbsp; <span class="co1">; Как вариант, можно было бы написать так: lsys_con_write ecx, eax ...или... lsys_con_write buffer, eax .</span>
&nbsp; <span class="co1">; Причина пропуска параметра в предыдущем примере (lsyscall sys_write...) та же, там тоже можно было бы</span>
&nbsp; <span class="co1">; использовать регистр ECX или адрес буфера (buffer).</span>
lsys_exit &nbsp;<span class="co1">; выходим из программы (если код завершения не задан, используется 0)</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ol>В чём разница между всеми этими макросами?<ul><li>Макрос <b>lsyscall</b> загружает параметры в регистры в <i>прямом</i> порядке (<font color="DarkSlateGray"><b>EBX</b>, <b>ECX</b>, <b>EDX</b>, <b>ESI</b>, <b>EDI</b>, <b>EBP</b></font> для 32-битного кода или <font color="DarkSlateGray"><b>RDI</b>, <b>RSI</b>, <b>RDX</b>, <b>R10</b>, <b>R8</b>, <b>R9</b></font> для 64-битного).</li>
<li>Макрос <b>lsyscallr</b> загружает параметры в регистры в <i>обратном</i> порядке (<font color="DarkSlateGray"><b>EBP</b>, <b>EDI</b>, <b>ESI</b>, <b>EDX</b>, <b>ECX</b>, <b>EBX</b></font> для 32-битного кода или <font color="DarkSlateGray"><b>R9</b>, <b>R8</b>, <b>R10</b>, <b>RDX</b>, <b>RSI</b>, <b>RDI</b></font> для 64-битного).</li>
<li>Макросы <b>$lsyscall</b> и <b>$lsyscallr</b> работают так же, но перед записью параметров сохраняют в стеке (а после системного вызова восстанавливают) регистры <font color="DarkSlateGray"><b>EBX</b>, <b>ESI</b>, <b>EDI</b>, <b>EBP</b></font> (которые в соответствии с соглашением о вызовах необходимо сохранять при изменении внутри функций), если конечно, эти регистры используются. Эти макросы определены только для 32-битного кода, а также при использовании <font color="DarkSlateGray"><b>linux_syscall.inc</b></font> (для 64-битного кода это только псевдонимы макросов <font color="DarkSlateGray"><b>lsyscall</b></font> и <font color="DarkSlateGray"><b>lsyscallr</b></font>, поскольку в 64-х битах сохраняемыми регистрами являются <font color="DarkSlateGray"><b>RBX</b>, <b>RBP</b>, <b>R12</b>-<b>R15</b></font>, которые не используются в качестве параметров системных вызовов – не путайте соглашения для Windows и Linux).<br />
<font color="DarkRed"><b>Важно:</b></font> используйте последовательности идущих друг за другом макросов <font color="DarkSlateGray"><b>$lsyscall</b></font> и <font color="DarkSlateGray"><b>$lsyscallr</b></font> с осторожностью,  понимая работу этого механизма, поскольку пропуск параметров или использование регистров в качестве параметров может повлечь за собой передачу неверных значений, восстановленных предыдущей функцией.</li>
<li>Макросы <b>lsys_con_read</b> и <b>lsys_con_read_r</b>, <b>lsys_con_write</b> и <b>lsys_con_write_r</b>, а также <b>lsys_err_write</b> и <b>lsys_err_write_r</b> отличаются порядком загрузки параметров в регистры аналогично макросам <font color="DarkSlateGray"><b>lsyscall</b></font> и <font color="DarkSlateGray"><b>lsyscallr</b></font>.</li>
<li>Макросы <b>lsys_err_write</b> и <b>lsys_err_write_r</b> отличаются от <b>lsys_con_write</b> и <b>lsys_con_write_r</b> тем, что осуществляют вывод на устройство вывода <i>ошибки</i>, которым почти всегда является экран. В отличие от <i>обычного</i> устройства вывода, вывод ошибки не перенаправляется в файл с помощью символа &quot;<b>&gt;</b>&quot; в командной строке.</li>
<li>Значение регистра <b>EAX</b>/<b>RAX</b> (номер функции) загружается всегда последним, вне зависимости от наличия суффикса '<b>r</b>' в имени макроса!</li>
</ul><br />
<font color="Navy"><i>Если у вас пока нет желания более глубоко разбираться в моих макросах, либо вы хотите сперва опробовать описанное выше, можете пропустить нижеследующие списки :)</i></font><br />
<br />
Дополнительные макросы 32-битного режима (<b>linux_syscall_32.mac</b>):<ul><li>Макрос <b>lsyscall_use_int80</b> – использовать <code class="inlinecode">int 0x80</code> для системных вызовов во всех нижеследующих макросах [<b>$</b>]<b>lsyscall</b>[<b>r</b>] (действует по умолчанию).</li>
<li>Макрос <b>lsyscall_use_sysenter</b> – использовать <code class="inlinecode">sysenter</code> для системных вызовов во всех нижеследующих макросах [<b>$</b>]<b>lsyscall</b>[<b>r</b>].</li>
<li>Макросы <b>lsyscalli</b>, <b>lsyscallir</b>, <b>$lsyscalli</b>, <b>$lsyscallir</b> – аналогичны макросам [<b>$</b>]<b>lsyscall</b>[<b>r</b>], но используют именно <code class="inlinecode">int 0x80</code> вне зависимости от выбранного режима (<b>lsyscall_use_<i>XXX</i></b>).</li>
<li>Макросы <b>lsyscallse</b>, <b>lsyscallser</b>, <b>$lsyscallse</b>, <b>$lsyscallser</b> – аналогичны макросам [<b>$</b>]<b>lsyscall</b>[<b>r</b>], но используют именно <code class="inlinecode">sysenter</code> вне зависимости от выбранного режима (<b>lsyscall_use_<i>XXX</i></b>).</li>
</ul><br />
Дополнительные макросы именованных вызовов (<b>linux_syscall_fn.mac</b>):<ul><li>Макрос <b>lsyscall_fn_noregsaving</b> – использовать макросы <font color="DarkSlateGray"><b>lsyscall</b></font> и <font color="DarkSlateGray"><b>lsyscallr</b></font> (не сохраняющие регистры) для всех нижеследующих системных вызовов в именованных макросах вроде <font color="DarkSlateGray"><b>lsys_read_con</b></font>, <font color="DarkSlateGray"><b>lsys_write_con</b></font> и пр. (действует по умолчанию).</li>
<li>Макрос <b>lsyscall_fn_regsaving</b> – использовать макросы <font color="DarkSlateGray"><b>$lsyscall</b></font> и <font color="DarkSlateGray"><b>$lsyscallr</b></font> (сохраняющие регистры) для всех нижеследующих системных вызовов в именованных макросах.</li>
</ul>p.s. Макрос <b>lsys_exit</b> всегда использует <font color="DarkSlateGray"><b>lsyscall</b></font> (т.е. режим <font color="DarkSlateGray"><b>lsyscall_fn_noregsaving</b></font>), т.к. сохранение регистров при завершении программы бессмысленно.<br />
<br />
Макросы для внутреннего применения, которые тем не менее можно использовать и в программах (любой разрядности):<ul><li>Макрос <b>movx reg,value</b> – оптимизированный вариант инструкции <code class="inlinecode">mov</code>: использует <code class="inlinecode">xor reg,reg</code> при записи нулевого значения в регистр и <code class="inlinecode">or reg,-1</code> при записи значения <b>-1</b>. <b>NASM</b> автоматически заменяет 64-битный регистр 32-битным при записи в первый числового значения, не превышающего 32-х бит, поэтому здесь подобная оптимизация не требуется. Обнуление 64-битного регистра через <code class="inlinecode">xor</code> <b>NASM</b> не оптимизирует, но макрос делает это сам (например, <code class="inlinecode">movx rax,0</code> преобразуется в <code class="inlinecode">xor eax,eax</code>). Если указаны 2 одинаковых регистра, макрос не генерирует инструкций (за исключением 32-битных регистров в 64-битном режиме, т.к. приём вида <code class="inlinecode">mov eax,eax</code> используется для очистки старших 32-х бит 64-битного регистра вместо недопустимого <code class="inlinecode">movzx rax,eax</code>).<br />
<font color="DarkRed"><b>Важно:</b></font> макрос не предназначен для записи в память, т.к. вызов вида <code class="inlinecode">movx &#91;eax&#93;,0</code> сгенерирует недопустимый код <code class="inlinecode">xor &#91;eax&#93;,&#91;eax&#93;</code>, а <code class="inlinecode">mov &#91;eax&#93;,-1</code> более медленный <code class="inlinecode">or &#91;eax&#93;,-1</code>.</li>
<li> Макрос <b>find_in_list exp, list</b> выполняет поиск выражения <font color="DarkSlateGray"><b>exp</b></font> в списке <font color="DarkSlateGray"><b>list</b></font> (например, <code class="inlinecode">find_in_list REG, eax,ebx,ecx,edx</code>). Устанавливает в качестве результата значение <b>?found_in_list = -1</b>, если выражение найдено, <b>?found_in_list = 0</b> в противном случае.</li>
</ul><br />
При подключении файла <b>linux_syscall.inc</b> становятся доступны следующие идентификаторы (которые позволяют создавать программы разной разрядности без изменения кода):<ul><li><b>?ax</b>, <b>?bx</b>, <b>?cx</b>, <b>?dx</b>, <b>?si</b>, <b>?di</b>, <b>?bp</b>, <b>?sp</b> – псевдонимы регистров <b>EAX</b>, <b>EBX</b>, <b>ECX</b>, <b>EDX</b>, <b>ESI</b>, <b>EDI</b>, <b>EBP</b>, <b>ESP</b> или <b>RAX</b>, <b>RBX</b>, <b>RCX</b>, <b>RDX</b>, <b>RSI</b>, <b>RDI</b>, <b>RBP</b>, <b>RSP</b> в зависимости от разрядности приложения.</li>
<li><b>?rfn</b> – регистр, используемый для записи номера функции (<b>EAX</b> или <b>RAX</b>, то же, что и <b>?ax</b>, по сути), <b>?rp1</b>..<b>?rp6</b> – регистры, используемые для параметров №1..6 в зависимости от разрядности кода.</li>
<li><b>?size = 4</b> для 32-битного кода, <b>?size = 8</b> для 64-битного кода.</li>
<li><b>?dd</b> – псевдоним <b>dd</b> или <b>dq</b>, <b>?resd</b> – псевдоним <b>resd</b> или <b>resq</b> в зависимости от разрядности кода.</li>
</ul><br />
Пара слов про чувствительность к регистру букв.<ul><li>Имена всех макросов (включая именованные макросы и макросы для внутреннего использования) <i>НЕ</i>чувствительны к регистру.</li>
<li>Псевдонимы регистров (<b>?ax</b>, <b>?rfn</b>, <b>?rp1</b> и пр), а также <b>?size</b>, <b>?dd</b>, <b>?resd</b> <i>НЕ</i>чувствительны к регистру.</li>
<li>Номера функций (<font color="DarkSlateGray"><b>sys_exit</b>, <b>sys_read</b>, <b>sys_write</b></font>...) и константы из файла <b>linux_const.inc</b> (<font color="DarkSlateGray"><b>STDIN_FILENO</b>, <b>STDOUT_FILENO</b></font>...) чувствительны к регистру.</li>
</ul><br />
Вот, собственно, и всё.<br />
<font color="Blue"><b>Все исходники прикреплены к данной статье!</b></font> (см. ниже файл <b>Linux_syscall.NASM.zip</b>)<br />
Примеры использования находятся в папке <b>examples</b> (все они выполняют одно и то же, но разными способами, при этом генерируется код <font color="DarkSlateGray"><b>x86</b></font>, <font color="DarkSlateGray"><b>x64</b></font> и <font color="DarkSlateGray"><b>x32</b></font>). Там же расположены cmd/sh-файлы для компиляции и готовые программы ;)<br />
<br />
p.s. Есть планы по доработке и созданию новых макросов, по пока обещать ничего не буду.<br />
<br />
<hr style="height:1px;border:0;color:#909090;background:#909090" /><br />
<font size="3"><b>Где найти описание системных функций, их номера и параметры?</b></font><br />
<br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6277.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Приведу несколько ссылок:<ul><li><a rel="nofollow noopener noreferrer" href="http://linuxdoc.ru/sys-doc.html" target="_blank" title="http://linuxdoc.ru/sys-doc.html">Документация по системным вызовам Linux</a> (на русском, неполный набор функций, без номеров)</li>
<li><a rel="nofollow noopener noreferrer" href="http://syscalls.kernelgrok.com/" target="_blank" title="http://syscalls.kernelgrok.com/">Linux Syscall Reference</a> (для x86, с номерами)</li>
<li><a rel="nofollow noopener noreferrer" href="http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/" target="_blank" title="http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/">LINUX SYSTEM CALL TABLE FOR X86 64</a> (для x64, с номерами, но без описания)</li>
<li> <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4937&amp;d=1531905229" target="_blank">LINUX System Call Quick Reference.pdf</a> (неполная таблица номеров системных вызовов x86)<br />
</li>
</ul><font color="Red"><i><b>Буду рад, если пришлёте мне ссылки на хорошие справочники по системным вызовам!</b></i></font> :thank_you:<br />
<br />
<b>О программировании в Linux:</b><ul><li><a rel="nofollow noopener noreferrer" href="http://www.gamedev.ru/code/articles/gcc_inline_asm?page=2" target="_blank" title="http://www.gamedev.ru/code/articles/gcc_inline_asm?page=2">GNU Assembler и синтаксис AT&amp;T</a> (про синтаксис AT&amp;T, там можно полистать &#8592;/&#8594;)</li>
<li><a rel="nofollow noopener noreferrer" href="https://ru.wikibooks.org/wiki/Ассемблер_в_Linux_для_программистов_C" target="_blank" title="https://ru.wikibooks.org/wiki/Ассемблер_в_Linux_для_программистов_C">Ассемблер в Linux для программистов C</a></li>
<li><a rel="nofollow noopener noreferrer" href="http://int80h.org/" target="_blank" title="http://int80h.org/">http://int80h.org/</a></li>
<li>См. прикреплённые книги...</li>
</ul></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4936&amp;d=1531905229">Linux_syscall.NASM.zip</a> (39.7 Кб, 613 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/pdf.gif" alt="Тип файла: pdf" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4938&amp;d=1531905229" target="_blank">syscalls.pdf</a> (420.0 Кб, 2277 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4939&amp;d=1531905229">linux_sys_prog.zip</a> (9.24 Мб, 3578 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4940&amp;d=1531905229">adv_linux_prog.zip</a> (3.37 Мб, 23818 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5351.html</guid>
		</item>
		<item>
			<title>Инструменты для низкоуровневого программирования</title>
			<link>https://www.cyberforum.ru/blogs/521524/5176.html</link>
			<pubDate>Mon, 12 Mar 2018 17:55:52 GMT</pubDate>
			<description>*Инструменты для низкоуровневого программирования* 
 
*Смотрите также:* 
 
*• Подборка литературы...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Инструменты для низкоуровневого программирования</b></font></font><br />
<br />
<table cellspacing="1" cellpadding="5" class="stg_table tborder"><tbody><tr class="alt2"><td><div align="center"><b>Смотрите также:</b></div></td></tr><tr class="alt1"><td><b>• <a href="https://www.cyberforum.ru/blogs/521524/blog5173.html">Подборка литературы по низкоуровневому программированию</a></b></td></tr><tr class="alt2"><td><b>• <a href="https://www.cyberforum.ru/low-level/thread2208389.html#a_topics">Полезные темы по низкоуровневому программированию</a></b></td></tr><tr class="alt1"><td><b>• </b><a href="https://www.cyberforum.ru/low-level/thread2208481.html">Обсуждение полезных ссылок, книг, инструментов...</a></td></tr></tbody></table><br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6296.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
<font size="3"><b>[APLACE=&quot;compilers&quot;]Компиляторы и компоновщики[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://masm32.com/" target="_blank" title="http://masm32.com/"><b>MASM32</b> (Macro Assembler)</a> – наверное, самый популярный пакет самого популярного ассемблера от Стива Хатчессона aka Hutch (содержит в себе также PoAsm), рекомендую сразу <a rel="nofollow noopener noreferrer" href="http://xk8.ru/ml8" target="_blank" title="http://xk8.ru/ml8">скачать ml.exe 8.0</a> и заменить им входящий в пакет ml.exe 6.14<ul><li><a rel="nofollow noopener noreferrer" href="http://masm32.com/download/build_x64.zip" target="_blank" title="http://masm32.com/download/build_x64.zip">MASM64 by Hutch</a> – набор файлов для 64-битной версии MASM (необходимо запустить <code class="inlinecode">makeall.bat</code>, а потом обратить особое внимание на файл <code class="inlinecode">include64\masm64rt.inc</code>); файлы <i>ml64.exe</i>, <i>link.exe</i> и прочие потроха можно взять из <a rel="nofollow noopener noreferrer" href="https://www.visualstudio.com/ru/" target="_blank" title="https://www.visualstudio.com/ru/">Visual Studio</a> (путь к папке с нужными файлами примерно такой: <code class="inlinecode">C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.12.25827\bin\Hostx64\x64\</code>)</li>
<li><a rel="nofollow noopener noreferrer" href="http://dsmhelp.narod.ru/masm64.zip" target="_blank" title="http://dsmhelp.narod.ru/masm64.zip">MASM64 includes and libs</a> – заголовки и библиотеки для 64-битного MASM'а от Vasiliy (тут главный файл – <code class="inlinecode">include64\temphls.inc</code>, который включён в набор Hutch'а и называется <code class="inlinecode">macros64\vasily.inc</code>, так что скачивать оба пакета смысла нет; однако <a rel="nofollow noopener noreferrer" href="http://dsmhelp.narod.ru/environment.htm" target="_blank" title="http://dsmhelp.narod.ru/environment.htm">информацию с сайта Василия</a> почитать стоит)</li>
<li><a rel="nofollow noopener noreferrer" href="http://dsmhelp.narod.ru/index.htm" target="_blank" title="http://dsmhelp.narod.ru/index.htm">Disassemble Help Library</a> – Библиотека того же автора (Vasiliy) для дизассемблирования</li>
<li><a rel="nofollow noopener noreferrer" href="http://dsmhelp.narod.ru/calceng.htm" target="_blank" title="http://dsmhelp.narod.ru/calceng.htm">Calculation Engine</a> – Библиотека для работы с длинными числами (снова by Vasiliy)</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="http://flatassembler.net/" target="_blank" title="http://flatassembler.net/"><b>fasm</b> (flat assembler)</a> – современный и удобный компилятор под DOS, Wndows, Linux с очень развитой системой макросов и полным набором инструкций Intel/AMD</li>
<li><a rel="nofollow noopener noreferrer" href="http://nasm.us/" target="_blank" title="http://nasm.us/"><b>NASM </b>(Netwide Assembler)</a> – ещё один современный кроссплатформенный компилятор с хорошей макросистемой и полным набором инструкций Intel/AMD, популярен в зарубежных проектах и при программировании под Linux/BSD<ul><li><a rel="nofollow noopener noreferrer" href="https://sourceforge.net/projects/nasmx/" target="_blank" title="https://sourceforge.net/projects/nasmx/">NASMX</a> – пакет макросов, include'ов, примеров и утилит для NASM под Windows, Linux, BSD, Xbox; включает макрос invoke, символы для работы с OpenGL и пр.</li>
<li><a rel="nofollow noopener noreferrer" href="http://yasm.tortall.net/" target="_blank" title="http://yasm.tortall.net/"><b>Yasm</b> (Yet another assembler...)</a> – попытка переписать NASM, однако последняя версия датируется 2014 годом и, на мой взгляд, не имеет преимуществ перед NASM</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="http://www.terraspace.co.uk/uasm.html" target="_blank" title="http://www.terraspace.co.uk/uasm.html"><b>UASM</b> (он же HJWasm)</a> – современный MASM-совместимый мультиплатформенный ассемблер с полным набором инструкций Intel/AMD</li>
<li><a rel="nofollow noopener noreferrer" href="http://old-dos.ru/files/file_683.html" target="_blank" title="http://old-dos.ru/files/file_683.html"><b>TASM 5.x</b> (Turbo Assembler)</a> – старый, но всё ещё популярный ассемблер, в основном используется для создания программ под DOS</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.godevtool.com/" target="_blank" title="http://www.godevtool.com/">GoAsm</a> – ассемблер для написания программ под Windows (<a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/GoAsm" target="_blank" title="https://ru.wikipedia.org/wiki/GoAsm">Вики</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://github.com/nidud/asmc" target="_blank" title="https://github.com/nidud/asmc">Asmc Macro Assembler</a> (с исходниками) – переделанный JWasm с довольно приличной библиотекой различных функций<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://flatassembler.net/fasmg.zip" target="_blank" title="http://flatassembler.net/fasmg.zip"><b>fasmg</b> (flat assembler g)</a> – универсальный ассемблер под любую платформу (имеются include-модули для создания кода под AVR, i8051, x86/x64, генерации байт-кода JVM, аналогично можно создать свои модули; <a rel="nofollow noopener noreferrer" href="http://flatassembler.net/docs.php?article=fasmg" target="_blank" title="http://flatassembler.net/docs.php?article=fasmg">информация</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="http://arm.flatassembler.net/" target="_blank" title="http://arm.flatassembler.net/"><b>FASMARM</b></a> – ассемблер под архитектуру ARM</li>
<li><a rel="nofollow noopener noreferrer" href="https://www2.keil.com/mdk5" target="_blank" title="https://www2.keil.com/mdk5"><b>ARM Keil MDK</b></a> (Microcontroller Development Kit) – средство разработки и отладки для контроллеров ARM (ещё <a rel="nofollow noopener noreferrer" href="https://www.arm.com/products/development-tools/embedded-and-software/keil-mdk" target="_blank" title="https://www.arm.com/products/development-tools/embedded-and-software/keil-mdk">ссылка</a>; дополнительные <a rel="nofollow noopener noreferrer" href="https://www.keil.com/dd2/pack/" target="_blank" title="https://www.keil.com/dd2/pack/">паки</a>; <a rel="nofollow noopener noreferrer" href="https://www.keil.com/support/man/docs/armasm/default.htm" target="_blank" title="https://www.keil.com/support/man/docs/armasm/default.htm">документация</a> [english])</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads" target="_blank" title="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads"><b>GNU Arm Toolchain</b></a> – тулчейн для компиляции ARM-приложений под Windows [i686], Linux [x86-64 и AArch64], macOS [x86-64] (ещё одна <a rel="nofollow noopener noreferrer" href="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads" target="_blank" title="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads">ссылка</a>)<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://sourceforge.net/projects/alink/" target="_blank" title="https://sourceforge.net/projects/alink/"><b>ALINK</b></a>, <a rel="nofollow noopener noreferrer" href="http://www.godevtool.com/#linker" target="_blank" title="http://www.godevtool.com/#linker"><b>GoLink</b></a> – компоновщики для программ под DOS и Windows</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/#objconv" target="_blank" title="http://www.agner.org/optimize/#objconv"><b>objconv</b></a> – преобразователь форматов объектных файлов (COFF/OMF/ELF/Mach-O)</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.crinkler.net" target="_blank" title="http://www.crinkler.net"><b>Crinkler</b></a> – популярный среди демомейкеров компоновщик-упаковщик<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://godbolt.org/" target="_blank" title="https://godbolt.org/"><b>Godbolt: Compiler Explorer</b></a> – популярный онлайн-компилятор разных языков с дизассемблером</li>
<li><a rel="nofollow noopener noreferrer" href="http://shell-storm.org/online/Online-Assembler-and-Disassembler/" target="_blank" title="http://shell-storm.org/online/Online-Assembler-and-Disassembler/"><b>Online Assembler and Disassembler</b></a> – поддерживает x86, ARM, Mips, PowerPC, Sparc</li>
<li><a rel="nofollow noopener noreferrer" href="https://defuse.ca/online-x86-assembler.htm" target="_blank" title="https://defuse.ca/online-x86-assembler.htm"><b>Online x86 / x64 Assembler and Disassembler</b></a></li>
<li><a rel="nofollow noopener noreferrer" href="https://quick-bench.com/" target="_blank" title="https://quick-bench.com/"><b>Quick C++ Benchmark</b></a> – бенчмарк и профайлер кода C++ (Clang/GCC)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;resources&quot;]Работа с ресурсами[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://www.masm32.com/board/index.php?topic=239.0" target="_blank" title="http://www.masm32.com/board/index.php?topic=239.0"><b>ResEd</b></a> – бесплатный редактор ресурсов</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.resource-builder.ru" target="_blank" title="http://www.resource-builder.ru"><b>Resource Builder</b></a> – редактор + компилятор ресурсов (shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.godevtool.com/#rc" target="_blank" title="http://www.godevtool.com/#rc"><b>GoRC</b></a> – компилятор ресурсов (rc → res) [в вышеупомянутом <b>NASMX</b> есть и GoLink, и objconv, и GoRC]</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;sdk&quot;]Наборы разработчика[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://developer.microsoft.com/ru-ru/windows/downloads/windows-10-sdk" target="_blank" title="https://developer.microsoft.com/ru-ru/windows/downloads/windows-10-sdk"><b>Windows 10 Software Development Kit (SDK)</b></a> – заголовочные файлы, библиотеки, инструменты (в т.ч. отладчик <a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/" target="_blank" title="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/">WinDbg</a>: <a rel="nofollow noopener noreferrer" href="https://www.securitylab.ru/analytics/453911.php" target="_blank" title="https://www.securitylab.ru/analytics/453911.php">док1</a>, <a rel="nofollow noopener noreferrer" href="https://www.securitylab.ru/analytics/453906.php" target="_blank" title="https://www.securitylab.ru/analytics/453906.php">док2</a>, <a rel="nofollow noopener noreferrer" href="https://habrahabr.ru/post/187522/" target="_blank" title="https://habrahabr.ru/post/187522/">док3</a>) для разработчиков Windows</li>
<li><a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk" target="_blank" title="https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk"><b>Windows Driver Kit (WDK)</b></a> – инструменты для разработчика драйверов (<a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/index" target="_blank" title="https://docs.microsoft.com/en-us/windows-hardware/drivers/index">документация</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;ide&quot;]Среды разработки (IDE) для ассемблера[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://fresh.flatassembler.net/" target="_blank" title="http://fresh.flatassembler.net/"><b>Fresh IDE</b></a> – визуальная среда разработки для fasm</li>
<li><a rel="nofollow noopener noreferrer" href="http://dman95.github.io/SASM/" target="_blank" title="http://dman95.github.io/SASM/"><b>SASM</b> (SimpleASM)</a> – простая кроссплатформенная среда разработки для NASM, MASM, GAS, fasm с подсветкой синтаксиса и отладчиком (для NASM имеется набор макросов для упрощения работы с консолью)</li>
<li><a rel="nofollow noopener noreferrer" href="https://gri-software.com/ru/" target="_blank" title="https://gri-software.com/ru/"><b>ASM Visual</b></a> – IDE для MASM, fasm, TASM со встроенным отладчиком и поддержкой WinDbg, OllyDbg, TD, x64dbg (имеется возможность установить весь пакет инструментов при установки IDE)</li>
<li><a rel="nofollow noopener noreferrer" href="https://sourceforge.net/projects/guitasm8086/" target="_blank" title="https://sourceforge.net/projects/guitasm8086/"><b>GUI Turbo Assembler</b></a> – среда разработки со встроенным компилятором TASM, отладчиком и эмулятором DOSBox</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.easycode.cat/English/" target="_blank" title="http://www.easycode.cat/English/"><b>Easy Code</b></a> – IDE с поддержкой множества различных ассемблеров (Asmc, fasm, GoAsm, JWasm, MASM, PoAsm, UASM), встроенным отладчиком, редактором ресурсов и диалоговых окон</li>
<li><a rel="nofollow noopener noreferrer" href="https://sourceforge.net/p/fbedit/code/HEAD/tree/" target="_blank" title="https://sourceforge.net/p/fbedit/code/HEAD/tree/">Rad ASM</a> – стал частью FbEdit FreeBASIC code editor, ищите в папках <i>RadASM*</i> по указанной ссылке (<a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/RadASM" target="_blank" title="https://ru.wikipedia.org/wiki/RadASM">Вики</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://sourceforge.net/projects/jaeeditor/" target="_blank" title="https://sourceforge.net/projects/jaeeditor/">JaeEditor</a> (fasm) – последнее обновление в 2015 году</li>
<li><a rel="nofollow noopener noreferrer" href="https://sites.google.com/site/gssvisasm/" target="_blank" title="https://sites.google.com/site/gssvisasm/">GSS Visual Assembler</a> – TASM, MASM32 и др. Последнее обновление в 2014 году!</li>
<li><a rel="nofollow noopener noreferrer" href="http://asmworld.ru/instrumenty/fasm-editor-2-0/" target="_blank" title="http://asmworld.ru/instrumenty/fasm-editor-2-0/">FASM Editor</a> – последнее обновление в 2011 году</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;debuggers&quot;]Отладчики, дизассемблеры[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://www.ollydbg.de/" target="_blank" title="http://www.ollydbg.de/"><b>OllyDbg</b></a> – популярный 32-битный отладчик (готовится 64-битная версия, но пока ещё не вышла)</li>
<li><a rel="nofollow noopener noreferrer" href="https://x64dbg.com/" target="_blank" title="https://x64dbg.com/"><b>x64dbg</b></a> – хороший отладчик для 32- и 64-битного кода</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.hex-rays.com/products/ida/" target="_blank" title="https://www.hex-rays.com/products/ida/"><b>IDA Pro</b></a> – мощный интерактивный дизассемблер (shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="https://github.com/NationalSecurityAgency/ghidra" target="_blank" title="https://github.com/NationalSecurityAgency/ghidra"><b>Ghidra</b></a> – инструмент для реверс-инжиниринга от NSA (агентства национальной безопасности США), поддерживающий разные типы процессоров (<a rel="nofollow noopener noreferrer" href="https://ghidra-sre.org/" target="_blank" title="https://ghidra-sre.org/">официальный сайт</a> – требует VPN/Proxy; <a rel="nofollow noopener noreferrer" href="https://en.wikipedia.org/wiki/Ghidra" target="_blank" title="https://en.wikipedia.org/wiki/Ghidra">Wiki</a>; статья на Habr &quot;<a rel="nofollow noopener noreferrer" href="https://habr.com/ru/post/480824/" target="_blank" title="https://habr.com/ru/post/480824/">GHIDRA vs. IDA Pro</a>&quot;)</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.radare.org/" target="_blank" title="https://www.radare.org/">radare2</a> (r2) – свободный кроссплатформенный фреймворк для реверс-инжиниринга, написанный на Си, который включает дизассемблер, шестнадцатеричный редактор, анализатор кода и т.д. Используется при реверсе, отладке вредоносного ПО и прошивок (<a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Radare2" target="_blank" title="https://ru.wikipedia.org/wiki/Radare2">Вики</a>; GUI <a rel="nofollow noopener noreferrer" href="https://cutter.re" target="_blank" title="https://cutter.re">Cutter</a>).<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://old-dos.ru/files/file_1403.html" target="_blank" title="http://old-dos.ru/files/file_1403.html"><b>Turbo Debugger</b></a> – популярный отладчик под DOS</li>
<li><a rel="nofollow noopener noreferrer" href="http://old-dos.ru/files/file_193.html" target="_blank" title="http://old-dos.ru/files/file_193.html">AFD Pro</a> – ещё один отладчик под DOS</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/dos/debug/" target="_blank" title="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/dos/debug/">debug</a> – реализация от легендарного <a rel="nofollow noopener noreferrer" href="https://www.japheth.de" target="_blank" title="https://www.japheth.de">Japheth</a>, входящая в состав FreeDOS. Являясь полным клоном MS debug, имеет возможность выполнять отладку protect-mode DPMI-приложений. Больше ссылок, в т.ч. на репозиторий github, см. <a rel="nofollow noopener noreferrer" href="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/repositories/1.3/pkg-html/debug.html" target="_blank" title="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/repositories/1.3/pkg-html/debug.html">здесь</a></li>
<li> <a rel="nofollow noopener noreferrer" href="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/dos/debug/ldebug/" target="_blank" title="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/dos/debug/ldebug/">ldebug</a> – новая реализация MS debug от другого разработчика, и хотя она не входит в состав FreeDOS, но программа доступна в репозитории, а также на <a rel="nofollow noopener noreferrer" href="https://pushbx.org/ecm/download/ldebug/" target="_blank" title="https://pushbx.org/ecm/download/ldebug/">сайте разработчика</a> (<a rel="nofollow noopener noreferrer" href="https://pushbx.org/ecm/doc/ldebug.htm" target="_blank" title="https://pushbx.org/ecm/doc/ldebug.htm">документация</a>; ещё <a rel="nofollow noopener noreferrer" href="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/repositories/1.3/pkg-html/ldebug.html" target="_blank" title="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/repositories/1.3/pkg-html/ldebug.html">ссылки</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;emulators&quot;]Эмуляторы, виртуализаторы[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://www.dosbox.com/" target="_blank" title="http://www.dosbox.com/"><b>DOSBox</b></a> – очень популярный эмулятор компьютера для запуска программ под DOS (имеет встроенный замедлитель скорости)<ul><li><a rel="nofollow noopener noreferrer" href="https://caiiiycuk.github.io/dosify/" target="_blank" title="https://caiiiycuk.github.io/dosify/">Dosify me!</a> – DOSBox онлайн</li>
<li><a rel="nofollow noopener noreferrer" href="http://twt86.co/" target="_blank" title="http://twt86.co/">TweetX86</a> – ещё один DOSBox онлайн</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="http://emu8086.com/" target="_blank" title="http://emu8086.com/"><b>emu8086</b></a> – простенький эмулятор процессора 8086 и некоторых функций MS-DOS со встроенным ассемблером и средой, включая отладчик</li>
<li><a rel="nofollow noopener noreferrer" href="http://bochs.sourceforge.net/" target="_blank" title="http://bochs.sourceforge.net/"><b>Bochs</b></a> – эмулятор компьютера IBM PC</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.qemu.org/" target="_blank" title="https://www.qemu.org/"><b>QEMU</b></a> – эмулятор аппаратного обеспечения различных платформ (<a rel="nofollow noopener noreferrer" href="http://soft.mydiv.net/win/download-QEMU-Manager.html" target="_blank" title="http://soft.mydiv.net/win/download-QEMU-Manager.html">QEMU Manager</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-software-development-emulator" target="_blank" title="https://software.intel.com/en-us/articles/intel-software-development-emulator"><b>Intel Software Development Emulator (SDE)</b></a> – эмулятор расширений (инструкций) процессоров Intel</li>
<li><a rel="nofollow noopener noreferrer" href="http://takeda-toshiya.my.coocan.jp/msdos/index.html" target="_blank" title="http://takeda-toshiya.my.coocan.jp/msdos/index.html">MS-DOS Player</a> – удобно использовать при сборке проекта с помощью компиляторов DOS и Windows, а также при запуске консольных DOS-программ (графические режимы не поддерживаются)</li>
<li><a href="https://www.cyberforum.ru/c/thread2008643.html#post13307342">Статья об эмуляторах DOS</a> на этом форуме<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.vmware.com/products/workstation-player.html" target="_blank" title="https://www.vmware.com/products/workstation-player.html"><b>VMware Workstation Player</b></a> (бесплатный для персонального использования), <a rel="nofollow noopener noreferrer" href="https://www.vmware.com/products/workstation-pro.html" target="_blank" title="https://www.vmware.com/products/workstation-pro.html"><b>VMware Workstation Pro</b></a> (shareware) – мощные виртуализаторы, позволяющие создавать и запускать виртуальные машины</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.virtualbox.org/" target="_blank" title="https://www.virtualbox.org/"><b>Oracle VirtualBox</b></a> – альтернативный бесплатный виртуализатор</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.sandboxie.com/" target="_blank" title="https://www.sandboxie.com/"><b>Sandboxie</b></a> – песочница для запуска программ в изолированной среде (shareware)<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.lauterbach.com/frames.html?main.html" target="_blank" title="https://www.lauterbach.com/frames.html?main.html"><b>Симуляторы ARM</b> и других процессоров</a> – хорошие симуляторы, однако имеются заморочки с написанием скриптов.</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;editors&quot;]Редакторы PE и двоичных файлов[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://pe-explorer.com/" target="_blank" title="http://pe-explorer.com/"><b>PE Explorer</b></a> – редактор секций, ресурсов PE, дизассемблер (shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.angusj.com/resourcehacker/" target="_blank" title="http://www.angusj.com/resourcehacker/"><b>Resourse Hacker</b></a> – редактор ресурсов исполняемых файлов под Windows</li>
<li><a rel="nofollow noopener noreferrer" href="http://hiew.ru/indexr.html" target="_blank" title="http://hiew.ru/indexr.html"><b>Hiew</b></a> – редактор двоичных файлов со встроенным дизассемблером, просмотром и редактированием заголовков исполняемых файлов (shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="http://thestarman.pcministry.com/tool/dl/hexit157.zip" target="_blank" title="http://thestarman.pcministry.com/tool/dl/hexit157.zip">HexIt</a> – бесплатная альтернатива Hiew, но не такая красивая и довольно старая (2001 года)</li>
<li><a rel="nofollow noopener noreferrer" href="http://winhex.com/winhex/" target="_blank" title="http://winhex.com/winhex/"><b>WinHex</b></a> – Hex-редактор, позволяющий редактировать не только файлы, но и диски (по секторам) и память, не имеет дизассемблера (shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="https://imhex.werwolv.net/" target="_blank" title="https://imhex.werwolv.net/"><b>ImHex</b></a> – бесплатный и активно развивающийся hex-редактор с дизассемблером (разных типов процессоров) и множеством интересных функций (<a rel="nofollow noopener noreferrer" href="https://github.com/WerWolv/ImHex" target="_blank" title="https://github.com/WerWolv/ImHex">github</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;packers&quot;]Упаковщики и протекторы[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://upx.github.io/" target="_blank" title="https://upx.github.io/"><b>UPX</b> (Ultimate Packer for eXecutables)</a> – популярный бесплатный упаковщик EXE-файлов и DLL-библиотек</li>
<li><a rel="nofollow noopener noreferrer" href="https://bitsum.com/portfolio/pecompact/" target="_blank" title="https://bitsum.com/portfolio/pecompact/"><b>PECompact</b></a> – ещё один упаковщик (shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="http://aspack.com/aspack.aspx" target="_blank" title="http://aspack.com/aspack.aspx"><b>ASPack</b>, <b>ASProtect</b></a> – упаковщик и протектор EXE-файлов</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.oreans.com/themida.php" target="_blank" title="http://www.oreans.com/themida.php"><b>Themida</b></a> – мощное средство защиты программ (shareware, <a rel="nofollow noopener noreferrer" href="https://habrahabr.ru/post/106920/" target="_blank" title="https://habrahabr.ru/post/106920/">статья на Хабре</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.enigmaprotector.com/ru/aboutvb.html" target="_blank" title="http://www.enigmaprotector.com/ru/aboutvb.html"><b>Enigma Virtual Box</b></a> – бесплатный виртуализатор файлов, объединяющий исполняемый файл вместе с сопутствующими (dll, ocx, графическими и звуковыми файлами) в один (на этом сайте также имеется shareware-протектор <a rel="nofollow noopener noreferrer" href="http://www.enigmaprotector.com/ru/about.html" target="_blank" title="http://www.enigmaprotector.com/ru/about.html">Enigma Protector</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;profilers&quot;]Профилировщики, анализаторы кода[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://godbolt.org" target="_blank" title="https://godbolt.org"><b>Compiler Explorer</b></a> - инструмент, позволяющий быстро перевести код на языках высокого уровня (C++, Pascal и многие другие) в инструкции ассемблера (<a rel="nofollow noopener noreferrer" href="https://habr.com/post/339962/" target="_blank" title="https://habr.com/post/339962/">статья на Хабре</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="http://quick-bench.com" target="_blank" title="http://quick-bench.com"><b>Quick C++ Benchmark</b></a> - онлайн-бенчмарк кода на C++<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/ru-ru/intel-vtune-amplifier-xe" target="_blank" title="https://software.intel.com/ru-ru/intel-vtune-amplifier-xe"><b>Intel VTune Amplifier</b></a> – фирменный профилировщик от Intel (входит в состав <a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/parallel-studio-xe" target="_blank" title="https://software.intel.com/en-us/parallel-studio-xe">Intel Parallel Studio XE</a>; shareware)</li>
<li><a rel="nofollow noopener noreferrer" href="https://github.com/intel/IntelSEAPI" target="_blank" title="https://github.com/intel/IntelSEAPI"><b>Intel Single Event API</b></a> – бесплатный профилировщик от Intel с открытым исходным кодом</li>
<li><a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Valgrind" target="_blank" title="https://ru.wikipedia.org/wiki/Valgrind"><b>Valgrind</b></a> – бесплатный профилировщик под Linux</li>
<li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-architecture-code-analyzer" target="_blank" title="https://software.intel.com/en-us/articles/intel-architecture-code-analyzer"><b>Intel Architecture Code Analyzer (IACA)</b></a> – анализатор кода от Intel (<a rel="nofollow noopener noreferrer" href="https://habrahabr.ru/company/intel/blog/144195/" target="_blank" title="https://habrahabr.ru/company/intel/blog/144195/">статья на Хабре</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;sysutils&quot;]Системные утилиты[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://technet.microsoft.com/ru-ru/sysinternals" target="_blank" title="https://technet.microsoft.com/ru-ru/sysinternals"><b>Windows Sysinternals</b></a> – набор системных утилит для Windows (работа с процессами, мониторы и прочее)</li>
<li><a rel="nofollow noopener noreferrer" href="https://rufus.ie/ru/" target="_blank" title="https://rufus.ie/ru/"><b>Rufus</b></a> – утилита для создания загрузочных USB</li>
<li><a rel="nofollow noopener noreferrer" href="https://sourceforge.net/projects/winspyex/" target="_blank" title="https://sourceforge.net/projects/winspyex/"><b>WinSpy</b></a> – утилита для получения информации об открытых окнах и управления ими</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;os&quot;]Операционные системы[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://reactos.org/" target="_blank" title="https://reactos.org/"><b>ReactOS</b></a> – бесплатная Windows-совместимая операционная система с открытым исходным кодом (<a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/ReactOS" target="_blank" title="https://ru.wikipedia.org/wiki/ReactOS">Вики</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://kolibrios.org/ru/" target="_blank" title="https://kolibrios.org/ru/"><b>KolibriOS</b></a> – миниатюрная ОС, умещающаяся на дискету 1.44 Mb, с исходниками на fasm (<a rel="nofollow noopener noreferrer" href="https://www.easycoding.org/2010/02/27/rabota-s-tortoisesvn.html" target="_blank" title="https://www.easycoding.org/2010/02/27/rabota-s-tortoisesvn.html">как скачать</a> / <a rel="nofollow noopener noreferrer" href="http://xandeadx.ru/blog/soft/10" target="_blank" title="http://xandeadx.ru/blog/soft/10">ещё вариант</a>; <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/KolibriOS" target="_blank" title="https://ru.wikipedia.org/wiki/KolibriOS">Вики</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://github.com/torvalds/linux" target="_blank" title="https://github.com/torvalds/linux"><b>Исходники Linux</b></a> (на GitHub)</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.freedos.org/" target="_blank" title="https://www.freedos.org/"><b>FreeDOS</b></a> с исходниками (<a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/FreeDOS" target="_blank" title="https://ru.wikipedia.org/wiki/FreeDOS">Вики</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;miscinstruments&quot;]Прочее[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://farmanager.com/" target="_blank" title="https://farmanager.com/"><b>Far Manager</b></a> – менеджер файлов в стиле Norton Commander с подсветкой кода в редакторе</li>
<li><a rel="nofollow noopener noreferrer" href="https://github.com/klopp/asmtidy" target="_blank" title="https://github.com/klopp/asmtidy"><b>AsmTidy</b></a> – форматтер ассемблерных исходников в Intel-синтаксисе (бьютифайлер) на Perl (ему также посвящена отдельная <a href="https://www.cyberforum.ru/low-level/thread2422401.html">тема на форуме</a>)</li>
</ul><br />
<font color="DarkRed"><i><b>Считаете, что здесь нет чего-то важного? Нашли или битую ссылку ошибку?</b><br />
Пишите в комментариях или в <a href="https://www.cyberforum.ru/low-level/thread2208481.html">специальную тему</a> (предпочтительно). Варез не размещаю! ;)</i></font></div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5176.html</guid>
		</item>
		<item>
			<title>Подборка литературы по низкоуровневому программированию</title>
			<link>https://www.cyberforum.ru/blogs/521524/5173.html</link>
			<pubDate>Sat, 10 Mar 2018 21:54:48 GMT</pubDate>
			<description>*Подборка литературы по низкоуровневому программированию* 
(книги, статьи, техническая...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Подборка литературы по низкоуровневому программированию</b><br />
(книги, статьи, техническая документация)</font></font><br />
<br />
<table cellspacing="1" cellpadding="5" class="stg_table tborder"><tbody><tr class="alt2"><td><div align="center"><b>Смотрите также:</b></div></td></tr><tr class="alt1"><td><b>• <a href="https://www.cyberforum.ru/blogs/521524/blog5176.html">Инструменты для низкоуровневого программирования</a></b></td></tr><tr class="alt2"><td><b>• <a href="https://www.cyberforum.ru/low-level/thread2208389.html#a_topics">Полезные темы по низкоуровневому программированию</a></b></td></tr><tr class="alt1"><td><b>• </b><a href="https://www.cyberforum.ru/low-level/thread2208481.html">Обсуждение полезных ссылок, книг, инструментов...</a></td></tr></tbody></table><br />
<img src="https://www.cyberforum.ru/members/521524/albums/742/6288.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
<font size="3"><b>[APLACE=&quot;learn&quot;]Обучение программированию на ассемблере[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/143291302" target="_blank" title="https://www.ozon.ru/context/detail/id/143291302"><b>Зубков С.В. Assembler для DOS, Windows и Unix.</b> — ДМК Пресс, 2017. — 638 c.</a> [электронная], ISBN 978-5-97060-535-6 (<a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/6597815" target="_blank" title="https://www.ozon.ru/context/detail/id/6597815">печать по требованию</a> (2006) // <a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/140439514" target="_blank" title="https://www.ozon.ru/context/detail/id/140439514">бумажная оригинальная в мягкой обложке</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/138906676" target="_blank" title="https://www.ozon.ru/context/detail/id/138906676"><b>Руслан Аблязов. Программирование на ассемблере на платформе x86-64.</b> — ДМК Пресс, 2016. — 302 с.</a> [электронная], ISBN 978-5-97060-364-2 (<a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/6997397" target="_blank" title="https://www.ozon.ru/context/detail/id/6997397">печать по требованию</a> // <a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/33686195" target="_blank" title="https://www.ozon.ru/context/detail/id/33686195">бумажная оригинальная в мягкой обложке</a>)<br />
<br /></li>
<li><b><a href="https://www.cyberforum.ru/assembler/thread1005284.html">https://www.cyberforum.ru/asse... 05284.html</a></b> (архитектура ЦП, инструкции ассемблера, синтаксис и макросы MASM/TASM, различные алгоритмы) [прикреплённая тема на CyberForum'е]</li>
<li><b><a href="https://www.cyberforum.ru/assembler/thread883314.html">https://www.cyberforum.ru/asse... 83314.html</a></b> (множество практических примеров использования ассемблера, алгоритмов, трюков) [прикреплённая тема на CyberForum'е]</li>
<li><b><a href="https://www.cyberforum.ru/assembler/thread751124.html">https://www.cyberforum.ru/asse... 51124.html</a></b> (программирование на MASM32 под Windows) [прикреплённая тема на CyberForum'е]<ul><li><b><a href="https://www.cyberforum.ru/fasm/thread1240590.html">https://www.cyberforum.ru/fasm/thread1240590.html</a></b> (программирование на fasm под Windows) [прикреплённая тема на CyberForum'е]</li>
<li><a rel="nofollow noopener noreferrer" href="http://old-dos.ru/index.php?page=lib&amp;do=show&amp;id=593" target="_blank" title="http://old-dos.ru/index.php?page=lib&amp;do=show&amp;id=593"><b>Туториалы Iczelion'а</b></a> – уроки от гуру ассемблера под Win32 API (на русском)</li>
<li><a rel="nofollow noopener noreferrer" href="http://win32assembly.programminghorizon.com/tutorials.html" target="_blank" title="http://win32assembly.programminghorizon.com/tutorials.html">Iczelion's Win32 Assembly Tutorials Homepage</a> [english]</li>
</ul></li>
<li><b><a href="https://www.cyberforum.ru/low-level/thread2020902.html">https://www.cyberforum.ru/low-... 20902.html</a></b> – ссылки на электронные версии различных книг по низкоуровневому программированию, реверсингу, ассемблеру.<br />
<br /></li>
<li><b><a rel="nofollow noopener noreferrer" href="https://web.archive.org/web/20150822173159/http://www.wasm.ru/wault" target="_blank" title="https://web.archive.org/web/20150822173159/http://www.wasm.ru/wault">Статьи старого WASM'а</a></b> – кладезь обучающего материала на самые разные низкоуровневые темы (крайне рекомендую!)</li>
<li><b><a rel="nofollow noopener noreferrer" href="https://www.wasm.in/blog" target="_blank" title="https://www.wasm.in/blog">Статьи нового WASM'а</a></b> – не менее ценные<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://flatassembler.net/docs.php" target="_blank" title="http://flatassembler.net/docs.php"><b>Документация по fasm</b> (flat assembler)</a> [english] (примерно то же самое есть в архиве самого fasm [PDF] // <a href="https://www.cyberforum.ru/fasm/thread1240599.html">русский перевод версии 1.71</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="http://nasm.us/docs.php" target="_blank" title="http://nasm.us/docs.php"><b>Документация по NASM</b> (Netwide Assembler)</a> [english] (<a rel="nofollow noopener noreferrer" href="http://xk8.ru/nasmdocrus" target="_blank" title="http://xk8.ru/nasmdocrus">русский перевод 2001 года в PDF</a> // <a rel="nofollow noopener noreferrer" href="http://opennet.ru/docs/RUS/nasm/" target="_blank" title="http://opennet.ru/docs/RUS/nasm/">html-версия</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="http://xk8.ru/masmdoc" target="_blank" title="http://xk8.ru/masmdoc"><b>Документация по MASM</b> (Macro Assembler)</a> [english, PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.terraspace.co.uk/uasm.html#p1" target="_blank" title="http://www.terraspace.co.uk/uasm.html#p1"><b>UASM с документацией</b></a> (современный MASM-совместимый мультиплатформенный ассемблер) [english, PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://sourceware.org/binutils/docs-2.37/as.html" target="_blank" title="https://sourceware.org/binutils/docs-2.37/as.html"><b>Using as</b></a> – документация по GAS / GNU Assembler (ещё одна <a rel="nofollow noopener noreferrer" href="http://tigcc.ticalc.org/doc/gnuasm.html" target="_blank" title="http://tigcc.ticalc.org/doc/gnuasm.html">ссылка</a>; <a rel="nofollow noopener noreferrer" href="https://www.zap.org.au/elec2041-cdrom/gnutools/doc/gnu-assembler.pdf" target="_blank" title="https://www.zap.org.au/elec2041-cdrom/gnutools/doc/gnu-assembler.pdf">PDF</a> [english]; <a rel="nofollow noopener noreferrer" href="https://www.opennet.ru/docs/RUS/gas/" target="_blank" title="https://www.opennet.ru/docs/RUS/gas/">по-русски</a>)<ul><li><a rel="nofollow noopener noreferrer" href="https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html" target="_blank" title="https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html">How to Use Inline Assembly Language in C Code</a> (asm-вставки в GCC)</li>
</ul></li>
<li>Документация по <b>emu8086</b> на русском: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=918483" target="_blank">Вложение 918483</a> [CHM] (англ. оригинал см. в папке <b>documentation</b> после установки эмулятора)</li>
<li><a rel="nofollow noopener noreferrer" href="http://flatassembler.net/docs.php?article=fasmg_manual" target="_blank" title="http://flatassembler.net/docs.php?article=fasmg_manual"><b>Документация по fasmg</b></a> [english] (<a rel="nofollow noopener noreferrer" href="http://flatassembler.net/docs.php?article=fasmg" target="_blank" title="http://flatassembler.net/docs.php?article=fasmg">введение и обзор</a>)</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;instructions&quot;]Архитектура и инструкции процессоров Intel, AMD, ARM[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-sdm#three-volume" target="_blank" title="https://software.intel.com/en-us/articles/intel-sdm#three-volume"><b>Официальная документация Intel</b> (4 тома)</a> [всё на english, PDF]:<ul><li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/sites/default/files/managed/a4/60/253665-sdm-vol-1.pdf" target="_blank" title="https://software.intel.com/sites/default/files/managed/a4/60/253665-sdm-vol-1.pdf">Том 1. Общая архитектура (Volume 1: Basic Architecture)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/sites/default/files/managed/a4/60/325383-sdm-vol-2abcd.pdf" target="_blank" title="https://software.intel.com/sites/default/files/managed/a4/60/325383-sdm-vol-2abcd.pdf">Том 2. Справочник по набору инструкций (Volume 2: Instruction Set Reference)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/sites/default/files/managed/a4/60/325384-sdm-vol-3abcd.pdf" target="_blank" title="https://software.intel.com/sites/default/files/managed/a4/60/325384-sdm-vol-3abcd.pdf">Том 3. Руководство по системному программированию (Volume 3: System Programming Guide)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://software.intel.com/sites/default/files/managed/22/0d/335592-sdm-vol-4.pdf" target="_blank" title="https://software.intel.com/sites/default/files/managed/22/0d/335592-sdm-vol-4.pdf">Том 4. Моделезависимые регистры (Volume 4: Model-Specific Registers)</a> [PDF]</li>
</ul><a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-sdm" target="_blank" title="https://software.intel.com/en-us/articles/intel-sdm">Там же</a> можно скачать <a rel="nofollow noopener noreferrer" href="https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf" target="_blank" title="https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf">все тома одним документом</a>, либо <a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-sdm#nine-volume" target="_blank" title="https://software.intel.com/en-us/articles/intel-sdm#nine-volume">с разбивкой на 10 томов</a>, а также прочую документацию (например, <a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-sdm#optimization" target="_blank" title="https://software.intel.com/en-us/articles/intel-sdm#optimization">по оптимизации</a>)<br />
<a rel="nofollow noopener noreferrer" href="http://developer.intel.com/" target="_blank" title="http://developer.intel.com/">Корневой раздел сайта Intel для разработчиков</a><br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.amd.com/resources/developer-guides-manuals/" target="_blank" title="https://developer.amd.com/resources/developer-guides-manuals/"><b>Официальная документация AMD</b></a> (множество документов) [всё на english, PDF]<br />
Документация по архитектуре AMD64:<ul><li><a rel="nofollow noopener noreferrer" href="http://support.amd.com/TechDocs/24592.pdf" target="_blank" title="http://support.amd.com/TechDocs/24592.pdf">Том 1. Программирование приложений (Volume 1: Application Programming)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://support.amd.com/TechDocs/24593.pdf" target="_blank" title="http://support.amd.com/TechDocs/24593.pdf">Том 2. Системное программирование (Volume 2: System Programming)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://support.amd.com/TechDocs/24594.pdf" target="_blank" title="http://support.amd.com/TechDocs/24594.pdf">Том 3. Инструкции общего назначения и системные (Volume 3: General Purpose and System Instructions)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://support.amd.com/TechDocs/26568.pdf" target="_blank" title="https://support.amd.com/TechDocs/26568.pdf">Том 4. Мультимедийные 128- и 256-битные инструкции (Volume 4: 128-Bit and 256-Bit Media Instructions)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://support.amd.com/TechDocs/26569_APM_v5.pdf" target="_blank" title="http://support.amd.com/TechDocs/26569_APM_v5.pdf">Том 5. 64-битные мультимедийные инструкции и инструкции x87 (Volume 5: 64-Bit Media and x87 Floating-Point Instructions)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://support.amd.com/TechDocs/32035.pdf" target="_blank" title="http://support.amd.com/TechDocs/32035.pdf">Рекомендации по использованию компиляторов (Compiler Usage Guidelines)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://support.amd.com/TechDocs/25112.PDF" target="_blank" title="http://support.amd.com/TechDocs/25112.PDF">Руководство по оптимизации ПО (Software Optimization Guide)</a> [PDF]</li>
</ul><a rel="nofollow noopener noreferrer" href="http://developer.amd.com/" target="_blank" title="http://developer.amd.com/">Корневой раздел сайта AMD для разработчиков</a><br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://www.club155.ru/programming" target="_blank" title="http://www.club155.ru/programming"><b>Архитектура и система команд микропроцессоров x86</b></a> [на русском] (староватая документация; из описания расширений есть только x87, MMX, 3DNow! и SSE(1))</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html" target="_blank" title="https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html"><b>Intel Intrinsic Guide</b></a> – руководство по интринсикам x86 от Intel [english]</li>
<li><a rel="nofollow noopener noreferrer" href="http://ref.x86asm.net/" target="_blank" title="http://ref.x86asm.net/"><b>X86 Opcode and Instruction Reference</b></a> – исчерпывающие таблицы опкодов инструкций x86/x86-64 [english]</li>
<li><a rel="nofollow noopener noreferrer" href="https://uops.info/table.html" target="_blank" title="https://uops.info/table.html"><b>uops.info</b></a> – таблица микроопераций</li>
<li><a rel="nofollow noopener noreferrer" href="https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html" target="_blank" title="https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html">GCC x86 Options</a> – список микроархитектур процессоров и наборов инструкций, поддерживаемых ими [english]</li>
<li><a rel="nofollow noopener noreferrer" href="https://en.wikipedia.org/wiki/X86_instruction_listings" target="_blank" title="https://en.wikipedia.org/wiki/X86_instruction_listings">x86 instruction listings</a> (список инструкций с указанием процессоров, в которых они появились) [english]</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.nasm.us/doc/nasmdocb.html" target="_blank" title="https://www.nasm.us/doc/nasmdocb.html">The Netwide Assembler Instruction List</a> (ещё один список инструкций с указанием процессоров и дополнительной информацией, но без описания)<br />
<br /></li>
<li><b>Документация ARM:</b> <a rel="nofollow noopener noreferrer" href="https://developer.arm.com/architectures" target="_blank" title="https://developer.arm.com/architectures"><b>по архитектурам</b></a>, <a rel="nofollow noopener noreferrer" href="https://developer.arm.com/Processors" target="_blank" title="https://developer.arm.com/Processors"><b>по процессорам</b></a> [всё на english]</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0487/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0487/latest/"><b>Arm Architecture Reference Manual for A-profile architecture</b></a> [PDF]<ul><li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0406/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0406/latest/">ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/100076/latest/" target="_blank" title="https://developer.arm.com/documentation/100076/latest/">Instruction Set Assembly Guide for Armv7 and earlier Arm architectures Reference Guide</a> [PDF] (<a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/100076/0200/a32-t32-instruction-set-reference?lang=en" target="_blank" title="https://developer.arm.com/documentation/100076/0200/a32-t32-instruction-set-reference?lang=en">онлайн-версия</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0557/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0557/latest/">ARM Architecture Reference Manual Supplement ARMv8.1, for ARMv8-A architecture profile</a> [PDF]<ul><li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0597/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0597/latest/">Arm Armv8-A A32/T32 Instruction Set Architecture</a> [online]</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0596/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0596/latest/">Arm A64 Instruction Set Architecture</a> [online]</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0608/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0608/latest/">Arm Architecture Reference Manual Supplement Armv9, for Armv9-A architecture profile</a> [PDF]<ul><li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/ddi0602/latest/" target="_blank" title="https://developer.arm.com/documentation/ddi0602/latest/">Arm Armv9-A A64 Instruction Set Architecture</a> [online]</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/102374/latest" target="_blank" title="https://developer.arm.com/documentation/102374/latest">Learn the architecture: AArch64 Instruction Set Architecture</a> [online]</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/architectures/instruction-sets/intrinsics" target="_blank" title="https://developer.arm.com/architectures/instruction-sets/intrinsics"><b>Intrinsics</b></a> [online]</li>
<li><b>Quick Reference Cards:</b><ul><li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/qrc0001/latest/" target="_blank" title="https://developer.arm.com/documentation/qrc0001/latest/">ARM and Thumb-2 Instruction Set Quick Reference Card</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/qrc0007/latest/" target="_blank" title="https://developer.arm.com/documentation/qrc0007/latest/">Vector Floating Point Instruction Set Quick Reference Card</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="https://developer.arm.com/documentation/qrc0006/latest/" target="_blank" title="https://developer.arm.com/documentation/qrc0006/latest/">Thumb 16-bit Instruction Set Quick Reference Card</a> [PDF]</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.keil.com/support/man/docs/armasm/armasm_dom1361289850039.htm" target="_blank" title="https://www.keil.com/support/man/docs/armasm/armasm_dom1361289850039.htm">Assembler User Guide: ARM and Thumb Instructions</a> – документация Keil MDK [online]</li>
<li><a rel="nofollow noopener noreferrer" href="https://thinkingeek.com/arm-assembler-raspberry-pi/" target="_blank" title="https://thinkingeek.com/arm-assembler-raspberry-pi/">ARM assembler in Raspberry Pi</a> [online]</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;api&quot;]Справочники по API-функциям, прерываниям, системным вызовам[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://msdn.microsoft.com/ru-ru/" target="_blank" title="https://msdn.microsoft.com/ru-ru/"><b>Microsoft Developer Network (MSDN)</b></a> [преимущественно english] (библиотека официальной технической документации для разработчиков под Windows: большой справочник по функциям WinAPI, интерфейсам, структурам данных, примеры кода и пр).<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://www.cs.cmu.edu/~ralf/files.html" target="_blank" title="http://www.cs.cmu.edu/~ralf/files.html"><b>Ralf Brown's Interrupt List (RBIL)</b></a> [архив] (большой справочник по прерываниям DOS, портам ввода-вывода и т.п. // <a rel="nofollow noopener noreferrer" href="http://www.ctyme.com/rbrown.htm" target="_blank" title="http://www.ctyme.com/rbrown.htm">html-версия</a> // <a rel="nofollow noopener noreferrer" href="http://www.delorie.com/djgpp/doc/rbinter/" target="_blank" title="http://www.delorie.com/djgpp/doc/rbinter/">ещё одна html-версия</a>) [english]<br />
<a rel="nofollow noopener noreferrer" href="http://www.codenet.ru/cat/Platforms/Other-Platforms/DOS" target="_blank" title="http://www.codenet.ru/cat/Platforms/Other-Platforms/DOS"><b>DOS</b></a> – справочник по прерываниям (и не только), краткий, зато на русском</li>
<li><b>Набор справочников под DOS:</b><ul><li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=918031" target="_blank">Вложение 918031</a> – справочник по прерываниям, системным структурам данных (базовый набор материалов, уступающий RBIL) [english]</li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=918032" target="_blank">Вложение 918032</a> – альтернативный справочник по прерываниям [english]</li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=918033" target="_blank">Вложение 918033</a> – справочник по ассемблеру 8086 с описанием инструкций [на русском]</li>
</ul><br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md" target="_blank" title="https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md"><b>Linux System Call Table</b></a> (справочник по системным вызовам Linux'а для x86, x86_64, ARM и ARM64) [english]</li>
<li><a rel="nofollow noopener noreferrer" href="https://gist.github.com/yamnikov-oleg/454f48c3c45b735631f2" target="_blank" title="https://gist.github.com/yamnikov-oleg/454f48c3c45b735631f2"><b>Architecture calling conventions</b></a> (справочник по системным вызовам Linux'а для разных платформ, включая x86 и ARM, 32/64 бита) [english]</li>
<li><a rel="nofollow noopener noreferrer" href="http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/" target="_blank" title="http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/"><b>Linux System Call Table for x86-64</b></a> (справочник по системным вызовам 64-битного Linux'а) [english]</li>
<li><a rel="nofollow noopener noreferrer" href="http://linuxdoc.ru/sys-doc.html" target="_blank" title="http://linuxdoc.ru/sys-doc.html"><b>Документация по системным вызовам Linux</b></a> [на русском]</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;sysprog&quot;]Системное программирование, устройство операционных систем, BIOS[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/20285651" target="_blank" title="https://www.ozon.ru/context/detail/id/20285651"><b>Марк Руссинович, Дэвид Соломон, Алекс Ионеску. Внутреннее устройство Microsoft Windows.</b> — 6-е изд., часть 1. — Питер, 2013. — 800 с.</a>, ISBN 978-5-496-00434-3, 978-5-459-01730-4 (англ.: 978-0735648739) <font color="Gray">[товар закончился, но при желании найти всегда можно]</font><br />
Вышло <a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/product/vnutrennee-ustroystvo-windows-146287471/" target="_blank" title="https://www.ozon.ru/product/vnutrennee-ustroystvo-windows-146287471/">7-е издание этой части с Павлом Йосифовичем в качестве ещё одного соавтора – Питер, 2018 – 944 с.</a>, ISBN 978–5–4461–0663–9 (англ.: 978–3864905384).</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/35161136" target="_blank" title="https://www.ozon.ru/context/detail/id/35161136"><b>Марк Руссинович, Дэвид Соломон, Алекс Ионеску. Внутреннее устройство Microsoft Windows. Основные подсистемы ОС.</b> — 6-е изд., часть 2. — Питер, 2014. — 672 с.</a> [электронная], ISBN 978-5-496-00791-7 (англ.: 978-0735665873)<br />
<a rel="nofollow noopener noreferrer" href="https://www.amazon.com/Windows-Internals-Part-2-7th/dp/0135462401/" target="_blank" title="https://www.amazon.com/Windows-Internals-Part-2-7th/dp/0135462401/">7-е издание этой части есть пока только на английском языке</a> (ISBN 978-0135462409).</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/116668" target="_blank" title="https://www.ozon.ru/context/detail/id/116668"><b>Джеффри Рихтер. Windows для профессионалов. Создание эффективных Win32-приложений с учётом специфики 64-разрядной версии Windows.</b> — 4-е изд. — Питер, Русская редакция, 2001. — 752 с.</a> (есть вариант книги 2008 г. на 720 с., но она тоже 4-го издания, с переводом 2000 года... в чём разница?), 5-272-00384-5, 978–5–7502–0360–4 (англ.: 1-57231-996-8) <font color="Gray">[товар закончился]</font><br />
(<a href="https://www.cyberforum.ru/win-api/thread366937.html">https://www.cyberforum.ru/win-... 66937.html</a>)</li>
<li> <a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/product/rabota-s-yadrom-windows-254596163/" target="_blank" title="https://www.ozon.ru/product/rabota-s-yadrom-windows-254596163/"><b>Павел Йосифович. Работа с ядром Windows.</b> – Питер, 2021 – 400 c.</a>, ISBN 978–5–4461–1680–5 (англ.: 978-1977593375).</li>
<li> <a rel="nofollow noopener noreferrer" href="https://www.amazon.com/Windows-10-System-Programming-Part/dp/B086Y6M7LH/" target="_blank" title="https://www.amazon.com/Windows-10-System-Programming-Part/dp/B086Y6M7LH/"><b>Pavel Yosifovich. Windows 10 System Programming</b>, Part 1 – 2020</a>, ISBN 979-8634170381 [англ].<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://undocumented.ntinternals.net/" target="_blank" title="http://undocumented.ntinternals.net/"><b>NTAPI Undocumented Functions</b> (Microsoft Windows NT/2000/XP/Win7)</a> [english]</li>
<li><a rel="nofollow noopener noreferrer" href="http://hex.pp.ua/native-api.php" target="_blank" title="http://hex.pp.ua/native-api.php"><b>Native API</b></a> (там же: <a rel="nofollow noopener noreferrer" href="http://hex.pp.ua/nt/" target="_blank" title="http://hex.pp.ua/nt/">справочник по функциям</a>) [на русском]<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/17925734" target="_blank" title="https://www.ozon.ru/context/detail/id/17925734"><b>Роберт Лав. Ядро Linux. Описание процесса разработки.</b> — 3-е изд. — Вильямс, 2014. — 496 с.</a>, ISBN 978-5-8459-1944-1</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/31775298" target="_blank" title="https://www.ozon.ru/context/detail/id/31775298"><b>Роберт Лав. Linux. Системное программирование.</b> — 2-е изд. — Питер, 2016. — 448 с.</a>, ISBN 978-5-496-01684-1, 978-1449339531 (<a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/31934003" target="_blank" title="https://www.ozon.ru/context/detail/id/31934003">бумажная в мягкой обложке</a>)<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.dmtf.org/standards/smbios" target="_blank" title="https://www.dmtf.org/standards/smbios"><b>System Management BIOS</b></a> – спецификация SMBIOS</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/3506567/" target="_blank" title="https://www.ozon.ru/context/detail/id/3506567/"><b>Дармаван Салихан. BIOS. Дизассемблирование, модификация, программирование (+ CD-ROM).</b></a> — БХВ-Петербург, 2007. — 784 с., ISBN 978-5-9775-0050-0, 978-1-931769-60-0 <font color="Gray">[товар закончился]</font></li>
</ul><br />
<font size="3"><b>[APLACE=&quot;hardware&quot;]Программирование железа, драйверы[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/6962030" target="_blank" title="https://www.ozon.ru/context/detail/id/6962030"><b>Михаил Гук. Аппаратные средства IBM PC. Энциклопедия.</b> — 3-е изд. — Питер, 2008. — 1072 с.</a>, ISBN 978-5-46901-182-8 <font color="Gray">[товар закончился]</font> (<a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/17869254" target="_blank" title="https://www.ozon.ru/context/detail/id/17869254">книга 2001 г. на 816 с., есть в продаже</a>, ISBN 5-88782-290-2)</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/1365094" target="_blank" title="https://www.ozon.ru/context/detail/id/1365094"><b>Владимир Кулаков. Программирование на аппаратном уровне. Специальный справочник (+ дискета).</b> — 2-е изд. — Питер, 2003. — 848 с.</a>, ISBN 5-94723-487-4 <font color="Gray">[товар закончился]</font></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/28350645" target="_blank" title="https://www.ozon.ru/context/detail/id/28350645"><b>Всеволод Несвижский. Программирование аппаратных средств в Windows (+ CD-ROM).</b> — 2-е изд. — БХВ-Петербург, 2008. — 528 с.</a>  [электронная], ISBN 978-5-9775-0263-4 (<a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/4030170" target="_blank" title="https://www.ozon.ru/context/detail/id/4030170">бумажная в мягкой обложке</a>)</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/964082" target="_blank" title="https://www.ozon.ru/context/detail/id/964082"><b>Владимир Кулаков. Программирование дисковых подсистем (+ дискета).</b> — Питер 2002. — 762 с.</a>, ISBN 5-318-00623-Х <font color="Gray">[товар закончился]</font><br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://uefi.org/specifications" target="_blank" title="http://uefi.org/specifications"><b>UEFI Specifications</b></a> – спецификации UEFI (<a rel="nofollow noopener noreferrer" href="http://www.uefi.org/uefi" target="_blank" title="http://www.uefi.org/uefi">доп. ссылки</a>) и ACPI (<a rel="nofollow noopener noreferrer" href="http://www.uefi.org/acpi" target="_blank" title="http://www.uefi.org/acpi">доп. ссылки</a>)<br />
<br /></li>
<li><b><a href="https://www.cyberforum.ru/drivers-programming/thread1451904.html">https://www.cyberforum.ru/driv... 51904.html</a></b> <font color="DarkRed">(содержит множество полезных ссылок, которые я не вижу смысла дублировать ещё раз!)</font> [прикреплённая тема на CyberForum'е]</li>
<li><b>Другие прикреплённые темы раздела <a href="https://www.cyberforum.ru/drivers-programming/">Программирование драйверов</a></b> на CyberForum'е:<ul><li><a href="https://www.cyberforum.ru/drivers-programming/thread1892717.html">https://www.cyberforum.ru/driv... 92717.html</a></li>
<li><a href="https://www.cyberforum.ru/drivers-programming/thread1793186.html">https://www.cyberforum.ru/driv... 93186.html</a></li>
<li><a href="https://www.cyberforum.ru/drivers-programming/thread656538.html">https://www.cyberforum.ru/driv... 56538.html</a></li>
<li><a href="https://www.cyberforum.ru/drivers-programming/thread1298567.html">https://www.cyberforum.ru/driv... 98567.html</a></li>
<li><a href="https://www.cyberforum.ru/drivers-programming/thread51974.html">https://www.cyberforum.ru/driv... 51974.html</a></li>
</ul></li>
</ul><br />
<font size="3"><b>[APLACE=&quot;optimization&quot;]Оптимизация кода[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/optimization_manuals.zip" target="_blank" title="http://www.agner.org/optimize/optimization_manuals.zip"><b>Документация по оптимизации от Agner'а Fog'а</b> (5 томов в одном архиве)</a> [всё на english]:<ul><li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/optimizing_cpp.pdf" target="_blank" title="http://www.agner.org/optimize/optimizing_cpp.pdf">Оптимизация на C++ под Windows, Linux и Mac (Optimizing software in C++: An optimization guide for Windows, Linux and Mac platforms)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/optimizing_assembly.pdf" target="_blank" title="http://www.agner.org/optimize/optimizing_assembly.pdf">Оптимизация на ассемблере под платформы x86 (Optimizing subroutines in assembly language: An optimization guide for x86 platforms)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/microarchitecture.pdf" target="_blank" title="http://www.agner.org/optimize/microarchitecture.pdf">Микроархитектура Intel, AMD и VIA (The microarchitecture of Intel, AMD and VIA CPUs: An optimization guide for assembly programmers and compiler makers)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/instruction_tables.pdf" target="_blank" title="http://www.agner.org/optimize/instruction_tables.pdf">Таблицы инструкций Intel, AMD и VIA (Instruction tables: Lists of instruction latencies, throughputs and micro-operation breakdowns for Intel, AMD and VIA CPUs)</a> [PDF]</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/calling_conventions.pdf" target="_blank" title="http://www.agner.org/optimize/calling_conventions.pdf">Соглашения о вызовах для различных компиляторов и ОС (Calling conventions for different C++ compilers and operating systems)</a> [PDF]</li>
</ul><a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/" target="_blank" title="http://www.agner.org/optimize/">Там же</a> можно скачать различные исходники и готовые библиотеки (<a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/#asmlib" target="_blank" title="http://www.agner.org/optimize/#asmlib">оптимизированные стандартные функции</a>, <a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/#vectorclass" target="_blank" title="http://www.agner.org/optimize/#vectorclass">класс для работы с векторами</a>, <a rel="nofollow noopener noreferrer" href="http://www.agner.org/optimize/#links" target="_blank" title="http://www.agner.org/optimize/#links">полезные ссылки</a> и прочее)<br />
На этом сайте так же имеется <a rel="nofollow noopener noreferrer" href="http://www.agner.org/random/" target="_blank" title="http://www.agner.org/random/">раздел, посвящённый генераторам псевдослучайных чисел</a></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/4893803" target="_blank" title="https://www.ozon.ru/context/detail/id/4893803"><b>Ричард Гербер, Арт Бик, Кевин Смит, Ксинмин Тиан. Оптимизация ПО. Сборник рецептов.</b> — Питер, 2010. — 352 с.</a>, ISBN 978-5-388-00131-3, 0976483211 <font color="Gray">[товар закончился]</font><br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://www.sizecoding.org/wiki/Main_Page" target="_blank" title="http://www.sizecoding.org/wiki/Main_Page"><b>SizeCoding</b></a> – искусство создания крошечных программ (трюки для демосценеров) [english]</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;debug&quot;]Отладка, дизассемблирование, безопасность, RE[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/person/273845" target="_blank" title="https://www.ozon.ru/person/273845"><b>Книги Криса Касперски</b></a> (много)</li>
<li><a rel="nofollow noopener noreferrer" href="https://yadi.sk/d/cWNGDOpC3TCuuQ" target="_blank" title="https://yadi.sk/d/cWNGDOpC3TCuuQ"><b>Статьи Криса Касперски</b></a> [большой архив с PDF, DOC] (507 шт // <a rel="nofollow noopener noreferrer" href="https://cloud.mail.ru/public/GvAG/vkDAgjHAJ" target="_blank" title="https://cloud.mail.ru/public/GvAG/vkDAgjHAJ">доп. ссылка</a> // <a rel="nofollow noopener noreferrer" href="https://yandex.ru/search/?text=сборник%20статей%20Криса%20Касперски" target="_blank" title="https://yandex.ru/search/?text=сборник%20статей%20Криса%20Касперски">ещё вариант</a>)<br />
<br /></li>
<li><a rel="nofollow noopener noreferrer" href="http://ref.x86asm.net/index.html" target="_blank" title="http://ref.x86asm.net/index.html"><b>X86 Opcode and Instruction Reference</b></a> (справочник по инструкциям и их опкодам) [english]</li>
</ul><br />
<font size="3"><b>[APLACE=&quot;microcontrollers&quot;]Программирование микроконтроллеров[/APLACE]</b></font><ul><li><b>Фрунзе А.В. Микроконтроллеры? Это же просто!</b> — 4 тома:<ul><li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/31239395" target="_blank" title="https://www.ozon.ru/context/detail/id/31239395">Том 1. — Додэка XXI, ДМК Пресс, 2015. — 312 с.</a>, ISBN 978-5-97060-263-8</li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/1276812" target="_blank" title="https://www.ozon.ru/context/detail/id/1276812">Том 2. — ИД Скимен, 2002. — 392 с.</a>, ISBN 5-94929-003-8, 5-94929-001-1 <font color="Gray">[товар закончился]</font></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/5396798" target="_blank" title="https://www.ozon.ru/context/detail/id/5396798">Том 3. — ИД Скимен, 2003. — 224 с.</a>, ISBN 5-94929-003-7, 5-94929-001-1 <font color="Gray">[товар закончился]</font></li>
<li><a rel="nofollow noopener noreferrer" href="https://www.ozon.ru/context/detail/id/4005806" target="_blank" title="https://www.ozon.ru/context/detail/id/4005806">Том 4 (+ CD-ROM). — Додэка XXI, 2008. — 464 с.</a>, ISBN 978-5-94120-141-9</li>
</ul></li>
</ul><br />
<font size="3"><b>[APLACE=&quot;miscdocs&quot;]Разное[/APLACE]</b></font><ul><li><a rel="nofollow noopener noreferrer" href="http://www.mkurnosov.net/teaching/" target="_blank" title="http://www.mkurnosov.net/teaching/"><b>Сайт поддержки учебных курсов</b> д.т.н., профессора Кафедры вычислительных систем СибГУТИ <b>Курносова Михаила Георгиевича</b></a> (много слайдов лекций на актуальные темы, в основном про: параллельное программирование, распределённые вычислительные системы, OpenMP, оптимизация, векторизация кода и т.п.)<br />
Пример: <a rel="nofollow noopener noreferrer" href="http://www.mkurnosov.net/uploads/Main/mkurnosov-rdtsc-2014.pdf" target="_blank" title="http://www.mkurnosov.net/uploads/Main/mkurnosov-rdtsc-2014.pdf">Использование Time-Stamp Counter для измерения времени выполнения кода на процессорах с архитектурой Intel 64 и IA-32</a> [PDF]<br />
На сайте также есть 2 его книги:<ul><li><a rel="nofollow noopener noreferrer" href="http://dsabook.mkurnosov.net/" target="_blank" title="http://dsabook.mkurnosov.net/">Курносов М.Г. Введение в структуры и алгоритмы обработки данных. — Автограф, 2015. — 179 с.</a>, ISBN 978-5-9906983-4-5</li>
<li><a rel="nofollow noopener noreferrer" href="http://www.mkurnosov.net/uploads/Main/kurnosov-dcsft.pdf" target="_blank" title="http://www.mkurnosov.net/uploads/Main/kurnosov-dcsft.pdf">Курносов М.Г., Пазников А.А. Основы теории функционирования распределенных вычислительных систем. — Автограф, 2015. — 52 с.</a>, ISBN 978-5-9906983-5-2</li>
</ul></li>
<li><a rel="nofollow noopener noreferrer" href="http://sandpile.org/" target="_blank" title="http://sandpile.org/"><b>sandpile.org</b> – The world's leading source for technical x86 processor information</a> (набор справочников по регистрам, опкодам, типам данных и пр.; насчёт полноты и актуальности данных не уверен)<br />
<a rel="nofollow noopener noreferrer" href="http://sandpile.org/x86/cpuid.htm" target="_blank" title="http://sandpile.org/x86/cpuid.htm"><b>x86 architecture CPUID</b></a> (справочник по CPUID, похож на достаточно полный и актуальный)</li>
<li><b><a href="https://www.cyberforum.ru/assembler/thread1054686.html">https://www.cyberforum.ru/asse... 54686.html</a></b> (термины) [прикреплённая тема на CyberForum'е]</li>
</ul><br />
<hr style="height:1px;border:0;color:#909090;background:#909090" /><br />
<font color="DarkRed"><i><b>Друзья, давайте пополнять этот список вместе!</b> :good:<br />
Присылайте ссылки на полезную литературу или названия книг с указанием авторов в комментарии или в <a href="https://www.cyberforum.ru/low-level/thread2208481.html">специальную тему</a> на форуме.<br />
Только давайте собирать не всё подряд, а самое лучшее :)</i></font><br />
<br />
p.s. Ссылки на бесплатные (нелицензионные) электронные версии книг выкладывать не буду – ищите и обрящете! ;)</div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/rar.gif" alt="Тип файла: rar" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4723&amp;d=1520698604">TechHelp60.rar</a> (738.2 Кб, 931 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/rar.gif" alt="Тип файла: rar" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4724&amp;d=1520698604">IntrList102.rar</a> (793.3 Кб, 1287 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/rar.gif" alt="Тип файла: rar" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4725&amp;d=1520698604">ASML.rar</a> (58.3 Кб, 1167 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4726&amp;d=1520847173">emu8086_rus_help.zip</a> (249.9 Кб, 960 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5173.html</guid>
		</item>
		<item>
			<title>Оптимизация кода: обходимся без ветвлений</title>
			<link>https://www.cyberforum.ru/blogs/521524/5122.html</link>
			<pubDate>Mon, 05 Feb 2018 12:43:38 GMT</pubDate>
			<description>*Оптимизация кода: обходимся без ветвлений* 
 
Думаю, ни для кого не секрет, что использование...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Оптимизация кода: обходимся без ветвлений</b></font></font></div><br />
Думаю, ни для кого не секрет, что использование условных переходов (инструкций <code class="inlinecode">jcc</code> в ассемблере; конструкций <b>if</b>, <b>while</b>, <b>case</b>, <b>for</b> в языках высокого уровня), т.е. ветвлений, могут значительно снизить скорость работы функций. Несмотря на наличие &quot;умной&quot; системы предсказания переходов в современных процессорах, эта система нередко ошибается. Доказательством тому служит тот факт, что один условный переход порой способен затормозить на десятки процентов код из полусотни строк. &quot;Высокая цена&quot; ветвлений привела сначала к появлению инструкций <code class="inlinecode">setcc</code> в процессорах 386, а затем и <code class="inlinecode">cmovcc</code> в P6, что позволило ощутимо ускорить некоторые участки кода. Однако есть довольно много мини-алгоритмов, позволяющих обойтись не только без ветвлений, но и без этих инструкций. Несмотря на то, что такие блоки кода оказываются более длинными, работают они, как правило, значительно быстрее, чем короткие, но с условными переходами. Я намеренно пишу &quot;как правило&quot;, поскольку оптимизация, особенно громоздкая и применённая бездумно, иногда работает против поставленной цели (ускорения) – надо тестировать.<br />
Помимо приведённой выше пары наборов инструкций архитектура IA-32/Intel 64 имеет множество других, которые могут помочь минимизировать кол-во ветвлений, например, <code class="inlinecode">cmpxchg</code> (486+), <code class="inlinecode">sbb</code>, расширения SIMD, иногда даже <code class="inlinecode">loopz</code> (<code class="inlinecode">loopnz</code>) и <code class="inlinecode">bsf</code> (<code class="inlinecode">bsr</code>).<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6304.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
Рассмотрим некоторые из мини-алгоритмов без ветвлений.<br />
<br />
<b>Присваивание значений:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="348486312"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="348486312" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Заполнение EAX битами флага CF</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; = cf ? 0xFFFFFFFF : 0</span>
<span class="co1">; Таким образом можно заменить недокументированную инструкцию salc на 'sbb al,al'</span>
<span class="co1">; (например, в x64, где salc не поддерживается)</span>
&nbsp;
<span class="co1">; Заполнение EAX битами инверсного значения флага CF</span>
<span class="kw1">cmc</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; invert cf</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; = (source cf==0) ? 0xFFFFFFFF : 0</span>
&nbsp;
<span class="co1">; Заполнение EAX битами флага ZF</span>
<span class="kw1">setz</span> <span class="kw4">al</span>
<span class="kw1">movzx</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">al</span>
<span class="kw1">neg</span> <span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; 1 -&gt; 0xFFFFFFFF</span>
<span class="co1">; Или так (чуть медленнее, ИМХО):</span>
<span class="kw1">setnz</span> <span class="kw4">al</span> &nbsp; &nbsp; &nbsp;<span class="co1">; inverted condition ('nz' instead of 'z')</span>
<span class="kw1">movzx</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">al</span>
<span class="kw1">dec</span> <span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; 1 -&gt; 0; 0 -&gt; 0xFFFFFFFF</span>
&nbsp;
<span class="co1">; Добавление значения флага CF к EAX</span>
<span class="kw1">adc</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">0</span>
<span class="co1">; Вычитание значения флага CF из EAX</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">0</span>
&nbsp;
<span class="co1">; Добавление 1 к EAX при значении CF==0</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,-</span><span class="nu0">1</span>
<span class="co1">; Вычитание 1 из EAX при значении CF==0</span>
<span class="kw1">adc</span> <span class="kw4">eax</span><span class="sy1">,-</span><span class="nu0">1</span>
&nbsp;
<span class="co1">; Вычитание 1 из EAX при SF==0</span>
<span class="kw1">setns</span> <span class="kw4">dl</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = sf ? 0 : 1</span>
<span class="kw1">movzx</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">dl</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Сложение/вычитание с ограничением:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="111559031"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="111559031" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Если EAX &lt; N (сравнение беззнаковое), добавить к нему 1</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span>N &nbsp;<span class="co1">; use N+1 for condition EAX &lt;= N</span>
<span class="kw1">adc</span> <span class="kw4">eax</span><span class="sy1">,</span>N &nbsp;<span class="co1">; use N+1 for condition EAX &lt;= N</span>
&nbsp;
<span class="co1">; Если EAX &gt; N (сравнение беззнаковое), добавить к нему 1</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span>N<span class="sy1">+</span><span class="nu0">1</span> &nbsp; <span class="co1">; use 'N' for condition EAX &gt;= N</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,-</span>N<span class="sy1">-</span><span class="nu0">2</span> &nbsp;<span class="co1">; -N-2 = (not 10)-1; use 'not N' for condition EAX &gt;= N</span>
&nbsp;
<span class="co1">; Если EAX &lt; N (сравнение беззнаковое), вычесть из него 1</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,-</span>N &nbsp; <span class="co1">; use 'not N' for condition EAX &lt;= N</span>
<span class="kw1">adc</span> <span class="kw4">eax</span><span class="sy1">,</span>N<span class="sy1">-</span><span class="nu0">1</span> &nbsp;<span class="co1">; use 'N' for condition EAX &lt;= N</span>
&nbsp;
<span class="co1">; Если EAX &gt; N (сравнение беззнаковое), вычесть из него 1</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw1">not</span> N &nbsp;<span class="co1">; use -N for condition EAX &gt;= N</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw1">not</span> N &nbsp;<span class="co1">; use -N for condition EAX &gt;= N</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Работа со знаком:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="383786594"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="383786594" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Приведение регистра EAX к абсолютному (положительному) значению [Agner Fog]</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; copy sign bit of eax to all bits of edx</span>
<span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; invert all bits if negative</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; add 1 if negative</span>
<span class="co1">; Приведение ECX к абсолютному значению (если EDX использовать нельзя) [+]:</span>
<span class="kw1">mov</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span>
<span class="kw1">neg</span> <span class="kw4">ebx</span>
<span class="kw1">cmovns</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; if value is positive after neg</span>
<span class="co1">; Тем не менее, этот вариант (с cmovns) может быть чуть медленнее, чем:</span>
&nbsp; <span class="kw1">test</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">jns</span> <span class="sy1">.</span>pos &nbsp;<span class="co1">; </span>
&nbsp; <span class="kw1">neg</span> <span class="kw4">ecx</span>
<span class="sy1">.</span>pos<span class="sy1">:</span>
<span class="co1">; Тестируйте!</span>
&nbsp;
<span class="co1">; Приведение регистра EAX к отрицательному значению [модификация предыдущего кода]</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; copy sign bit of eax to all bits of edx</span>
<span class="kw1">not</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; inverted all bits in edx</span>
<span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; invert all bits if positive</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; add 1 if positive</span>
<span class="co1">; Приведение ECX к отрицательному значению (если EDX использовать нельзя) [+]:</span>
<span class="kw1">mov</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span>
<span class="kw1">neg</span> <span class="kw4">ebx</span>
<span class="kw1">cmovs</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; if value is negative after neg (you can also use cmovl)</span>
<span class="co1">; Аналогично, вариант с условным переходом (js) может оказаться быстрее, чем с cmovs.</span>
&nbsp;
<span class="co1">; Инвертирование знака EAX при CF==1</span>
<span class="kw1">sbb</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; copy cf value to all bits of edx</span>
<span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; invert all bits if cf</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; add 1 if cf</span>
&nbsp;
<span class="co1">; Установка знака EAX в соответствии с флагом CF (0 - положительное, 1 - отрицательное значение)</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; copy sign bit of eax to all bits of edx</span>
<span class="kw1">sbb</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; copy cf value to all bits of edx</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; 0xFFFFFFFF if need to change sign, 0 if not</span>
<span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; invert all bits if need to change sign</span>
<span class="kw1">sbb</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; add 1 if need to change sign</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Минимум, максимум:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="939277708"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="939277708" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Нахождение минимума среди EAX (a) и EBX (b), для беззнаковых чисел [Agner Fog, немного модифицированный код]</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = a-b</span>
<span class="kw1">sbb</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &lt; b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &lt; b) ? a-b : 0</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; result is in eax</span>
&nbsp;
<span class="co1">; Нахождение минимума среди EAX (a) и EBX (b), для знаковых чисел [Agner Fog, немного модифицированный код]</span>
<span class="co1">; Не работает при переполнении после первой инструкции, т.е. если числа отличаются на 0x80000000 и больше</span>
<span class="co1">; в знаковом формате (в этом случае работает наоборот - находит максимум)!</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; will not work if overflow here (it will find maximum - Jin X comment)</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt; b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &lt; b) ? a-b : 0</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; result is in eax</span>
&nbsp;
<span class="co1">; Нахождение минимума среди EAX (a) и EBX (b), для знаковых чисел [модифицированный предыдущий код]</span>
<span class="co1">; Работает при любых значениях EAX и EBX</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = a-b</span>
<span class="kw1">setl</span> <span class="kw4">dl</span>
<span class="kw1">neg</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt; b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &lt; b) ? a-b : 0</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; result is in eax</span>
&nbsp;
<span class="co1">; Нахождение минимума среди EAX и EBX с использованием cmovcc, для беззнаковых чисел</span>
<span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span>
<span class="kw1">cmova</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = ebx if eax (use cmovg for signed)</span>
&nbsp;
<span class="co1">; Нахождение максимума среди EAX (a) и EBX (b), для беззнаковых чисел [на основе кода поиска минимума]</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = a-b</span>
<span class="kw1">cmc</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; invert cf</span>
<span class="kw1">sbb</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &gt;= b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &gt;= b) ? a-b : 0</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; result is in eax</span>
&nbsp;
<span class="co1">; Нахождение максимума среди EAX (a) и EBX (b), для знаковых чисел [на основе кода поиска минимума]</span>
<span class="co1">; Не работает при переполнении после первой инструкции, т.е. если числа отличаются на 0x80000000 и больше</span>
<span class="co1">; в знаковом формате (в этом случае работает наоборот - находит минимум)!</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; will not work if overflow here (it will find minimum - Jin X comment)</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt; b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">not</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &gt;= b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &gt;= b) ? a-b : 0</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; result is in eax</span>
&nbsp;
<span class="co1">; Нахождение максимума среди EAX (a) и EBX (b), для знаковых чисел [модифицированный предыдущий код]</span>
<span class="co1">; Работает при любых значениях EAX и EBX</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span>
<span class="kw1">sub</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = a-b</span>
<span class="kw1">setg</span> <span class="kw4">dl</span>
<span class="kw1">neg</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &gt; b) ? 0xFFFFFFFF : 0</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &gt; b) ? a-b : 0</span>
<span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; result is in eax</span>
&nbsp;
<span class="co1">; Нахождение максимума среди EAX и EBX с использованием cmovcc, для беззнаковых чисел</span>
<span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span>
<span class="kw1">cmovb</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = ebx if eax (use cmovl for signed)</span>
&nbsp;
<span class="co1">; Приведение EAX к диапазону значений ECX..EDX (для знаковых чисел) [+]:</span>
<span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span>
<span class="kw1">cmovl</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; check and adjust lower bound (use cmovb for unsigned)</span>
<span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
<span class="kw1">cmovg</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; check and adjust upper bound (use cmova for unsigned)</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Условный выбор значений:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="541965194"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="541965194" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Выбор между значениями EBX (b) и ECX (c) в зависимости от знака EAX (a), результат в EDX [Agner Fog]</span>
<span class="kw1">test</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span>
<span class="kw1">mov</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span>
<span class="kw1">cmovs</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = (a &lt; 0) ? b : c</span>
&nbsp;
<span class="co1">; Как вы понимаете, в предыдущем фрагменте можно использовать любые регистры и условия</span>
<span class="co1">; Например, выбор между EAX (a) и EDX (d), последний выбирается при EBX (b) != ECX (c), результат в ESI:</span>
<span class="kw1">cmp</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span>
<span class="kw1">mov</span> <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">eax</span>
<span class="kw1">cmovne</span> <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (b != c) ? d : a</span>
&nbsp;
<span class="co1">; Выбор между значениями EBX (b) и ECX (c) в зависимости от знака EAX (a), без использования cmovcc,</span>
<span class="co1">; результат в EDX [Agner Fog]</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt; 0) ? 0xFFFFFFFF : 0</span>
<span class="kw1">xor</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; b ^ c = bits that differ between b and c</span>
<span class="kw1">and</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = (a &lt; 0) ? (b ^ c) : 0</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; = (a &lt; 0) ? b : c</span>
&nbsp;
<span class="co1">; Обмен значений EBX (b) и ECX (c) при CF==1 [на основе предыдущего кода]</span>
<span class="kw1">sbb</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = cf ? 0xFFFFFFFF : 0</span>
<span class="kw1">xor</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; b ^ c = bits that differ between b and c</span>
<span class="kw1">and</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp;<span class="co1">; = cf ? (b ^ c) : 0</span>
<span class="kw1">xor</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = cf ? b : c</span>
<span class="kw1">xor</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; = cf ? c : b</span>
&nbsp;
<span class="co1">; Код, из предыдущего фрагмента можно адаптировать под любое другое условие, заменив первую инструкцию</span>
<span class="co1">; Например, произвести обмен при EAX (a) &lt; 0:</span>
<span class="kw1">cdq</span> &nbsp;<span class="co1">; = (a &lt; 0) ? 0xFFFFFFFF : 0</span>
<span class="co1">; Произвести обмен при EAX (a) &lt;= 0:</span>
<span class="kw1">dec</span> <span class="kw4">eax</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt;= 0) ? 0xFFFFFFFF : 0</span>
<span class="co1">; Произвести обмен при EAX (a) &gt; 0:</span>
<span class="kw1">neg</span> <span class="kw4">eax</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &gt; 0) ? 0xFFFFFFFF : 0</span>
<span class="co1">; Произвести обмен при EAX (a) &gt;= 0:</span>
<span class="kw1">cdq</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt; 0) ? 0xFFFFFFFF : 0</span>
<span class="kw1">not</span> <span class="kw4">edx</span> &nbsp;<span class="co1">; = (a &gt;= 0) ? 0xFFFFFFFF : 0</span>
<span class="co1">; Произвести обмен при CF=0:</span>
<span class="kw1">cmc</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; invert cf</span>
<span class="kw1">sbb</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = (source cf==0) ? 0xFFFFFFFF : 0</span>
<span class="co1">; Произвести обмен при ESI (s) &gt; EDI (d), беззнаковое сравнение:</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span>
<span class="kw1">cmp</span> <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edi</span>
<span class="kw1">seta</span> <span class="kw4">dl</span> &nbsp;<span class="co1">; = (s &gt; d) ? 1 : 0</span>
<span class="kw1">neg</span> <span class="kw4">edx</span> &nbsp; <span class="co1">; = (s &gt; d) ? 0xFFFFFFFF : 0</span>
<span class="co1">; В последнем случае код получается довольно длинным (8 инструкций), и его использование</span>
<span class="co1">; может оказаться неоправданным – это необходимо тестировать на реальном коде!</span>
<span class="co1">; Вообще, тестирование вариантов кода, критичного к скорости исполнения - хорошая привычка :)</span>
&nbsp;
<span class="co1">; Обмен значений EBX (b) и ECX (c), если EAX (a) == EBX (b)</span>
<span class="kw1">cmpxchg</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; if (a==b) { eax=b; b=c; zf=1 }</span>
<span class="kw1">cmovz</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp;<span class="co1">; c=b if (a==b)</span>
&nbsp;
<span class="co1">; Обмен значений EAX (a) и EDX (d) при CF==1 с использованием cmovcc</span>
<span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span>
<span class="kw1">cmovc</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = d if cf</span>
<span class="kw1">cmovc</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; = a if cf</span>
&nbsp;
<span class="co1">; Пример адаптирования предыдущего кода под другие условия</span>
<span class="co1">; Обмен значений EAX (a) и EDX (d), если в ECX (c) установлены все биты по маске EBX (b):</span>
<span class="kw1">and</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ebx</span>
<span class="kw1">xor</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp; &nbsp;<span class="co1">; zf = 1 if (c &amp; b) == b</span>
<span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span>
<span class="kw1">cmove</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; = d if ((c &amp; b) == b)</span>
<span class="kw1">cmove</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; = a if ((c &amp; b) == b)</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Проверка границ и преобразование:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="623551855"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="623551855" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Проверка содержимого AL на символ цифры</span>
<span class="kw1">sub</span> <span class="kw4">al</span><span class="sy1">,</span><span class="st0">'0'</span>
<span class="kw1">cmp</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">9</span> &nbsp; &nbsp; &nbsp;<span class="co1">; '9'-'0'</span>
<span class="kw1">ja</span> <span class="sy1">.</span>notdigit
&nbsp;
<span class="co1">; Получение 16-ричной цифры (символа) из значения AL (a) == 0..15</span>
<span class="co1">; [+]</span>
<span class="kw1">cmp</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">10</span> &nbsp; &nbsp; &nbsp;<span class="co1">; cf=1 if a &lt; 10</span>
<span class="kw1">sbb</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="kw4">dl</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &lt; 10) ? 0xFF : 0</span>
<span class="kw1">and</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="nu0">7</span> &nbsp; &nbsp; &nbsp; <span class="co1">; = (a &lt; 10) ? 7 : 0 (use 27h for lower case letters 'a'..'f')</span>
<span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="st0">'A'</span><span class="sy1">-</span><span class="nu0">10</span> &nbsp;<span class="co1">; convert to char (use 'a'-10 for lower case)</span>
<span class="kw1">sub</span> <span class="kw4">al</span><span class="sy1">,</span><span class="kw4">dl</span> &nbsp; &nbsp; &nbsp;<span class="co1">; subtract a break between digits and letters (if a &lt; 10)</span>
<span class="co1">; или так:</span>
<span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">256</span><span class="sy1">-</span><span class="nu0">10</span> &nbsp;<span class="co1">; cf=1 if a &gt;= 10</span>
<span class="kw1">sbb</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="kw4">dl</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = (a &gt;= 10) ? 0xFF : 0</span>
<span class="kw1">and</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="nu0">7</span> &nbsp; &nbsp; &nbsp; <span class="co1">; = (a &gt;= 10) ? 7 : 0 (use 27h for lower case letters 'a'..'f')</span>
<span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="st0">'0'</span><span class="sy1">+</span><span class="nu0">10</span> &nbsp;<span class="co1">; convert to char</span>
<span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="kw4">dl</span> &nbsp; &nbsp; &nbsp;<span class="co1">; add a break between digits and letters (if a &gt;= 10)</span>
<span class="co1">; Этот код работает гораздо быстрее, чем:</span>
<span class="kw1">cmp</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">10</span>
<span class="kw1">sbb</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">69h</span>
<span class="kw1">das</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; very slow instruction</span>
<span class="co1">; Однако он может работать и чуть медленнее, чем:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">10</span>
&nbsp; <span class="kw1">jb</span> <span class="sy1">.</span>digit
&nbsp; <span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="nu0">7</span> &nbsp; &nbsp;<span class="co1">; add a break between digits and letters (if a &gt;= 10)</span>
<span class="sy1">.</span>digit<span class="sy1">:</span>
&nbsp; <span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="st0">'0'</span> &nbsp;<span class="co1">; convert to digit char</span>
<span class="co1">; Тестируйте!</span>
&nbsp;
<span class="co1">; Приведение строчной буквы AL к заглавной (остальные символы остаются без изменений)</span>
<span class="kw1">mov</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="kw4">al</span>
<span class="kw1">sub</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="st0">'a'</span>
<span class="kw1">cmp</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="nu0">26</span> &nbsp; <span class="co1">; alphabet has 26 letters</span>
<span class="kw1">sbb</span> <span class="kw4">dh</span><span class="sy1">,</span><span class="kw4">dh</span> &nbsp; <span class="co1">; = (al is lower case) ? 0xFF : 0</span>
<span class="kw1">and</span> <span class="kw4">dh</span><span class="sy1">,</span><span class="nu0">20h</span> &nbsp;<span class="co1">; = (al is lower case) ? 0x20 : 0</span>
<span class="kw1">sub</span> <span class="kw4">al</span><span class="sy1">,</span><span class="kw4">dh</span> &nbsp; <span class="co1">; convert to upper case</span>
&nbsp;
<span class="co1">; Приведение заглавной буквы AL к строчной (остальные символы остаются без изменений)</span>
<span class="kw1">mov</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="kw4">al</span>
<span class="kw1">sub</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="st0">'A'</span>
<span class="kw1">cmp</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="nu0">26</span> &nbsp; <span class="co1">; alphabet has 26 letters</span>
<span class="kw1">sbb</span> <span class="kw4">dh</span><span class="sy1">,</span><span class="kw4">dh</span> &nbsp; <span class="co1">; = (al is capital) ? 0xFF : 0</span>
<span class="kw1">and</span> <span class="kw4">dh</span><span class="sy1">,</span><span class="nu0">20h</span> &nbsp;<span class="co1">; = (al is capital) ? 0x20 : 0</span>
<span class="kw1">add</span> <span class="kw4">al</span><span class="sy1">,</span><span class="kw4">dh</span> &nbsp; <span class="co1">; convert to upper case</span>
&nbsp;
<span class="co1">; Приведение 16 строчных букв к заглавным (остальные символы остаются без изменений) с использованием SSE2</span>
<span class="co1">; Блок инициализации (выполняется 1 раз):</span>
<span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#40;</span><span class="nu0">127</span><span class="sy1">-</span><span class="st0">'z'</span><span class="br0">&#41;</span><span class="sy1">*</span><span class="nu0">01010101h</span>
<span class="kw3">movd</span> <span class="kw4">xmm2</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; mov eax value to lower dword of xmm2</span>
<span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#40;</span><span class="nu0">127</span><span class="sy1">-</span><span class="nu0">26</span><span class="br0">&#41;</span><span class="sy1">*</span><span class="nu0">01010101h</span>
<span class="kw3">movd</span> <span class="kw4">xmm3</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; mov eax value to lower dword of xmm3</span>
<span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">20202020h</span>
<span class="kw3">movd</span> <span class="kw4">xmm4</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; mov eax value to lower dword of xmm4</span>
<span class="kw3">pshufd</span> <span class="kw4">xmm2</span><span class="sy1">,</span><span class="kw4">xmm2</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp;<span class="co1">; fill entire xmm2 register by lower dword value</span>
<span class="kw3">pshufd</span> <span class="kw4">xmm3</span><span class="sy1">,</span><span class="kw4">xmm3</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp;<span class="co1">; fill entire xmm3 register by lower dword value</span>
<span class="kw3">pshufd</span> <span class="kw4">xmm4</span><span class="sy1">,</span><span class="kw4">xmm4</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp;<span class="co1">; fill entire xmm4 register by lower dword value</span>
<span class="co1">; Преобразование содержимого XMM0, результат будет также в XMM0:</span>
<span class="kw3">movdqa</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm0</span> &nbsp; &nbsp;<span class="co1">; temp register</span>
<span class="kw3">paddb</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm2</span> &nbsp; &nbsp; <span class="co1">; shift each byte with lower case letter to high signed short int values</span>
<span class="kw3">pcmpgtb</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm3</span> &nbsp; <span class="co1">; compare each byte with high 26 signed values and store 0xFF (if in range)</span>
<span class="kw3">pand</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm4</span> &nbsp; &nbsp; &nbsp;<span class="co1">; mask with 20h (difference between upper and lower case)</span>
<span class="kw3">psubb</span> <span class="kw4">xmm0</span><span class="sy1">,</span><span class="kw4">xmm1</span> &nbsp; &nbsp; <span class="co1">; convert each byte to upper case</span>
&nbsp;
<span class="co1">; Приведение 16 заглавных букв к строчным (остальные символы остаются без изменений) с использованием SSE2</span>
<span class="co1">; Блок инициализации (выполняется 1 раз):</span>
<span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#40;</span><span class="nu0">127</span><span class="sy1">-</span><span class="st0">'Z'</span><span class="br0">&#41;</span><span class="sy1">*</span><span class="nu0">01010101h</span>
<span class="kw3">movd</span> <span class="kw4">xmm2</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; mov eax value to lower dword of xmm2</span>
<span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#40;</span><span class="nu0">127</span><span class="sy1">-</span><span class="nu0">26</span><span class="br0">&#41;</span><span class="sy1">*</span><span class="nu0">01010101h</span>
<span class="kw3">movd</span> <span class="kw4">xmm3</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; mov eax value to lower dword of xmm3</span>
<span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">20202020h</span>
<span class="kw3">movd</span> <span class="kw4">xmm4</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; <span class="co1">; mov eax value to lower dword of xmm4</span>
<span class="kw3">pshufd</span> <span class="kw4">xmm2</span><span class="sy1">,</span><span class="kw4">xmm2</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp;<span class="co1">; fill entire xmm2 register by lower dword value</span>
<span class="kw3">pshufd</span> <span class="kw4">xmm3</span><span class="sy1">,</span><span class="kw4">xmm3</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp;<span class="co1">; fill entire xmm3 register by lower dword value</span>
<span class="kw3">pshufd</span> <span class="kw4">xmm4</span><span class="sy1">,</span><span class="kw4">xmm4</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp;<span class="co1">; fill entire xmm4 register by lower dword value</span>
<span class="co1">; Преобразование содержимого XMM0, результат будет также в XMM0:</span>
<span class="kw3">movdqa</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm0</span> &nbsp; &nbsp;<span class="co1">; temp register</span>
<span class="kw3">paddb</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm2</span> &nbsp; &nbsp; <span class="co1">; shift each byte with capital case letter to high signed short int values</span>
<span class="kw3">pcmpgtb</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm3</span> &nbsp; <span class="co1">; compare each byte with high 26 signed values and store 0xFF (if in range)</span>
<span class="kw3">pand</span> <span class="kw4">xmm1</span><span class="sy1">,</span><span class="kw4">xmm4</span> &nbsp; &nbsp; &nbsp;<span class="co1">; mask with 20h (difference between upper and lower case)</span>
<span class="kw3">paddb</span> <span class="kw4">xmm0</span><span class="sy1">,</span><span class="kw4">xmm1</span> &nbsp; &nbsp; <span class="co1">; convert each byte to lower case</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Манипуляции с битами:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="528951647"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="528951647" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Определить степень двойки значения EAX (с округлением в меньшую сторону), результат в ECX</span>
<span class="kw1">bsr</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; ecx = most significant bit of eax</span>
&nbsp;
<span class="co1">; Определить степень двойки значения EAX (с округлением в большую сторону), результат в ECX</span>
<span class="kw1">dec</span> <span class="kw4">eax</span>
<span class="kw1">bsr</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; ecx = most significant bit of (eax-1)</span>
<span class="kw1">inc</span> <span class="kw4">ecx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; result in ecx</span>
&nbsp;
<span class="co1">; Определить кол-во идущих подряд нулевых битов в младших разрядах EAX, результат в ECX</span>
<span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">32</span> &nbsp; <span class="co1">; bsf will not modify destination register if source == 0</span>
<span class="kw1">bsf</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; count of zero low bits</span>
<span class="co1">; Вместо этой конструкции можно использовать инструкцию 'tzcnt ecx,eax' из набора BMI1, однако</span>
<span class="co1">; я не рекомендую увлекаться этим, поскольку для её корректного использования вы должны быть</span>
<span class="co1">; уверены в том, что она поддерживается, иначе рискуете получить ту же bsf (с бессмысленным</span>
<span class="co1">; префиксом rep), которая при значении EAX==0 оставит результат в ECX неопределённым.</span>
&nbsp;
<span class="co1">; Определить кол-во идущих подряд единичных битов в младших разрядах EAX, результат в ECX</span>
<span class="kw1">not</span> <span class="kw4">eax</span> &nbsp; &nbsp; &nbsp;<span class="co1">; inverse all bits</span>
<span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">32</span> &nbsp; <span class="co1">; bsf will not modify destination register if source == 0</span>
<span class="kw1">bsf</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; count of non-zero low bits</span>
&nbsp;
<span class="co1">; Определить кол-во идущих подряд нулевых битов в старших разрядах EAX, результат в ECX</span>
<span class="kw1">or</span> <span class="kw4">ecx</span><span class="sy1">,-</span><span class="nu0">1</span> &nbsp; &nbsp;<span class="co1">; = -1; bsf will not modify destination register if source == 0</span>
<span class="kw1">bsr</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; count of zero low bits</span>
<span class="kw1">not</span> <span class="kw4">ecx</span>
<span class="kw1">add</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">32</span> &nbsp; <span class="co1">; = 31 - (ecx after bsr)</span>
<span class="co1">; Более простой (но опасный, см. ниже) вариант:</span>
<span class="kw1">lzcnt</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span>
<span class="co1">; Перед использованием этой инструкции необходимо проверить бит LZCNT в CPUID (уровень 0x80000001, бит 5 в ECX),</span>
<span class="co1">; иначе инструкция lzcnt превратиться в bsr (с бессмысленным префиксом rep) и вернёт не кол-во нулевых</span>
<span class="co1">; битов в старших разрядах, а номер последнего ненулевого бита (что далеко не одно и то же).</span>
&nbsp;
<span class="co1">; Определить кол-во идущих подряд единичных битов в старших разрядах EAX, результат в ECX</span>
<span class="kw1">not</span> <span class="kw4">eax</span> &nbsp; &nbsp; &nbsp;<span class="co1">; inverse all bits</span>
<span class="kw1">or</span> <span class="kw4">ecx</span><span class="sy1">,-</span><span class="nu0">1</span> &nbsp; &nbsp;<span class="co1">; = -1; bsf will not modify destination register if source == 0</span>
<span class="kw1">bsr</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; count of non-zero low bits</span>
<span class="kw1">not</span> <span class="kw4">ecx</span>
<span class="kw1">add</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">32</span> &nbsp; <span class="co1">; = 31 - (ecx after bsr)</span>
&nbsp;
<span class="co1">; Определить кол-во единичных битов в EAX, результат в ECX</span>
<span class="kw1">popcnt</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; requires SSE 4.2</span>
&nbsp;
<span class="co1">; Определить кол-во нулевых битов в EAX, результат в ECX</span>
<span class="kw1">not</span> <span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; inverse all bits</span>
<span class="kw1">popcnt</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; requires SSE 4.2</span>
&nbsp;
<span class="co1">; Определить кол-во общих младших нулевых битов в EAX и EBX, результат в ECX</span>
<span class="co1">; (например для 10110000b и 11101100b общее кол-во младших нулевых битов = 2)</span>
<span class="kw1">or</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp; <span class="co1">; join non-zero bits of eax and ebx</span>
<span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">32</span> &nbsp; <span class="co1">; you can remove this if you're sure that at least one of registers (eax or ebx) is non-zero or if you'll use jz after bsf</span>
<span class="kw1">bsf</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp;<span class="co1">; minimum of zero bit counts in eax and ebx</span>
&nbsp;
<span class="co1">; Сдвинуть EAX на бит влево при CF==1</span>
<span class="kw1">setc</span> <span class="kw4">cl</span> &nbsp; &nbsp; <span class="co1">; = cf ? 1 : 0</span>
<span class="kw1">shl</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">cl</span>
&nbsp;
<span class="co1">; Установить бит номер CL в регистре EAX при условии CF==1</span>
<span class="kw1">setc</span> <span class="kw4">dl</span>
<span class="kw1">movzx</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">dl</span> &nbsp;<span class="co1">; = cf ? 1 : 0</span>
<span class="kw1">shl</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">cl</span> &nbsp; &nbsp;<span class="co1">; = single bit if cf</span>
<span class="kw1">or</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; &nbsp;<span class="co1">; set bit if cf</span>
&nbsp;
<span class="co1">; Сбросить бит номер CL в регистре EAX при условии CF==0</span>
<span class="kw1">setnc</span> <span class="kw4">dl</span>
<span class="kw1">movzx</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">dl</span> &nbsp;<span class="co1">; = cf ? 0 : 1</span>
<span class="kw1">shl</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">cl</span> &nbsp; &nbsp;<span class="co1">; = single bit if not cf</span>
<span class="kw1">not</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp; <span class="co1">; inverse bit</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; <span class="co1">; clear bit if not cf</span>
&nbsp;
<span class="co1">; Установить бит номер CL в регистре EAX в соответствии со значением флага CF</span>
<span class="kw1">setc</span> <span class="kw4">dl</span> &nbsp; &nbsp; &nbsp;<span class="co1">; = cf ? 1 : 0</span>
<span class="kw1">bt</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp; <span class="co1">; cf = is bit already set in eax?</span>
<span class="kw1">sbb</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="nu0">0</span> &nbsp; &nbsp;<span class="co1">; dl = 1 or 0xFF if source cf != bit in eax</span>
<span class="kw1">and</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="nu0">1</span> &nbsp; &nbsp;<span class="co1">; extract single bit of dl</span>
<span class="kw1">shl</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">cl</span> &nbsp; <span class="co1">; = single bit if eax != 0</span>
<span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; inverse if source cf != bit in eax</span>
&nbsp;
<span class="co1">; Обнулить старшие биты в EAX, сохранив CL (0..31) младших</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; clear all bits</span>
<span class="kw1">bts</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; set bit cl in edx</span>
<span class="kw1">dec</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; make mask of cl lower bits</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; apply mask</span>
&nbsp;
<span class="co1">; Обнулить CL (0..31) младших битов в EAX</span>
<span class="kw1">or</span> <span class="kw4">edx</span><span class="sy1">,-</span><span class="nu0">1</span> &nbsp; &nbsp;<span class="co1">; set all bits</span>
<span class="kw1">btr</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; set bit cl in edx</span>
<span class="kw1">inc</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; make mask of cl lower bits</span>
<span class="kw1">and</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; apply mask</span>
&nbsp;
<span class="co1">; Установить CL (0..31) младших битов в EAX</span>
<span class="kw1">xor</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; clear all bits</span>
<span class="kw1">bts</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; set bit cl in edx</span>
<span class="kw1">dec</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; make mask of cl lower bits</span>
<span class="kw1">or</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; <span class="co1">; apply mask</span>
&nbsp;
<span class="co1">; Установить старшие биты в EAX, сохранив CL (0..31) младших</span>
<span class="kw1">or</span> <span class="kw4">edx</span><span class="sy1">,-</span><span class="nu0">1</span> &nbsp; &nbsp;<span class="co1">; set all bits</span>
<span class="kw1">btr</span> <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp;<span class="co1">; set bit cl in edx</span>
<span class="kw1">inc</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; make mask of cl lower bits</span>
<span class="kw1">or</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; <span class="co1">; apply mask</span></pre></td></tr></table></div></td></tr></tbody></table></div>Если вас интересуют манипуляции с битами, изучите набор инструкций <b>BMI1</b>, <b>BMI2</b>, которые, правда, присутствуют лишь в новых моделях процессоров Intel (начиная с Haswell).<br />
<br />
<b>Манипуляции с флагами:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="888612207"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="888612207" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Установка флага ZF=1</span>
<span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp;
<span class="co1">; Установка флага CF=1, если EAX==0 (сброс в противном случае) [Agner Fog]</span>
<span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span>
&nbsp;
<span class="co1">; Установка флага CF=1, если EAX!=0 (сброс в противном случае), флаг ZF = not CF [Agner Fog]</span>
<span class="kw1">neg</span> <span class="kw4">eax</span></pre></td></tr></table></div></td></tr></tbody></table></div><img src="https://www.cyberforum.ru/members/521524/albums/742/6290.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
<b>Оптимизация циклов:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="815867786"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="815867786" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Не используйте в критичном к скорости исполнения коде инструкцию loop, она медленнее, чем:</span>
<span class="kw1">sub</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">1</span> &nbsp;<span class="co1">; it's faster a bit than 'dec ecx'</span>
<span class="kw1">jnz</span> <span class="sy1">.</span><span class="kw1">loop</span>
<span class="co1">; Заменив jnz на ja исходное значение ECX==0 не будет порождать 2^32 циклов, цикл завершится на первом же витке</span>
<span class="co1">; (использовать 'dec ecx' при этом нельзя).</span>
<span class="co1">; Использовав jg, значение ECX будет считаться знаковым (т.е. при значении, скажем, ECX==-1 цикл не будет повторён).</span>
<span class="co1">; Использовав jnc, jge или jns можно организовать на 1 цикл больше (т.е. последний виток будет при ECX==0),</span>
<span class="co1">; при этом jnc будет считать значение ECX беззнаковым (использовать 'dec ecx' при этом нельзя), а jge и jns - знаковым.</span>
<span class="co1">; Разница между ними в том, что при исходном значении ECX==0x80000000 (уменьшенном в конце первого витка цикла до 0x7FFFFFFF)</span>
<span class="co1">; jge завершит работу, а jns - нет (при других отрицательных значениях, скажем, 0x80000001, уменьшенном до 0x80000000,</span>
<span class="co1">; работу завершат оба варианта).</span>
&nbsp;
<span class="co1">; Инструкция jecxz также медленнее, чем:</span>
<span class="kw1">test</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ecx</span>
<span class="kw1">jz</span> <span class="sy1">.</span>break</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="651207293"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="651207293" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Для организации цикла for (int i=0; i &lt; n; i++) вместо кода:</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span>N
&nbsp; <span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; <span class="co1">; i = 0</span>
<span class="sy1">.</span><span class="kw1">loop</span><span class="sy1">:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp; <span class="co1">; i &lt; N ?</span>
&nbsp; <span class="kw1">jge</span> <span class="sy1">.</span>loopend &nbsp;<span class="co1">; exit when i &gt;= N</span>
&nbsp; <span class="sy1">.</span> <span class="sy1">.</span> <span class="sy1">.</span>
&nbsp; <span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span> &nbsp; &nbsp; <span class="co1">; i++</span>
&nbsp; <span class="kw1">jmp</span> <span class="sy1">.</span><span class="kw1">loop</span> &nbsp; &nbsp; <span class="co1">; repeat</span>
<span class="sy1">.</span>loopend<span class="sy1">:</span>
&nbsp;
<span class="co1">; Лучше убрать лишнюю инструкцию jmp и написать так:</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span>N
&nbsp; <span class="kw1">test</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">jle</span> <span class="sy1">.</span>loopend &nbsp;<span class="co1">; skip if N &lt;= 0</span>
&nbsp; <span class="kw1">xor</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; <span class="co1">; i = 0</span>
<span class="sy1">.</span><span class="kw1">loop</span><span class="sy1">:</span>
&nbsp; <span class="sy1">.</span> <span class="sy1">.</span> <span class="sy1">.</span>
&nbsp; <span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span> &nbsp; &nbsp; <span class="co1">; i++</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">jl</span> <span class="sy1">.</span><span class="kw1">loop</span> &nbsp; &nbsp; &nbsp;<span class="co1">; loop if i &lt; N</span>
<span class="sy1">.</span>loopend<span class="sy1">:</span>
&nbsp;
<span class="co1">; А ещё лучше - так (если увеличивающееся значение i не используется внутри цикла):</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">ecx</span><span class="sy1">,</span>N
&nbsp; <span class="kw1">test</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">jle</span> <span class="sy1">.</span>loopend &nbsp;<span class="co1">; skip if N &lt;= 0</span>
<span class="sy1">.</span><span class="kw1">loop</span><span class="sy1">:</span>
&nbsp; <span class="sy1">.</span> <span class="sy1">.</span> <span class="sy1">.</span>
&nbsp; <span class="kw1">sub</span> <span class="kw4">ecx</span><span class="sy1">,</span><span class="nu0">1</span> &nbsp; &nbsp; <span class="co1">; N--</span>
&nbsp; <span class="kw1">jnz</span> <span class="sy1">.</span><span class="kw1">loop</span> &nbsp; &nbsp; <span class="co1">; loop if not zero</span>
<span class="sy1">.</span>loopend<span class="sy1">:</span></pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="643236028"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="643236028" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Циклы while(true) {... if (smth) break...} лучше записывать не так:</span>
<span class="sy1">.</span>next<span class="sy1">:</span>
&nbsp; <span class="kw1">call</span> A
&nbsp; <span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; break condition</span>
&nbsp; <span class="kw1">je</span> <span class="sy1">.</span>break &nbsp; &nbsp;<span class="co1">; break cycle</span>
&nbsp; <span class="kw1">call</span> B
&nbsp; <span class="kw1">jmp</span> <span class="sy1">.</span>next
<span class="sy1">.</span>break<span class="sy1">:</span>
&nbsp;
<span class="co1">; А вот так (что так же избавит цикл от лишнего jmp):</span>
&nbsp; <span class="kw1">jmp</span> <span class="sy1">.</span><span class="kw5">start</span>
<span class="sy1">.</span>next<span class="sy1">:</span>
&nbsp; <span class="kw1">call</span> B
<span class="sy1">.</span><span class="kw5">start</span><span class="sy1">:</span>
&nbsp; <span class="kw1">call</span> A
&nbsp; <span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; break condition</span>
&nbsp; <span class="kw1">jne</span> <span class="sy1">.</span>next &nbsp; &nbsp;<span class="co1">; continue if no break</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Оптимизация кол-ва ветвлений:</b><br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="357795584"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="357795584" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="de1"><pre class="de1"><span class="co1">; Оптимизация if с присваиванием в ветке then или else</span>
<span class="co1">; Вариант с использованием cmovcc уже рассматривался, поэтому давайте оптимизируем код:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edi</span> &nbsp;<span class="co1">; any condition</span>
&nbsp; <span class="kw1">jne</span> <span class="sy1">.</span>else
&nbsp; <span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">jmp</span> <span class="sy1">.</span>continue
<span class="sy1">.</span>else<span class="sy1">:</span>
&nbsp; <span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
<span class="sy1">.</span>continue<span class="sy1">:</span>
<span class="co1">; Следующим образом:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edi</span> &nbsp; <span class="co1">; any condition</span>
&nbsp; <span class="kw1">mov</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp; <span class="co1">; 'mov' doesn't change any flags</span>
&nbsp; <span class="kw1">je</span> <span class="sy1">.</span>continue
&nbsp; <span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp;
<span class="co1">; Для более сложного (чем простое присваивание) кода в then, но с коротким блоком else</span>
<span class="co1">; (размером с байт, слово или двойное слово) можно сделать так:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edi</span> &nbsp;<span class="co1">; any condition</span>
&nbsp; <span class="kw1">jne</span> <span class="sy1">.</span>else
&nbsp; <span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ebx</span>
&nbsp; <span class="kw5">db</span> <span class="nu0">0B9h</span> &nbsp; &nbsp; &nbsp;<span class="co1">; first byte of 'mov ecx,N' instruction (this is equal to 'mov ecx,?' + 'org $-4' in MASM)</span>
<span class="sy1">.</span>else<span class="sy1">:</span>
&nbsp; <span class="kw1">add</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp;<span class="co1">; 2 bytes</span>
&nbsp; <span class="kw1">inc</span> <span class="kw4">ebx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; 1 byte</span>
&nbsp; <span class="kw1">dec</span> <span class="kw4">edx</span> &nbsp; &nbsp; &nbsp;<span class="co1">; 1 byte - 4 bytes total</span>
<span class="co1">; Поясню: блок else занимает ровно 4 байта, значит блок then можно завершить не инструкцией 'jmp .continue',</span>
<span class="co1">; а инструкцией 'mov ecx,N', которая &quot;поглотит&quot; эти 4 байта (т.к. именно они будут записаны внутри</span>
<span class="co1">; 'mov ecx,N' в качестве присваиваемого значения) - это работает быстрее</span>
&nbsp;
<span class="co1">; Предположим, нам необходимо выйти из цикла при значениях EAX==0 или EAX==1, но перейти необходимо по разным адресам</span>
<span class="co1">; Вместо кода:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span>
&nbsp; <span class="kw1">jb</span> <span class="sy1">.</span>eax_zero
&nbsp; <span class="kw1">je</span> <span class="sy1">.</span>eax_one
<span class="co1">; Лучше написать:</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span>
&nbsp; <span class="kw1">jbe</span> <span class="sy1">.</span>eax_zero
&nbsp; <span class="sy1">.</span> <span class="sy1">.</span> <span class="sy1">.</span>
<span class="sy1">.</span>eax_zero<span class="sy1">:</span>
&nbsp; <span class="kw1">je</span> <span class="sy1">.</span>eax_one
<span class="co1">; Тем самым мы уменьшим кол-во условных инструкций внутри цикла (ведь весь код в нём повторяется многократно)</span>
<span class="co1">; с 2 до 1, а проверку на значение 0 или 1 вынесем наружу</span>
&nbsp;
<span class="co1">; Выход из цикла при значении EAX == 0 или EBX &gt; ECX</span>
<span class="co1">; Вместо кода:</span>
&nbsp; <span class="kw1">test</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp; <span class="kw1">jz</span> <span class="sy1">.</span>break
&nbsp; <span class="kw1">cmp</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">ja</span> <span class="sy1">.</span>break
<span class="co1">; Можно написать:</span>
&nbsp; <span class="kw1">test</span> <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp; <span class="kw1">setz</span> <span class="kw4">dl</span> &nbsp; &nbsp; &nbsp; <span class="co1">; = (eax==0) ? 1 : 0</span>
&nbsp; <span class="kw1">cmp</span> <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ecx</span>
&nbsp; <span class="kw1">seta</span> <span class="kw4">dh</span> &nbsp; &nbsp; &nbsp; <span class="co1">; = (ebx&gt;ecx) ? 1 : 0</span>
&nbsp; <span class="kw1">or</span> <span class="kw4">dl</span><span class="sy1">,</span><span class="kw4">dh</span> &nbsp; &nbsp; &nbsp;<span class="co1">; zf = not (eax==0 || ebx&gt;ecx)</span>
&nbsp; <span class="kw1">jnz</span> <span class="sy1">.</span>break
<span class="co1">; Так можно объединить любое кол-во условий и использовать одну инструкцию условного перехода внутри цикла вместо нескольких.</span>
<span class="co1">; Но опять же, используя подобные трюки, тестируйте код, поскольку они могут наоборот привести к замедлению!</span>
<span class="co1">; К примеру, пытаясь таким образом оптимизировать 3 условных перехода в алгоритме быстрого вычисления НОД,</span>
<span class="co1">; я обнаружил, что &quot;оптимизированный&quot; вариант работает дольше (по крайней мере, на моём компьютере).</span>
<span class="co1">; Попытка оптимизировать 2 условных перехода так же не привела к успеху, поэтому я оставил все 3.</span>
<span class="co1">; В другом же коде такая оптимизация привела к ускорению.</span></pre></td></tr></table></div></td></tr></tbody></table></div>Если вы поймёте принцип всех этих манипуляций, то сможете модифицировать приведённый выше код под необходимые вам условия.<br />
Тем не менее, используя эти трюки, призываю вас тестировать их на <i>реальном коде</i> (по возможности, на разных процессорах). В некоторых случаях код с ветвлением может оказаться быстрее, а использование инструкций <code class="inlinecode">cmovcc</code> хоть и короче, но бывает медленнее более длинных алгоритмов без их использования.<br />
<br />
Всех, кто интересуется оптимизацией, рекомендую посетить сайт <a rel="nofollow noopener noreferrer" href="http://agner.org/optimize/" target="_blank" title="http://agner.org/optimize/">Агнера Фога</a>, известного эксперта по оптимизации, и почитать его статьи и электронные книги.<br />
Кроме того, рекомендую изучить полный <a rel="nofollow noopener noreferrer" href="https://software.intel.com/en-us/articles/intel-sdm#three-volume" target="_blank" title="https://software.intel.com/en-us/articles/intel-sdm#three-volume">набор инструкций процессоров Intel</a> (да и вообще архитектуру современных процессоров), чтобы максимально эффективно использовать все возможности технического прогресса :)<br />
<br />
p.s. Присылайте в комментариях к этой статье другие трюки, о которых вы знаете (желательно с комментариями), и я добавлю их в этот список (но только если они будут касаться оптимизации <i>ветвлений</i>, всё остальное – в других статьях). Также пишите о найденных неточностях и о том, как можно оптимизировать этот код ещё сильнее ;)<br />
<br />
p.p.s. Буду так же рад любому качественному материалу (ссылкам) про оптимизацию.<br />
<br />
Эта и другие <a href="https://www.cyberforum.ru/assembler/thread2184145.html">мои статьи на форуме</a>.</div>

]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5122.html</guid>
		</item>
		<item>
			<title>Реально быстрый алгоритм вычисления НОД</title>
			<link>https://www.cyberforum.ru/blogs/521524/5121.html</link>
			<pubDate>Fri, 02 Feb 2018 23:24:38 GMT</pubDate>
			<description>*Реально быстрый алгоритм вычисления НОД* 
 
Основными популярными алгоритмами вычисления...</description>
			<content:encoded><![CDATA[<div><div align="center"><font color="Navy"><font size="5"><b>Реально быстрый алгоритм вычисления НОД</b></font></font></div><br />
Основными популярными алгоритмами вычисления наибольшего общего делителя (НОД) являются <b>алгоритм Евклида</b> и <b>бинарный алгоритм</b>. Первый очень простой и компактный, второй – якобы быстрый, поскольку в нём отсутствуют &quot;долгие&quot; операции деления, а присутствуют лишь операции сдвига. Однако на практике бинарный алгоритм зачастую работает раза в 2(!) медленнее алгоритма Евклида, поскольку в нём присутствует довольно много операций ветвления. Описанные в различных источниках бинарные алгоритмы вычисления НОД (в т.ч. в <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/Бинарный_алгоритм_вычисления_НОД" target="_blank" title="https://ru.wikipedia.org/wiki/Бинарный_алгоритм_вычисления_НОД">Википедии</a>) подразумевают единичные операции на каждом цикле итерации и кучу проверок. По факту же за одну итерацию можно совершить сразу группу операций (сдвигов). Для тех, кто знает, как работает этот алгоритм, поясню, что сдвиг (деление пополам) можно производить безо всяких лишних проверок до тех пор, пока каждое из чисел не станет нечётным. После этого уже можно сделать сравнение значений с единицей, а далее (при отсутствии единицы) – нахождение разницы полученных нечётных значений с делением пополам и повтор цикла. Проверку же на 0 достаточно сделать 1 раз в самом начале.<br />
<br />
<div align="center"><img src="https://www.cyberforum.ru/members/521524/albums/742/6291.jpg" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></div><br />
А вот, собственно, и сам код (на <b>fasm</b>):<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="858216094"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="858216094" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="de1"><pre class="de1"><span class="co1">; (c) 2018 by Jin X</span>
<span class="co1">; Return GCD of val1 and val2 in EAX (binary algorithm, no recursion calls)</span>
<span class="co1">; val1 and val2 are treated as unsigned</span>
proc &nbsp; &nbsp;FastGCD uses <span class="kw4">ebx</span> <span class="kw4">esi</span> <span class="kw4">edi</span><span class="sy1">,</span> val1<span class="sy1">,</span> val2
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">edx</span><span class="sy1">,</span><span class="br0">&#91;</span>val2<span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#91;</span>val1<span class="br0">&#93;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">test</span> &nbsp; &nbsp;<span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jz</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val1noshift &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; if val2 = 0 return val1</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">xor</span> &nbsp; &nbsp; <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; bl = left shift count before return (result must be multiplied by 2^bl)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">test</span> &nbsp; &nbsp;<span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jz</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; if val1 = 0 return val2</span>
&nbsp;
&nbsp; &nbsp; <span class="sy1">.</span>next<span class="sy1">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">bsf</span> &nbsp; &nbsp; <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">eax</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; esi = count of lower zero bits in val1</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">bsf</span> &nbsp; &nbsp; <span class="kw4">edi</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; edi = count of lower zero bits in val2</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">esi</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">shr</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">cl</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; shift val1 right until it will be odd</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">edi</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">shr</span> &nbsp; &nbsp; <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">cl</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; shift val2 right until it will be odd</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmp</span> &nbsp; &nbsp; <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edi</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmova</span> &nbsp; <span class="kw4">esi</span><span class="sy1">,</span><span class="kw4">edi</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; esi = min(esi,edi)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">add</span> &nbsp; &nbsp; <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">esi</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; add this number to ebx (bl)</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmp</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">je</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; if val1 = 1 return 1 (val1)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmp</span> &nbsp; &nbsp; <span class="kw4">edx</span><span class="sy1">,</span><span class="nu0">1</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">je</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; if val2 = 1 return 1 (val2)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmp</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">je</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; if val1 = val2 return val1</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmovb</span> &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cmovb</span> &nbsp; <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; swap val1 and val2 if val1 &lt; val2</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">sub</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">shr</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="nu0">1</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; val1 = (val1-val2)/2</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jmp</span> &nbsp; &nbsp; <span class="sy1">.</span>next &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; go to next iteration</span>
&nbsp;
&nbsp; &nbsp; <span class="sy1">.</span>val2<span class="sy1">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; eax = val2</span>
&nbsp; &nbsp; <span class="sy1">.</span>val1<span class="sy1">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">ebx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">shl</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">cl</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; multiple result (eax) by 2^bl</span>
&nbsp; &nbsp; <span class="sy1">.</span>val1noshift<span class="sy1">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">ret</span>
endp</pre></td></tr></table></div></td></tr></tbody></table></div>Приведу заодно и реализацию алгоритма Евклида:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="118922656"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="118922656" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="co1">; (c) 2018 by Jin X</span>
<span class="co1">; Return GCD of val1 and val2 in EAX (Euclid algorithm, no recursion calls)</span>
<span class="co1">; val1 and val2 are treated as unsigned</span>
proc &nbsp; &nbsp;EuclidGCD val1<span class="sy1">,</span> val2
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#91;</span>val1<span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="br0">&#91;</span>val2<span class="br0">&#93;</span>
&nbsp; &nbsp; @@<span class="sy1">:</span> <span class="kw1">jecxz</span> &nbsp; @F &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; return val1 if val2 = 0</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">xor</span> &nbsp; &nbsp; <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">div</span> &nbsp; &nbsp; <span class="kw4">ecx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; eax = val1 / val2; edx = val1 % val2 (replace this instruction by 'idiv' and previous one by 'cdq' to treat val1 and val2 as signed)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; eax = val2</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; ecx = edx = val1 % val2</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jmp</span> &nbsp; &nbsp; @B
&nbsp; &nbsp; @@<span class="sy1">:</span> <span class="kw1">ret</span>
endp</pre></td></tr></table></div></td></tr></tbody></table></div>(замечу, что при внесении описанных в комментариях изменений в алгоритм Евклида для работы с отрицательными числами результат может быть отрицательным при отрицательном значении одного или обеих параметров... в прикреплённом архиве есть signed-функция, которая выполняет приведение результата к абсолютному значению).<br />
<br />
<b>Скорость работы бинарного алгоритма выше алгоритма Евклида примерно на 35-40%</b> (на моём компьютере с процессором Intel Core i5-2500K @ 3.7 ГГц). Для кого-то это может показаться несущественным, поэтому алгоритм Евклида вполне имеет право на жизнь :). Кроме того, справедливости ради хочу сказать, что в алгоритме Евклида отсутствуют инструкции <code class="inlinecode">cmovcc</code>, требующие процессора Pentium Pro+ (правда, сейчас трудно найти более слабый процессор), без которых скорость алгоритма значительно снизится. К тому же, бинарный алгоритм не может работать с отрицательными числами (даже если заменить <code class="inlinecode">shr</code> на <code class="inlinecode">sar</code>), хотя этот вопрос легко решается заменой первых инструкций (до метки <code class="inlinecode">.next</code>) на следующие, приводящие оба числа к абсолютному (положительному) значению:<br />
<div class="codeblock"><table class="asm"><thead><tr><td colspan="2" id="514477610"  class="head">Assembler</td></tr></thead><tbody><tr class="li1"><td><div id="514477610" style="height: 286px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#91;</span>val2<span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cdq</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">xor</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">sub</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; eax = abs(eax)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">ecx</span><span class="sy1">,</span><span class="kw4">eax</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">xor</span> &nbsp; &nbsp; <span class="kw4">ebx</span><span class="sy1">,</span><span class="kw4">ebx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; bl = left shift count before return (result must be multiplied by 2^bl)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="br0">&#91;</span>val1<span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">cdq</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">xor</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">sub</span> &nbsp; &nbsp; <span class="kw4">eax</span><span class="sy1">,</span><span class="kw4">edx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; eax = abs(eax) = |val1|</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">mov</span> &nbsp; &nbsp; <span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">ecx</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; edx = |val2|</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jz</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">; if val1 = 0 return |val2|</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">test</span> &nbsp; &nbsp;<span class="kw4">edx</span><span class="sy1">,</span><span class="kw4">edx</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">jz</span> &nbsp; &nbsp; &nbsp;<span class="sy1">.</span>val1noshift &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">; if val2 = 0 return |val1|</span></pre></td></tr></table></div></td></tr></tbody></table></div>При этом скорость работы алгоритма падает лишь на 1-2% :)<br />
<br />
Прикрепляю к статье архив с исходниками и программами для теста корректности и скорости работы алгоритмов.<br />
Наслаждайтесь ;)<br />
<br />
Эта и другие <a href="https://www.cyberforum.ru/assembler/thread2184145.html">мои статьи на форуме</a>.<br />
<br />
<hr style="height:1px;border:0;color:#909090;background:#909090" /><br />
<font color="Red"><b>Updated 03.02.2018:</b></font><ul><li>Внёс небольшие изменения в код signed-функции, а также добавил архивчик <b>GCDX.zip</b> с немного изменёнными заголовками функций для обоих алгоритмов (стандартные прологи/эпилоги вырезаны и оптимизированы).</li>
<li><font color="Red">Через пару часов:</font> добавил ещё одну версию (<b>GCD386.zip</b>), без инструкций <code class="inlinecode">cmovcc</code>, т.е. работающую на любом 386+ процессоре. Этот код медленнее на 10-13%, но всё равно быстрее алгоритма Евклида.</li>
</ul><font color="Red"><b>Updated 09.02.2018:</b></font><ul><li>Исправлен небольшой косяк в <b>GCD.zip</b>: вместо <code class="inlinecode">cinvoke</code> использовался <code class="inlinecode">invoke</code>.</li>
</ul><br />
<font color="Navy"><i>p.s. Тестовые программы есть только в архиве <b>GCD.zip</b> !!!</i></font></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4665&amp;d=1517655429">GCDX.zip</a> (2.7 Кб, 475 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4666&amp;d=1517655429">GCD386.zip</a> (1.6 Кб, 499 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4667&amp;d=1518201633">GCD.zip</a> (14.3 Кб, 422 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Jin X</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/521524/5121.html</guid>
		</item>
	</channel>
</rss>
