<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Блоги: заметки с тегом программирование</title>
<link>https://blogengine.ru/blogs/tags/programmirovanie/</link>
<description>Автоматически собираемая лента заметок, написанных в блогах на Эгее</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.0 (v4079e)</generator>

<itunes:subtitle>Автоматически собираемая лента заметок, написанных в блогах на Эгее</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>Утилита cdecl</title>
<guid isPermaLink="false">137604</guid>
<link>https://bolknote.ru/all/utilita-cdecl/</link>
<pubDate>Tue, 30 Sep 2025 11:27:05 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/utilita-cdecl/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Какая интересная утилита есть, оказывается, а я и не знал! Позволяет по любой декларации типа в языке Си получить описание на английском или наоборот — свернуть такое описание в тип. Вот примеры:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="cpp"&gt;cdecl&amp;gt; explain char *(* const volatile (*(*hydra)(int (*)(void), char * const * restrict))[13]) (unsigned long, char * const [static 3]);
declare hydra as pointer to function (pointer to function (void) returning integer, restricted pointer to constant pointer to character) returning pointer to array 13 of constant volatile pointer to function (unsigned long integer, non-empty array 3 of constant pointer to character) returning pointer to character

cdecl&amp;gt; declare fp as pointer to function (pointer to char) returning pointer to array of pointer to char
char* (*(*fp)(char*))[];&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>Модели BitNet</title>
<guid isPermaLink="false">137592</guid>
<link>https://bolknote.ru/all/modeli-bitnet/</link>
<pubDate>Sun, 28 Sep 2025 14:20:57 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/modeli-bitnet/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Эксперементировал сегодня ночью с моделями &lt;i&gt;BitNet&lt;/i&gt;. Это небольшие (1—2 миллиарда параметров) модели очень низкой битности — 1,58 бит. Причём это не квантизация, они сразу так обучены. Интересны тем, что работают настолько быстро, что их можно запускать без графических ускорителей.&lt;/p&gt;
&lt;p&gt;Было интересно посмотреть с какими типами задач они способны справиться.&lt;/p&gt;
&lt;p&gt;Давал несложные задачи генерации текста, выделения сущностей, классификации, перевода с английского на русский, написания эскуэля, но что-то не нащупал область применения. Везде она кое-как справляется, но неудовлетворительно — чаще не решает задачу, чем решает.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.09.28.1@2x.webp" width="1000" height="350" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;На скриншоте у меня задача по написанию крайне простого эскуэля. Выглядит хорошо, задача решена, но это верхний предел этой модели — если дать ещё одну таблицу, всё сыпется в половине моих тестов. А если в задачу добавить ещё и &lt;tt&gt;LEFT JOIN&lt;/tt&gt;, то тесты не проходят вообще — модель ни разу ничего адекватного не написала даже с очень детальными подсказками.&lt;/p&gt;
&lt;p&gt;Поразительно, конечно, что сети такой низкой битности вообще как-то работают и даже иногда дают какой-то осмысленный результат, но куда бы их можно было применить — мне решительно непонятно.&lt;/p&gt;
</description>
</item>

<item>
<title>Ошмётки в консоли</title>
<guid isPermaLink="false">137570</guid>
<link>https://bolknote.ru/all/oshmyotki-v-konsoli/</link>
<pubDate>Fri, 26 Sep 2025 00:30:42 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/oshmyotki-v-konsoli/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Как известно, много лет назад «Эпл» перешла с процессоров «Интел» на собственные, основанные на архитектуре «АРМ». Процессоры несовместимы, однако бинарные программы, скомпилированные под «Интел», продолжают работать — в «МакОС» встроен специальный транслятор, который обеспечивает такую возможность.&lt;/p&gt;
&lt;p&gt;Много лет я таскаю с собой различные утилиты, которые при переходе с одного «Макбука» на другой автоматически копируются при помощи встроенной в ОС процедуры миграции. Однако некоторое время назад я занялся тем, что с помощью &lt;tt&gt;brew&lt;/tt&gt; перевёл всё это бинарное хозяйство на «АРМ».&lt;/p&gt;
&lt;p&gt;По пути у меня что-то неприятно сломалось — иногда, при редактировании командной строки, всё странно съезжало, части текста наезжали друг на друга и невозможно было понять какая команда получится в итоге.&lt;/p&gt;
&lt;p&gt;Я всю голову сломал, пытаясь понять что же произошло, даже переставил себе &lt;i&gt;iTerm2&lt;/i&gt;, думал дело в нём, но не помогло. Подумал, что может у меня что-то такое погружается при старте терминала, что всё ломает. В итоге стал отключать команды по одной строке в &lt;tt&gt;.bash_profile&lt;/tt&gt;, пока не отключил строку с переменной &lt;tt&gt;PS1&lt;/tt&gt;, задающей вид приглашения перед вводом программы, и всё стало нормально работать.&lt;/p&gt;
&lt;p&gt;Тут я каким-то образом догадался, что дело в кодах, задающих цвет приглашения. Спросил у ЧатаГПТ и тот подтвердил мою догадку.&lt;/p&gt;
&lt;p&gt;Оказывается библиотека &lt;tt&gt;readline&lt;/tt&gt;, отвечающая за редактирование текста в командной строке, неправильно считает длину строки, если в ней есть управляющие символы, — например, задающие цвет. Чтобы всё работало как надо, их надо обрамлять специальными последовательностями &lt;tt&gt;\[&lt;/tt&gt; и &lt;tt&gt;\]&lt;/tt&gt;. Если я когда-то это и знал, то успел прочно забыть.&lt;/p&gt;
&lt;p&gt;В общем, я заменил приглашение с&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="bash"&gt;PS1=&amp;#039;\e[33;1m\u: \e[31m\W$(__git_ps1)\e[0m \$ &amp;#039;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;на&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="bash"&gt;PS1=&amp;#039;\[\e[33;1m\]\u:\[\e[0m\] \[\e[31m\]\W$(__git_ps1)\[\e[0m\] \$ &amp;#039;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;и всё заработало как надо.&lt;/p&gt;
</description>
</item>

<item>
<title>Имя-эксплоит</title>
<guid isPermaLink="false">137553</guid>
<link>https://bolknote.ru/all/imya-eksploit/</link>
<pubDate>Wed, 24 Sep 2025 20:05:13 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/imya-eksploit/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Читал недавно про &lt;a href="https://ru.wikipedia.org/wiki/Вольф%2B585_старший"&gt;человека&lt;/a&gt;, сейчас уже покойного, фамилия которого состояла из более чем &lt;i&gt;шести сотен&lt;/i&gt; букв.&lt;/p&gt;
&lt;p&gt;В газете «&lt;i&gt;The Free Lance-Star&lt;/i&gt;» за 25 июня 1964 года можно найти о нём заметку, где утверждается, что его фамилия настолько длинная, что компьютер &lt;i&gt;IBM 7074&lt;/i&gt; страховой компании «&lt;i&gt;John Hancock Mutual Life Insurance&lt;/i&gt;» завис («&lt;i&gt;stops dead&lt;/i&gt;») при её обработке и полис пришлось оформлять вручную.&lt;/p&gt;
&lt;p&gt;Я, конечно, сразу вспомнил известный комикс &lt;i&gt;XKCD&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;И хотя история вполне вероятная, — не исключено, что в программе не проверялись границы буфера при вводе фамилии и это послужило причиной зависания, всё же я думаю, что это журналистское преувеличение и в реальности проблема была в том, что столь длинная строка просто не поместилась в нужное поле.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.09.24@2x.webp" width="740" height="228" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Если кому интересно, то согласно «Книге рекордов Гиннеса», его звали так:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Zeus Wolfeschlegelsteinhausen­bergerdorff­welche­vor­altern­waren­gewissenhaft­schafers­wessen­schafe­waren­wohl­gepflege­und­sorgfaltigkeit­beschutzen­von­angreifen­durch­ihr­raubgierig­feinde­welche­vor­altern­zwolf­tausend­jahres­voran­die­erscheinen­van­der­erste­erdemensch­der­raumschiff­gebrauch­licht­als­sein­ursprung­von­kraft­gestart­sein­lange­fahrt­hinzwischen­sternartig­raum­auf­der­suchen­ach­die­stern­welche­gehabt­bewohnbar­planeten­kreise­drehen­sich­und­wohin­der­neu­rasse­von­verstandig­menschlichkeit­konnte­fortpflanzen­und­sich­erfreuen­an­lebenslanglich­freude­und­ruhe­mit­nicht­ein­furcht­vor­angreifen­von­anderer­intelligent­geschopfs­von­hinzwischen­sternartig­raum.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
</item>

<item>
<title>Какой RLE лучше-2</title>
<guid isPermaLink="false">137547</guid>
<link>https://bolknote.ru/all/kakoy-rle-luchshe-2/</link>
<pubDate>Tue, 23 Sep 2025 23:58:53 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/kakoy-rle-luchshe-2/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Какое-то время назад я сравнивал два разных алгоритма сжатия &lt;i&gt;RLE&lt;/i&gt;. Один вспомнил сам, а второй прислал один из читателей.&lt;/p&gt;
&lt;p&gt;Они по-разному устроены, но оба используют для сжатия простой принцип — вместо повторяющейся последовательности записывать её длину. Я тогда &lt;a href="https://bolknote.ru/all/kakoy-rle-luchshe/"&gt;написал небольшой скрипт&lt;/a&gt; на Пайтоне, чтобы сравнить эти два алгоритма на бинарных файлах в моей папке «Загрузки» и посмотреть что получится.&lt;/p&gt;
&lt;p&gt;Оказалось, что более сложным алгоритмом я кодирую неправильно, так как в нём потенциально есть несколько стратегий кодирования одной и той же последовательности, чего я не увидел и не учёл в своей программе. На это мне попенял читатель, который мне когда-то и прислал этот алгоритм.&lt;/p&gt;
&lt;p&gt;У меня всё никак не доходили руки аккуратно переписать свой скрипт, чтобы учесть замечание, но сегодня я не вытерпел и сделал некрасиво, практически перебором. Правда двухбайтный счётчик повторов делать не стал, наверное он тоже повлиял бы, но пока что-то времени нет дописать это место.&lt;/p&gt;
&lt;p&gt;В общем, новые результаты такие. Использовал на той же папке, что и в прошлый раз, но с той поры её состав немного поменялся. Алгоритм, который вспомнил я, лучше сжал 440 файлов, который предложил читатель — 4159, не удалось сжать вообще — 2507 файлов.&lt;/p&gt;
&lt;p&gt;Прежний результат был такой: 1811 лучше сжал «мой» алгоритм, 2152 — читательский, в 3193 случаях не справился ни один из алгоритмов.&lt;/p&gt;
&lt;p&gt;В общем, соотношение сильно изменилось.&lt;/p&gt;
</description>
</item>

<item>
<title>Что послушать — 83</title>
<guid isPermaLink="false">137468</guid>
<link>https://ilyabirman.ru/meanwhile/all/listening-83/</link>
<pubDate>Wed, 17 Sep 2025 14:28:38 +0500</pubDate>
<author>Илья Бирман</author>
<comments>https://ilyabirman.ru/meanwhile/all/listening-83/</comments>
<description>
&lt;p&gt;&lt;a href="https://ilyabirman.ru/meanwhile/"&gt;Илья Бирман&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Всё, что можно слушать, &lt;a href="https://ilyabirman.ru/meanwhile/all/layfhak-pro-slushanie-lekciy-i-dokladov/"&gt;я стараюсь слушать&lt;/a&gt;, а не читать и не смотреть. Потому что когда у меня свободны глаза, я предпочитаю делать что-то более полезное.&lt;/p&gt;
&lt;p&gt;Вот что я слушал в последнее время, что мне понравилось:&lt;/p&gt;
&lt;ol start="1"&gt;
  &lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=vagyIcmIGOQ"&gt;Дэвид Хайнемайер Хенсон у Лекса Фридмана&lt;/a&gt;. Всё правильно и про программирование, и про бизнес, и про отношение к жизни, а также интересно про гонки, особенно после того, как посмотришь эпловскую «Формулу 1».&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://overcast.fm/+ABD4yYAS3fM"&gt;What To Do When The World Is Falling Apart&lt;/a&gt;. Недавно открыл для себя такого классного ютюбера-психотерапевта. Тут он отлично прочищает мозги людям со взглядами типа «мир нам всё должен» вместо того, чтобы начать самостоятельно чё-то решать.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://atp.fm/644"&gt;ATP 644: You Have to Invert&lt;/a&gt;. В этом выпуске любимого подкаста АТП обсуждают новый дизайн Макоса, и там много классного, особенно речь Сиракьюсы о том, как тупо отрывать панели от краёв экрана в районе 1:08.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://daringfireball.net/thetalkshow/2025/07/31/ep-428"&gt;The Talk Show 428: Michigan-Starred Fine Dining&lt;/a&gt;. А это выпуск шоу Джона Грубера, где они с гостем Луи Мантией ситуацию с дизайном интерфейсов в Эпле и тот факт, что у Алана Дая, оказывается, даже нет образования на эту тему.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=5KmpT-BoVf4"&gt;Сэм Альтман о боге, Илоне Маске и загадочной смерти своего бывшего сотрудника&lt;/a&gt;. Интервью Такера Карлсона! Ребята стоят друг друга, конечно.&lt;/li&gt;
&lt;/ol&gt;
</description>
</item>

<item>
<title>Какой RLE лучше?</title>
<guid isPermaLink="false">137366</guid>
<link>https://bolknote.ru/all/kakoy-rle-luchshe/</link>
<pubDate>Thu, 11 Sep 2025 14:01:52 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/kakoy-rle-luchshe/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;У меня тут в комментариях на сайте &lt;a href="https://bolknote.ru/all/rle-v-bzip2/"&gt;интересная дискуссия&lt;/a&gt; развернулась — есть ли преимущество у реализации &lt;i&gt;RLE&lt;/i&gt;, которую я описывал, по сравнению с другим алгоритмом, который вспомнил один из читателей.&lt;/p&gt;
&lt;p&gt;Для меня вполне очевидно, что на разных данных каждый из них может выиграть. Но что насчёт реальной жизни?&lt;/p&gt;
&lt;p&gt;Я написал небольшую программу на Пайтоне, которая считает сколько занял бы файл, если его сжимать каждым из алгоритмов, а потом прогнал её на каждой из 7000+ файлов в моей папке «Загрузки».&lt;/p&gt;
&lt;p&gt;Какой же итог? В 1811 случаях выиграл алгоритм, который вспомнил я, в 2152 — который вспомнил читатель, в 3193 случаях оба алгоритма сделали только хуже — файл стал длиннее.&lt;/p&gt;
&lt;p&gt;В итоге, если бы мы писали утилиту для сжатия, можно было бы использовать все три метода (включая сохранение файла в исходном виде), указав в начале файла кодовый байт означающий метод сжатия.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="python"&gt;from itertools import groupby
from math import ceil
import os
import sys

try:
    filename = sys.argv[1]
except IndexError:
    filename = __file__

def reader(filepath):
    with open(filepath, &amp;quot;rb&amp;quot;) as f:
        while chunk := f.read(4096): yield from chunk

def mark(x, y):
    if x == y: return (x, y)

    c1, c2 = (32, 31) if x &amp;lt; y else (31, 32)
    return (f&amp;#039;\x1B[{c1}m{x:+d}&amp;#039;, f&amp;#039;\x1B[{c2}m{y:+d}&amp;#039;)

flen = os.path.getsize(filename)

grouped_same = (tuple(x[1]) for x in groupby(reader(filename)))
chains = groupby(grouped_same, lambda it: len(it) == 1 or object())

bolk = maks = 0

for diff, x in chains:
    x = tuple(x) if diff is True else tuple(x)[0]
    l = len(x)

    if diff is True:
        bolk  += l                       #                {x} {y} {z}…
        maks  += l + ceil(l / (128 + 1)) # {l &amp;amp; 0x7F - 1} {x} {y} {z}…
    else:
        bolk  += (2 + 1) * ceil(l / (255 + 2)) # {x}            {x} {l}
        maks  += (1 + 1) * ceil(l / (128 + 2)) # {l &amp;amp; 0x7F - 2} {x}


bdiff, mdiff = mark(bolk - flen, maks - flen)

print(f&amp;#039;Len\t{flen}&amp;#039;)
print(f&amp;quot;Bolk&amp;#039;s\t{bolk}\t{bdiff}\x1B[0m&amp;quot;)
print(f&amp;quot;Maks&amp;#039;\t{maks}\t{mdiff}\x1B[0m&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;i&gt;Добавлено позднее&lt;/i&gt;: в комментариях есть замечания к реализации, которые я &lt;a href="https://bolknote.ru/all/kakoy-rle-luchshe-2/"&gt;учёл позднее&lt;/a&gt;.&lt;/p&gt;
</description>
</item>

<item>
<title>RLE в bzip2</title>
<guid isPermaLink="false">137349</guid>
<link>https://bolknote.ru/all/rle-v-bzip2/</link>
<pubDate>Wed, 10 Sep 2025 00:10:58 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/rle-v-bzip2/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Очень меня поразил тот факт, что внутри очень эффективного архиватора &lt;tt&gt;bzip2&lt;/tt&gt; &lt;a href="https://habr.com/ru/companies/kts/articles/937554/"&gt;работает алгоритм &lt;i&gt;RLE&lt;/i&gt;&lt;/a&gt;. Да, после очень хитрых перестановок данных, но &lt;i&gt;RLE&lt;/i&gt;!&lt;/p&gt;
&lt;p&gt;Это очень простое семейство алгоритмов сжатия, с которым я познакомился ещё в то время, когда у меня был «Спектрум».&lt;/p&gt;
&lt;p&gt;У него может быть много разных реализаций, но та, что я тогда программировал, выглядела следующим образом.&lt;/p&gt;
&lt;p&gt;Последовательности одинаковых значений мы кодируем как один и тот же байт, записанный дважды, плюс счётчик — сколько таких байтов надо дописать; остальное оставляем как есть.&lt;/p&gt;
&lt;p&gt;Например:&lt;/p&gt;
&lt;p&gt;01 02 &lt;tt&gt;03 03 03 03 03 03 03&lt;/tt&gt; &lt;tt&gt;04 04 04&lt;/tt&gt; → 01 02 &lt;tt&gt;03 03&lt;/tt&gt; &lt;tt&gt;05&lt;/tt&gt; &lt;tt&gt;04 04&lt;/tt&gt; &lt;tt&gt;01&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Как я уже написал, могут быть варианты. Например, можно счётчик делать больше, чем один байт или записывать количество повторений около каждого байта, всё зависит от характера сжимаемых данных, но суть плюс-минус одна и та же.&lt;/p&gt;
&lt;p&gt;И как-то похожий простой алгоритм трудится внутри &lt;tt&gt;bzip2&lt;/tt&gt;! Мне кажется, этому нельзя не изумиться!&lt;/p&gt;
</description>
</item>

<item>
<title>MS-DOS Siberian edition</title>
<guid isPermaLink="false">137327</guid>
<link>https://bolknote.ru/all/ms-dos-syberian-edition/</link>
<pubDate>Sun, 07 Sep 2025 18:35:26 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/ms-dos-syberian-edition/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Думаю на Земле живёт очень мало людей, которые хоть раз компилировали бы &lt;i&gt;MS-DOS&lt;/i&gt;. Теперь в этот клуб с сомнительными бенефитами влился и я, тем более, что «Микрософт» выложила исходники этой операционной системы по четвёртую версию.&lt;/p&gt;
&lt;p&gt;Вроде там утекли и более свежие версии, но зачем нарушать закон, если всё равно какую версию собирать?&lt;/p&gt;
&lt;p&gt;Собирал я её с одной-единственной целью — в голове засела мысль, что раз сибиряки называют канцелярский файл «мультифорой», то и на файловой системе операционной системы для Сибири все файлы должны быть «мультифорами».&lt;/p&gt;
&lt;p&gt;Теперь у меня есть «&lt;i&gt;MS-DOS Siberian edition&lt;/i&gt;» — до компиляции поправил в исходниках несколько строк и все файлы теперь при выводе теперь называются понятным сибирякам термином.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.09.07.1@2x.webp" width="690" height="450" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;i&gt;Дополнено&lt;/i&gt;: дважды ошибся — &lt;i&gt;Syberia&lt;/i&gt; вместо &lt;i&gt;Siberian&lt;/i&gt; и &lt;i&gt;vikhorka&lt;/i&gt; вместо &lt;i&gt;vikhotka&lt;/i&gt;. Первое понятно — так называлась игра, которую у нас перевели как «Сибирь», вот у меня и застряло, а второе вспомнил неправильно — больше десяти лет не слышал этого слова.&lt;/p&gt;
</description>
</item>

<item>
<title>Ковыряю bc</title>
<guid isPermaLink="false">136673</guid>
<link>https://bolknote.ru/all/kovyryayu-bc/</link>
<pubDate>Fri, 18 Jul 2025 00:25:53 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/kovyryayu-bc/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Ковырял сегодня &lt;tt&gt;bc&lt;/tt&gt; на досуге, ту версию, которая помощнее. Что-то не очень мне нравится как он написан. Я добавлял в язык одну конструкцию и одну функцию. Конструкцию удалось добавить быстро, а с функцией я возился не один час.&lt;/p&gt;
&lt;p&gt;На скриншоте — количество мест, в которые пришлось её прописать. И только в одном из этих мест хранится её реализация. Взял за образец другие объявленные функции, поэтому не имею не малейшего понятия почему так много где пришлось её прописывать, не успел разобраться.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.07.17@2x.webp" width="1000" height="231" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Лучше расскажу что именно я придумал добавить в язык. В &lt;tt&gt;bc&lt;/tt&gt; есть несколько глобальных переменных, которые очень много на что влияют. Две, наверное, самые важные — это &lt;tt&gt;ibase&lt;/tt&gt; и &lt;tt&gt;scale&lt;/tt&gt;. Очень часто их приходится сохранять в начале и восстанавливать в конце своих функций, особенно библиотечных.&lt;/p&gt;
&lt;p&gt;У более продвинутого &lt;tt&gt;bc&lt;/tt&gt; есть специальный ключ, который, если его указать, меняет это поведение — при входе в каждую функцию значения этих и других глобальных переменных будут записываться в специальный стек, а на выходе — восстанавливаться оттуда.&lt;/p&gt;
&lt;p&gt;Но библиотечные функции, всё одно, пишут, для универсальности, не рассчитывая на то, что этот флаг установлен. Вот, например, библиотечная функция косинуса:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="cpp"&gt;define c(x){
    auto b,s
    b=ibase
    ibase=A
    s=scale
    scale*=1.2
    x=s(2*a(1)+x)
    scale=s
    ibase=b
    return(x/1)
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Вот я и подумал, чтобы бы неплохо придумать директиву, при указании которой такой стек, для помеченной ею функции, всегда включался бы; а кроме того, была бы полезна функция, которая восстановила бы значения глобальных переменных ещё до выхода из функции. Иногда это необходимо, чтобы вернуть число в соответствии с установленными в них параметрами.&lt;/p&gt;
&lt;p&gt;Функция косинуса с этими новыми возможностями выглядела бы так:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="cpp"&gt;define stack c(x){
    ibase=A
    scale*=1.2
    x=s(2*a(1)+x)
    pop_stack()
    return(x/1)
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Завтра ещё потестирую и попробую закинуть код автору &lt;tt&gt;bc&lt;/tt&gt;, вдруг понравится изменение.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Добавлено позднее&lt;/i&gt;: Автор &lt;tt&gt;bc&lt;/tt&gt; &lt;a href="https://github.com/gavinhoward/bc/pull/93#issuecomment-3099251028"&gt;написал&lt;/a&gt;, что идея у меня интересная, но его жизнь серьёзно изменилась и теперь он не будет заниматься проектом бесплатно. Видимо крепко его прижало. Учитывая низкую популярность &lt;tt&gt;bc&lt;/tt&gt;, можно сказать, что этот проект умер, если у него не найдётся новый мантейнер, что маловероятно.&lt;/p&gt;
</description>
</item>

<item>
<title>99 бутылок: HolyC</title>
<guid isPermaLink="false">136588</guid>
<link>https://bolknote.ru/all/99-butylok-holyc/</link>
<pubDate>Wed, 09 Jul 2025 21:19:57 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/99-butylok-holyc/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;История появления языка, на котором написана сегодняшняя «песня о пиве», довольно занятна.&lt;/p&gt;
&lt;p&gt;Его автор, Терри Дэвис — гениальный одиночка и бывший инженер компании &lt;i&gt;Ticketmaster&lt;/i&gt;, который посвятил более десяти лет созданию &lt;a href="https://habr.com/ru/companies/x-com/articles/904018/"&gt;собственной операционной системы &lt;i&gt;TempleOS&lt;/i&gt;&lt;/a&gt;. Страдая от шизофрении, он считал, что действует по воле Бога, который лично поручил ему создать «божественную ОС». Несмотря на тяжёлое психическое состояние, Дэвис самостоятельно написал компилятор, ядро, графическую оболочку и язык программирования — в полном одиночестве и с поразительной продуктивностью.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;83. HolyC&lt;/b&gt; — тот самый язык, разработанный Терри. Выглядит он довольно интересно. Сильно напоминает Си, но имеет много интересных особенностей, некоторые из которых сразу бросаются в глаза, даже в моей небольшой программе.&lt;/p&gt;
&lt;p&gt;Во-первых, конечно, это собственная система типов, простая и понятная — значение либо выводится (&lt;tt&gt;auto&lt;/tt&gt;), либо сразу видно сколько бит оно занимает, а так же знаковое оно или нет — &lt;tt&gt;U8&lt;/tt&gt;, &lt;tt&gt;I8&lt;/tt&gt;, &lt;tt&gt;U16&lt;/tt&gt; и так далее. Тип &lt;tt&gt;U0&lt;/tt&gt;, как легко догадаться — аналог &lt;tt&gt;void&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Во-вторых, упрощённый вывод на экран — всё отдельностоящие строки сразу выводятся, всё остальное можно вывести через операцию «запятая», указав формат и значения — одно или несколько.&lt;/p&gt;
&lt;p&gt;Чуть менее заметная деталь — оператор &lt;tt&gt;case&lt;/tt&gt; может не иметь аргумента, в таком случае используется автоикрементное значение, начинающееся с нуля. В &lt;i&gt;HolyC&lt;/i&gt; вообще довольно много интересного синтаксического сахара.&lt;/p&gt;
&lt;p&gt;Поражает, как много может создать в одиночку человек, заражённый какой-то идеей. Работы проделано довольно много, причём, работы проделанной очень хорошо. Я не смотрел внутренности &lt;i&gt;TempleOS&lt;/i&gt;, но язык &lt;i&gt;HolyC&lt;/i&gt; выглядит как нечто цельное и продуманное. Некоторые конструктивные особенности я был бы рад видеть и в современном Си, например, значения по-умолчанию для параметров функций.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="cpp"&gt;// &amp;quot;99 Bottles of Beer,&amp;quot; written in HolyC on July 9, 2025
// by Evgeny Stepanishchev (https://bolknote.ru)

auto Bottle(U8 b)
{
  U8 *bottles, *ret;

  switch (b) {
    case:
      bottles = StrNew(&amp;quot;No bottles&amp;quot;);
      break;
    case:
      bottles = StrNew(&amp;quot;1 bottle&amp;quot;);
      break;
    default:
      bottles = StrPrint(NULL, &amp;quot;%d bottles&amp;quot;, b);
      break;
  }

  ret = StrMerge(bottles, &amp;quot; of beer&amp;quot;);
  Free(bottles);
  return ret;
}

U0 Main()
{
  U8 *bottles, b = 99;

  while (b) {
    bottles = Bottle(b);
    &amp;quot;%s on the wall, %1$s!\n&amp;quot;, bottles;
    Free(bottles);

    bottles = Bottle(--b);
    &amp;quot;Take one down, pass it around,\n&amp;quot;;
    &amp;quot;%s on the wall!\n\n&amp;quot;, bottles;
    Free(bottles);
  }

  &amp;quot;No more bottles of beer on the wall,\n&amp;quot;;
  &amp;quot;No more bottles of beer!\n&amp;quot;;
  &amp;quot;Go to the store and buy some more,\n&amp;quot;;
  &amp;quot;99 bottles of beer on the wall!\n&amp;quot;;
}&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>JavaScript™</title>
<guid isPermaLink="false">136483</guid>
<link>https://bolknote.ru/all/javascript-tm/</link>
<pubDate>Mon, 30 Jun 2025 23:48:38 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/javascript-tm/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Поразительно! Сегодня я узнал, что «&lt;i&gt;JavaScript&lt;/i&gt;» — &lt;a href="https://tsdr.uspto.gov/#caseNumber=75026640&amp;caseType=SERIAL_NO&amp;searchType=statusSearch"&gt;зарегистрированная торговая марка&lt;/a&gt;, принадлежащая компании «Оракл». Она попала к «Ораклу» вместе с другими активами компании «Сан Микросистемс» при её поглощении в 2010-м году.&lt;/p&gt;
&lt;p&gt;Большое везение, что «Оракл» до сих пор не попыталась что-нибудь сделать с тем, что их торговую марку используют направо и налево. Попади она к каким-нибудь патентным троллям, мало не показалось бы. К сожалению, не факт, что «Оракл» никогда не перейдёт в их стан.&lt;/p&gt;
&lt;p&gt;Автор &lt;i&gt;Node.js&lt;/i&gt; &lt;a href="https://www.opennet.ru/opennews/art.shtml?num=63494"&gt;пытается добиться&lt;/a&gt; отмены регистрации торговой марки, аргументируя это повсеместным использованием этого названия. Прецеденты есть, насколько я знаю, может и получиться.&lt;/p&gt;
&lt;p&gt;Другим выходом из ситуации было бы ещё переименование языка в &lt;i&gt;EMCAScript&lt;/i&gt; или в &lt;i&gt;LiveScript&lt;/i&gt; — оба названия &lt;a href="https://bolknote.ru/all/language-attribute/"&gt;имеют&lt;/a&gt; отношение в ДжаваСкрипту. Но этот путь, как мне представляется, сложнее первого.&lt;/p&gt;
</description>
</item>

<item>
<title>Scratch на каникулах</title>
<guid isPermaLink="false">136354</guid>
<link>https://bolknote.ru/all/scratch-na-kanikulah/</link>
<pubDate>Fri, 20 Jun 2025 23:27:32 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/scratch-na-kanikulah/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Ещё до отъезда к дедушке и бабушке дочка, с моей подачи, увлеклась программированием на «Скретче» — иногда по вечерам делала на нём что-то несложное. Я показал ей «Скретч», чтобы запрограммировать вместе &lt;a href="https://bolknote.ru/all/tablica-umnozheniya/"&gt;таблицу умножения&lt;/a&gt; — это был мой хитрый план, чтобы она через игру потом её выучила.&lt;/p&gt;
&lt;p&gt;Как-то неожиданно программировать ей понравилось. Я не ожидал, что она настолько этим увлечётся.&lt;/p&gt;
&lt;p&gt;На мой импульс позже наложился лагерь, куда мы её отдали на неделю между каникулами и отъездом, — там тоже был «Скретч». В лагере они программировали мультики, что ещё больше закрепило интерес — дочка когда-то уже &lt;a href="https://bolknote.ru/all/rikki-tikki-tavi/"&gt;делала мультфильм&lt;/a&gt; и думала однажды продолжить.&lt;/p&gt;
&lt;p&gt;Думал на каникулах интерес сойдёт на нет, но как бы не так. Сейчас в её «детском гитхабе» уже 15 проектов, часть из них — вариации одного и того же, но, судя по активности, она и по числу оригинальных проектов меня скоро перегонит.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.06.20@2x.webp" width="1000" height="705" alt="" /&gt;
&lt;/div&gt;
</description>
</item>

<item>
<title>Недокументированные возможности bc</title>
<guid isPermaLink="false">136318</guid>
<link>https://bolknote.ru/all/nedokumentirovannye-vozmozhnosti-bc/</link>
<pubDate>Tue, 17 Jun 2025 20:03:31 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/nedokumentirovannye-vozmozhnosti-bc/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;У той версии утилиты &lt;tt&gt;bc&lt;/tt&gt;, которая является частью проекта &lt;i&gt;GNU&lt;/i&gt;, есть ряд недокументированных возможностей, про которые я узнал, исследуя её исходный код.&lt;/p&gt;
&lt;p&gt;Я уже &lt;a href="https://bolknote.ru/all/igra-viselica-na-bc-pod-linuks/"&gt;писал&lt;/a&gt; про недокументированную и сломанную функцию &lt;tt&gt;random()&lt;/tt&gt;, которая починена в новой версии &lt;a href="https://bolknote.ru/all/pochinili-random-v-bc/"&gt;моими усилиями&lt;/a&gt;. Но кроме этого, есть ещё две вещи отсутствующие в документации.&lt;/p&gt;
&lt;p&gt;Во-первых, у самой утилиты есть ключ &lt;nobr&gt;&lt;tt&gt;-c&lt;/tt&gt;&lt;/nobr&gt;, показывающий байт-код, в который переводится программа на языке &lt;tt&gt;bc&lt;/tt&gt;. Во-вторых, есть альтернативный синтаксис для передачи массива по ссылке — кроме символа &lt;tt&gt;*&lt;/tt&gt;, как везде, есть нестандартный символ &lt;tt&gt;&amp;amp;&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.06.17@2x.webp" width="1000" height="310" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Но это я сам нашёл, руками. Стало интересно посмотреть, что могут найти языковые модели. Для исследования я выбрал редактор кода «Курсор» и модель &lt;i&gt;Claude Sonnet 4&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;С первого захода «Клод» нашёл много всего, но бо́льшая часть — вполне обычные возможности, присутствующие в документации. Засучил рукава, порылся в найденном. Кроме мусора там нашлось и полезное — ключ и функцию &lt;tt&gt;random()&lt;/tt&gt; он нашёл, но про символ &lt;tt&gt;&amp;amp;&lt;/tt&gt; не упомянул.&lt;/p&gt;
&lt;p&gt;Пришлось подтолкнуть — поместить в контекст нужный файл (&lt;tt&gt;bc.y&lt;/tt&gt;) и спросить нет чего-то недокументированного в нём. Со второго раза «Клод» обнаружил искомое, правда, и в этот раз добавил в список много пунктов не по делу.&lt;/p&gt;
&lt;p&gt;С минимальным участием человека нашлись все недокументированные возможности о которых я знаю — три из трёх, правда эти жемчужины пришлось искать вручную в кучке навоза.&lt;/p&gt;
&lt;p&gt;Какой вывод?&lt;/p&gt;
&lt;p&gt;Я считаю, что это, в определённом смысле, успех — «Клод» помог мне вычленить искомое гораздо быстрее, чем в своё время это сделал я. Да, без моей подсказки третью возможность он не нашёл, но и задача очень и очень нетривиальная.&lt;/p&gt;
</description>
</item>

<item>
<title>Текст в PDF</title>
<guid isPermaLink="false">136253</guid>
<link>https://bolknote.ru/all/tekst-v-pdf/</link>
<pubDate>Mon, 09 Jun 2025 20:53:48 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/tekst-v-pdf/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Попалась задача — преобразовать огромный (полтора миллиона строк) тестовый файл в кодировке &lt;i&gt;UTF-8&lt;/i&gt; в &lt;i&gt;PDF&lt;/i&gt;. Не ожидал с ней каких-то сложностей, но оказалось, что это не так-то просто.&lt;/p&gt;
&lt;p&gt;Проблемы две — объём текста и кодировка. Графические утилиты на таком объёме умирают, а с кодировкой &lt;i&gt;UTF&lt;/i&gt;, как оказалось, работают далеко не все утилиты командной строки.&lt;/p&gt;
&lt;p&gt;Перебрал несколько, с задачей справилась только утилита &lt;a href="https://github.com/dov/paps"&gt;&lt;tt&gt;paps&lt;/tt&gt;&lt;/a&gt;. Хочу себе это записать, чтобы не пришлось заниматься перебором, если в будущем столкнусь с такой же задачей.&lt;/p&gt;
&lt;p&gt;Ещё в моей задаче первый лист должен быть пустым и на каждом листе должен быть номер страницы. В результате строка запуска выглядит так:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="bash"&gt;paps --footer --footer-center={page_idx} &amp;lt;(printf \\f;cat listing.txt) -o listing.pdf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Небольшое примечание: при помощи &lt;tt&gt;printf&lt;/tt&gt; я вставляю текстовый символ разрыва страницы (&lt;tt&gt;\f&lt;/tt&gt;), чтобы первая страница оказалась пустой.&lt;/p&gt;
</description>
</item>

<item>
<title>Архиватор HA на «Эльбрусе»</title>
<guid isPermaLink="false">136159</guid>
<link>https://bolknote.ru/all/arhivator-ha-na-elbruse/</link>
<pubDate>Mon, 02 Jun 2025 20:09:37 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/arhivator-ha-na-elbruse/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Мы тут «Эльбрус» решили оживить, который был &lt;a href="https://bolknote.ru/all/elbrus/"&gt;куплен&lt;/a&gt; несколько лет назад для одного из проектов. Проект закончился и компьютер с тех пор лежал на складе.&lt;/p&gt;
&lt;p&gt;Внутри стоит восьмиядерный процессор «Эльбрус-8C» 1,3ГГц. Он тогда-то был экзотикой, а после санкций стал буквально раритетом.&lt;/p&gt;
&lt;p&gt;Я, чтобы прикинуть  его производительностью, решил попробовать повторить на нём свой &lt;a href="https://bolknote.ru/all/arhivator-ha-i-sovremennye-kompyutery/"&gt;недавний эксперимент&lt;/a&gt; — скомпилировать архиватор &lt;tt&gt;ha&lt;/tt&gt; и засечь время, — за сколько он на этой машине сожмёт «Дум».&lt;/p&gt;
&lt;p&gt;Там довольно старая операционка стоит с компилятором &lt;i&gt;gcc 7.3.0&lt;/i&gt; и нет &lt;tt&gt;cmake&lt;/tt&gt;. Пришлось переписать компиляцию на &lt;tt&gt;make&lt;/tt&gt; и компилировать тем, что есть. Наверное новый компилятор соптимизировал бы код лучше, но взять его некуда — надо переставлять операционную систему, а это целая история.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.06.02@2x.webp" width="750" height="485" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;На «Эльбрусе» «Дум» сжался за 18,77 секунды против 4,3 секунды на моём ноутбуке с &lt;i&gt;M3 Max&lt;/i&gt;. Разница более чем в четыре раза. Я даже не знаю — много это или мало. Надо, наверное, посмотреть на каком-нибудь среднем компьютере, чтобы оценить результат.&lt;/p&gt;
</description>
</item>

<item>
<title>Архиватор HA и современные компьютеры</title>
<guid isPermaLink="false">136013</guid>
<link>https://bolknote.ru/all/arhivator-ha-i-sovremennye-kompyutery/</link>
<pubDate>Fri, 30 May 2025 00:25:34 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/arhivator-ha-i-sovremennye-kompyutery/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Узнал сегодня о существовании архиватора &lt;tt&gt;lzip&lt;/tt&gt; — им сжат исходный код &lt;a href="https://bolknote.ru/all/pochinili-random-v-bc/"&gt;свежей версии&lt;/a&gt; утилиты &lt;tt&gt;bc&lt;/tt&gt;. Какой-то современный архиватор из мира Линукса, я не сталкивался ни разу.&lt;/p&gt;
&lt;p&gt;Пока ехал домой, мысли крутились вокруг архиваторов и как-то незаметно докрутились до воспоминаний об архиваторе &lt;tt&gt;ha&lt;/tt&gt; эпохи ДОС. Он тогда сжимал лучше всех, но делал это очень медленно. Я как-то &lt;a href="https://bolknote.ru/all/ha-archiver/"&gt;уже вспоминал&lt;/a&gt;, что над «Думом» он трудился несколько часов. Это были ранние 90-е.&lt;/p&gt;
&lt;p&gt;Я подумал — было бы интересно скомпилировать этот архиватор под мой процессор &lt;i&gt;M3 Max&lt;/i&gt;, который сейчас считается довольно мощным, и посмотреть за какое время на нём сожмётся «Дум».&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.05.29@2x.webp" width="750" height="485" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Ответ — «Дум» теперь сжимается за 4,3 секунды! Надо будет повторить эксперимент лет через 10.&lt;/p&gt;
&lt;p&gt;Кстати, результаты по коэффициенту сжатия тоже довольно достойные — сжалось чуть лучше, чем утилитой &lt;tt&gt;gzip&lt;/tt&gt; и чуть хуже, чем &lt;tt&gt;bzip2&lt;/tt&gt;. Но &lt;tt&gt;lzip&lt;/tt&gt;, что было для меня полной неожиданностью, оставил всех далеко позади:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="javascript"&gt;-rw-r--r--   1 bolk  staff   3688370 May 29 21:37 doom.tar.lz
-rw-r--r--   1 bolk  staff   5226359 May 29 21:39 doom.tar.bz2
-rw-rw-r--   1 bolk  staff   5312857 May 29 21:35 doom.ha
-rw-r--r--   1 bolk  staff   5497638 May 29 21:39 doom.tar.gz&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>Немного о сложностях написания ассемблера на m4</title>
<guid isPermaLink="false">135849</guid>
<link>https://bolknote.ru/all/nemnogo-o-slozhnostyah-napisaniya-assemblera-na-m4/</link>
<pubDate>Sun, 18 May 2025 17:56:58 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/nemnogo-o-slozhnostyah-napisaniya-assemblera-na-m4/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Не думаю, что я много буду использовать язык &lt;i&gt;m4&lt;/i&gt; в будущем, если вообще буду, поэтому хотел дать себе и, возможно, кому-то из читателей чуть больше контекста о том как писался на этом макропроцессоре &lt;a href="https://bolknote.ru/all/assembler-processora-i8080a-na-m4/"&gt;ассемблер процессора 8080A&lt;/a&gt;. А то со временем всё забудется.&lt;/p&gt;
&lt;p&gt;Для этого я чуть-чуть больше расскажу о &lt;i&gt;m4&lt;/i&gt; и ассемблере 8080A.&lt;/p&gt;
&lt;p&gt;Ассемблер 8080А довольно простой. Будучи школьником, я его выучил по комментариям к кускам кода, которые печатались в журнале «Радио» — другой литературы в моём доступе не было. В нём всего несколько команд, большинство из них имеют один или два параметра.&lt;/p&gt;
&lt;p&gt;Посмотрим, например, на команды &lt;tt&gt;ADD B&lt;/tt&gt; и &lt;tt&gt;ADD C&lt;/tt&gt;. Первая эквивалентна &lt;tt&gt;A += B&lt;/tt&gt; на других языках, вторая — &lt;tt&gt;A += C&lt;/tt&gt;. Буквами обозначаются регистры, для простоты можно считать их именованными переменными. Их мало, всего несколько штук и они имеют свои особенности. Например, в этих двух командах мы видим особенность регистра &lt;tt&gt;A&lt;/tt&gt; — к нему можно прибавлять значения других регистров.&lt;/p&gt;
&lt;p&gt;Команды &lt;tt&gt;ADD B&lt;/tt&gt; и &lt;tt&gt;ADD C&lt;/tt&gt; для исполнения компьютером переводятся в числа — в машинные коды. Обычно их записывают в шестандцатеричном виде, я тоже так буду делать. Данные команды сложения кодируются как числа &lt;tt&gt;80&lt;/tt&gt; и &lt;tt&gt;81&lt;/tt&gt; соответственно.&lt;/p&gt;
&lt;p&gt;Теперь немного про &lt;i&gt;m4&lt;/i&gt;. Я писал выше, что &lt;i&gt;m4&lt;/i&gt; — макропроцессор, если упрощать, язык макропроцессора позволяет указать как одни «слова» заменить на другие. «Слова» при этом должны начинаться с буквы или подчёркивания и содержать только буквы, цифры или знак подчёркивания. Это ограничение очень важное. Не будь его, я бы задал по одному правилу на каждую команду: &lt;nobr&gt;&lt;tt&gt;ADD B → 80&lt;/tt&gt;&lt;/nobr&gt;, &lt;nobr&gt;&lt;tt&gt;ADD C → 81&lt;/tt&gt;&lt;/nobr&gt; и был таков.&lt;/p&gt;
&lt;p&gt;К сожалению, так это не работает. Из-за этого ограничения, когда макропроцессор встречает &lt;tt&gt;ADD&lt;/tt&gt;, он ещё не знает что будет дальше, поэтому не может выбрать на какой код заменить это слово, а когда дальше он видит &lt;tt&gt;B&lt;/tt&gt; или &lt;tt&gt;C&lt;/tt&gt;, ему надо помнить, что было до этого, так как с этими регистрами работает много команд. Другими словами, макропроцессору нужно запоминать контекст.&lt;/p&gt;
&lt;p&gt;В руководствах по &lt;i&gt;m4&lt;/i&gt; указывается, что этот макропроцессор контекст учитывать не умеет. Так и есть, встроенных конструкций, предназначенных именно для этого нет, но можно выкрутиться менее специфичными. Дело в том, что &lt;i&gt;m4&lt;/i&gt; может проверять как выглядят его текущие правила замен одного слова на другое.&lt;/p&gt;
&lt;p&gt;Поэтому мы можем завести специальное правило, куда будем записывать какая команда нам встретилась, а позже, встретив имя регистра, будет проверять чему равно наше специальное правило и производить замену, основываясь на этом.&lt;/p&gt;
&lt;p&gt;При этом &lt;i&gt;m4&lt;/i&gt; не делает различий между, так сказать, текстом программы и обрабатываемым текстом, для него это одно и то же. То есть макропроцессор делает возможным метапрограммирование — позволяет менять программе свой собственный текст.&lt;/p&gt;
&lt;p&gt;Вот как это выглядит в коде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="plaintext"&gt;dnl заменяем строку ADD на определение макроса, сама строка ADD при этом пропадёт
define(`ADD&amp;#039;, `define(`__cmd&amp;#039;, `__s_ADD&amp;#039;)&amp;#039;)dnl

dnl когда встречаем B, смотрим чему равно определение макроса __cmd
define(`B&amp;#039;, `
ifelse(
    defn(`__cmd&amp;#039;), `__s_ADC&amp;#039;, 88,
    defn(`__cmd&amp;#039;), `__s_ADD&amp;#039;, 80,
    …тут остальные команды…
    `&amp;#039;)
&amp;#039;)dnl

dnl когда встречаем C, смотрим чему равно определение макроса __cmd
define(`C&amp;#039;, `
ifelse(
    defn(`__cmd&amp;#039;), `__s_ADC&amp;#039;, 89,
    defn(`__cmd&amp;#039;), `__s_ADD&amp;#039;, 81,
    …тут остальные команды…
    `&amp;#039;)
&amp;#039;)dnl&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Чтобы дойти до этого трюка, пришлось поломать голову, но тем интереснее. Возможно он где-то уже описан, но искать информацию по &lt;i&gt;m4&lt;/i&gt; очень тяжело — поисковые машины охотно путают его с одноимённым процессором, а нейросети пишут какую-то пургу, не имеющую никакого отношения к реальности.&lt;/p&gt;
</description>
</item>

<item>
<title>Ассемблер процессора i8080A на m4</title>
<guid isPermaLink="false">135830</guid>
<link>https://bolknote.ru/all/assembler-processora-i8080a-na-m4/</link>
<pubDate>Fri, 16 May 2025 10:40:51 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/assembler-processora-i8080a-na-m4/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Сегодня опять сычевал почти до полуночи — вечером попался кусок кода на &lt;i&gt;m4&lt;/i&gt; и я, пробормотав вечное «когда-нибудь надо бы его выучить», вдруг подумал — а почему бы и не сейчас? Я и так всё время откладываю, а этот вечер ничем для этой цели не хуже, чем любой другой.&lt;/p&gt;
&lt;p&gt;Чтобы разбираться было веселее, придумал себе задачу — написать на &lt;i&gt;m4&lt;/i&gt; ассемблер, желательно не очень сложный, чтобы занятие на вечерок не разрослось потом до недельного проекта. Взял &lt;a href="https://web.archive.org/web/20131014125438/https://demin.ws/projects/radio86/info/kr580/i8080.html"&gt;инструкции интеловского процессора 8080A&lt;/a&gt; — это был мой первый ассемблер. Советской аналог процессора стоял на компьютере «Радио-86РК», с &lt;a href="https://bolknote.ru/all/4316/"&gt; которого я когда-то начинал&lt;/a&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2025.05.15@2x.webp" width="1000" height="665" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Строка «HELLO WORLD», выведенная программой, переведённой в машинный код моим ассемблером&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Несколько слов о том что такое &lt;i&gt;m4&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Это довольно простой макропроцессор, умеющий заменять одни указанные строки на другие. Описание что на что заменить делается параметрическими макросами. В языке есть собственные макросы, но можно определить и пользовательские. Поддерживаются так же условия и математика. В продвинутых версиях &lt;i&gt;m4&lt;/i&gt; есть даже циклы, но их в любой версии можно эмулировать рекурсией.&lt;/p&gt;
&lt;p&gt;Парочка примеров того как выглядит его синтаксис:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="plaintext"&gt;dnl Макрос, заменяющий одну строку на другую
define(`WORLD&amp;#039;, `KAZAN&amp;#039;)dnl

dnl Макрос, оставляющий первый свой параметр как есть, а
dnl второй складывающий со значением другого макроса,
dnl если второй параметр не указан, его значение — единица
define(`__pr&amp;#039;, `define(`__ip&amp;#039;, eval(__ip + ifelse($2, `&amp;#039;, 1, $2)))$1&amp;#039;)dnl&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Чтобы реализовать задуманное, я взял список команд процессора с кодами — их там чуть меньше 250, если брать варианты с разными регистрами, и написал на Пайтоне два генератора.&lt;/p&gt;
&lt;p&gt;Два, потому что мне нужно было как-то решить проблему расчёта адресов ссылок. Первая программа генерирует файл &lt;tt&gt;linker8080.m4&lt;/tt&gt;, который этим и занимается. Адреса он на следующем этапе передаёт в виде макросов второму файлу — &lt;tt&gt;asm8080.m4&lt;/tt&gt;, который делает основную работу — переводит ассемблер в машинные коды.&lt;/p&gt;
&lt;p&gt;Сначала у меня всё было сделано в одном файле, но я быстро выяснил, что макросы распространяются сверху вниз, то есть определённые ниже макросы не влияют на текст выше. Если ссылка, для которой я подсчитал адрес, находится ниже точки вызова, я этот вызов уже не могу заменить.&lt;/p&gt;
&lt;p&gt;Вот программа на этом ассемблере, в действии её можно посмотреть на скриншоте:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="asm"&gt;ORG(h1100)
LXI H, ADDR(TEXT)
CALL hF818
JMP hF86C

LABEL(TEXT)
BYTE(h48, h45, h4C, h4C, h4F, h20, h57, h4F, h52, h4C, h44, hD, hA, h0)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Не слишком отличается от привычного вида, но отличия всё-таки есть.&lt;/p&gt;
&lt;p&gt;Во-первых, числа должны быть только шестнадцатеричными. Часто так и бывает, но тут запись немного непривычная — &lt;tt&gt;hFF&lt;/tt&gt; вместо более привычной &lt;tt&gt;FFh&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Во-вторых, многие вещи, не генерирующие код, выглядят чуть иначе — адрес запуска задаётся конструкцией &lt;tt&gt;ORG(…)&lt;/tt&gt;, метка — через &lt;tt&gt;LABEL(…)&lt;/tt&gt;, а её адрес получается через &lt;tt&gt;ADDR(…)&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;В-третьих, произвольные цепочки байт задаются не директивой &lt;tt&gt;DB&lt;/tt&gt;, а конструкцией &lt;tt&gt;BYTE(…)&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Результат можно увидеть у меня &lt;a href="https://github.com/bolknote/M4-8080A-Asm"&gt;в репозитории&lt;/a&gt;.&lt;/p&gt;
</description>
</item>

<item>
<title>«Курсор»</title>
<guid isPermaLink="false">135778</guid>
<link>https://bolknote.ru/all/ide-cursor/</link>
<pubDate>Fri, 09 May 2025 11:35:04 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/ide-cursor/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Что-то я опять по кривой Гартнера свалился на дно разочарования в «Курсоре» — это редактор, где можно программировать с помощью нейросетей. Из семи последних задач «Курсор» запорол все семь, да ещё как эпично! Задачи, на мой взгляд, я описывал понятно — так, как описал бы живому программисту.&lt;/p&gt;
&lt;p&gt;Чтобы отойти от разочарования, решил как-то реабилитировать технологию в своих глазах, тем более, что некоторые мои задачи нейросети всё-таки выполняют. Взял &lt;a href="https://github.com/gavinhoward/bc/blob/master/gen/lib2.bc"&gt;библиотеку функций&lt;/a&gt; из продвинутой реализации &lt;tt&gt;bc&lt;/tt&gt;, чтобы попробовать портировать её на версию &lt;i&gt;GNU&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Попросил три понятных изменения сделать, любой дурак справится:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a@b заменить на вызов функции &lt;tt&gt;floor(a, b)&lt;/tt&gt;, которую я написал;&lt;/li&gt;
&lt;li&gt;a$ заменить на вызов &lt;tt&gt;floor(a, 0)&lt;/tt&gt;;&lt;/li&gt;
&lt;li&gt;там, где оператор &lt;tt&gt;else&lt;/tt&gt; перенесен на другую строку от конструкции &lt;tt&gt;if&lt;/tt&gt;, надо либо заэкранировать перенос через обратный слеш, либо вернуть &lt;tt&gt;else&lt;/tt&gt; на одну строку с &lt;tt&gt;if&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Задача простая, но даже тут «Курсор» накосячил, не справившись с подсчётом скобок. В итоге, тщательно проверял все замены и считал скобки я сам. К чёрту такую автоматизацию, по сумме, я бы сам быстрее сделал.&lt;/p&gt;
&lt;p&gt;Раньше я бы к этому спокойно отнёсся, но в последнее время раздражительность повысилась — мёрзну и всё время на грани простуды. Отопление давно отключили, а на улице резко похолодало — снег уже несколько раз шёл. Но, видимо, недостаточно холодно, чтобы включать отопление обратно.&lt;/p&gt;
&lt;p&gt;Вокруг очень многие болеют пневмонией, это ещё что такое, откуда? Я уверен, что слово «пневмония» я слышал за прошедшие два года больше, чем за всю прошлую жизнь. Сам я всё время кашляю, хотя не чувствуется, что болею, временами только какая-то слабость накатывает.&lt;/p&gt;
</description>
</item>


</channel>
</rss>