Избранное

Баг

Принято считать, что слово «баг» появилось 9 сентября 1946 года, когда Грейс Хоппер, которая работала в тот момент в Гарвардском университете с ЭВМ «Марк II», проследила ошибку в работе программы до реле машины, куда попал мотылёк. Грейс вклеила насекомое в технический журнал, сопроводив шуткой «Первый реальный случай обнаружения жучка» («First actual case of bug being found»).

На самом деле это одна из версий проникновения термина в среду компьютерщиков. В выпущенном в 1892 году «Стандартизованном словаре электротехники» можно прочитать:

Баг — это любая неисправность или дефект в электрических соединениях или работе электрических аппаратов

Как видим слово появилось раньше 1946 и даже не в 20 веке. По одной из версий термин придумал и популяризировал Томас Эдисон — известный американский предприниматель, Стив Джобс своего времени.

В своих письмах и дневниковых заметках он нередко употребляет это слово. Выше — скан его письма от 3 марта 1878 года (оригинал можно купить за пару тысяч долларов). В пятой строчке, сразу после артикля, написано «bug».

Употреблял ли Эдисон это слово в знакомом нам значении? Да! Так 18 ноября 1878 года он написал Тивадару Пушкашу (венгерскому учёному, физику, и изобретателю первой в мире телефонной станции):

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

Так что термину в этом году исполняется по меньше мере 140 лет.

Казанская страховая доска

Страховые доски — металлические таблички, которые до революции крепились на фасад застрахованного строения (или над дверью застрахованной квартиры). Они всё ещё попадаются на старинных зданиях в российских городах, но всё реже — за ними охотятся коллекционеры.

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

Узнать местоположение последней страховой доски оказалось непросто, возможно поэтому коллекционеры пока до неё не добрались. Даже зная примерный адрес, нашёл только через полчаса поисков. Доска маленькая, сильно заржавела, пришлось занимать объектив у приятеля, чтобы снять.

Написано там следующее: «въ обществѣ РОССІЯ застраховано». На фоне — почти уже незаметная восьмиугольная звезда, намёк на икону «Неопалимая Купина». «Неопалимая Купина» почитается как заступница при пожарах, так что такая страховая доска одновременно играла ещё и роль оберега.

ProxyJump

Как-то писал заметку про .ssh/config и опцию ProxyCommand, а потом почти сразу после этого, перечитывая руководство по теме, наткнулся на схожую опцию ProxyJump:

Host 10.1.10.*
        IdentityFile ~/.ssh/id_rsa
        #ProxyCommand /usr/bin/ssh -W %h:%p bolk@rptn.tunnel
        ProxyJump rptn.tunnel

Возможности её у́же, зато пользоваться ею проще. Кроме указания в конфиге, её просто использовать и из командной строки, как ключ, причём цепочки выстраиваются очень просто:

ssh -J bolk.sed-php7:2258,rptn.tunnel 10.1.10.158

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

10 февраля   ssh   ssh_config   программирование

🍎 + 🍍 + 🍌 = 🥗

Уравнение (118.71КиБ)
Казалось бы, обычная картинка, которых сотни — реши фрукты

По интернету ходят сотни картинок, где надо «решить фрукты» — в уравнение в качестве имён переменных подставлены какие-нибудь посторонние предметы. В вариантах чуть посложнее надо быть повнимательнее — например, в уравнениях везде бананы, а в одном месте гроздь из трёх.

Когда я увидел картинку выше, ради развлечения сунул её в «Вольфрам» — хотелось посмотреть как ему указать, что числа должны быть целые. Заинтересовало, что решения не нашлось. Я задумался и внимательно посмотрел на фрукты, в них подвоха тоже не увидел.

Оказалось, что картинка выше — пранк по мотивам статьи на «Кьюоре». Решить уравнение, которое на ней, сможет лишь небольшое количество людей со специальными знаниями, а прямой перебор значений займёт совершенно нереальное время.

Минимальные подходящие числа для уравнения такие (ответ проверял на ЯП «Эр»):

`🍎` <- 154476802108746166441951315019919837485664325669565431700026634898253202035277999
`🍌` <- 36875131794129999827197811565225474825492979968971970996283137471637224634055579
`🍍` <- 4373612677928697257861252602371390152816537558161613618621437993378423467772036

print(`🍎` / (`🍌` + `🍍`) + `🍌` / (`🍎` + `🍍`) + `🍍`/(`🍎` + `🍌`)) # [1] 4

Это числа от 79 знаков и больше! Где уж такое решить!

31 января  

Ассемблер под Линукс

Заметка про полноту по Тьюрингу команды присваивания в ассемблере натолкнула меня на мысль, что я как-то не удосужился попрограммировать на ассемблере под Линукс — эту ОС я начал осваивать примерно в то же время, когда начал быстро терять интерес к ассемблеру.

Тогда не довелось, решил вчера попробовать. Теорию в очень общих чертах я знал — есть системные вызовы (сисколы), которые можно дёргать какой-то командой, имена сисколов мне знакомы через Си. Попробовал написать программу, которая выводит на вход то, что ей дают на вход. Быстро разобрался, что регистры сейчас имеют впереди букву «эр», а сисколы делаются прерыванием №128. Удобный способ, параметры идут в логичном виде — последовательно через регистры в почти алфавитном порядке (ближе к концу последовательность нарушается):

MOV RAX, 3 ; sys_read
MOV RBX, 0 ; stdin
MOV RCX, string ; адрес строки, которую выведем на экран
MOV RDX, len ; длина строки
INT 0x80

Но я где-то читал, что для сисколов есть команда новее — syscall, просто заменил вызов прерывания на эту команду — не заработало. Полез в интернет. Оказалось, у там другой набор параметров, да и сами сисколы имеют другие номера.

MOV RAX, 0 ; sys_read
MOV RDI, 0 ; stdin
MOV RSI, string ; адрес строки, которую выведем на экран
MOV RDX, len ; длина строки
SYSCALL

К тому времени меня посетила мысль сделать простенький аналог линуксовой утилитки tee, но для этого нужно было как-то прочитать параметры командной строки. Гугление показало, что после запуска программы на стеке лежат количество параметров и указатели на каждый из них, причём каждый параметр кончается нулём — обычная сишная строка.

Так как системный вызов для открытия файла (sys_open) как раз требует на вход сишную строку, я передал указатель, который взял со стека, в сискол, ожидая, что всё заработает. Это было моей ошибкой. Я потратил не меньше часа, разбираясь, что я сделал не так, перебирал способы передачи параметров, ползал по стеку при помощи отладчика gdb, ничего не помогало, пока не забрезжила догадка, что сами параметры командной строки тоже лежат на стеке и системному вызову это может не нравится.

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

Пока получилась очень простая утилитка, но хочу её дописать как выпадет свободный вечер — сделать поддержку указания нескольких файлов и флага для режима присоединения. Размер радует, кстати, — всего 752 байта.

Дизассемблируй это

Дум (71.16КиБ)
«ДУМ», скомпилированный с использованием одних только команд MOV

В моей жизни последовательно сменяли друг друга три ассемблера. Первый, для компьютера «Радио-86РК», я выучил по комментариям к ассемблерному коду в журнале «Радио» — другой литературы не было, а до моего знакомства с интернетом оставалось несколько лет. Потом были последовательно ассемблеры для «Спектрума» и интеловских процессоров.

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

В ассемблере есть такая команда — MOV (в некоторых ассемблерах — LD), записывает содержимое одного аргумента в другой. Сейчас набор комманд разросся, аргументом может быть почти что угодно — регистр, ячейка в памяти, сумма некоторого числа, одного регистра и другого, умноженного на число, но по сути это всегда присваивание.

И вот оказалось, что эта команда — полная по Тьюрингу. Звучит невероятно, но это так. Некие ребята заморочились и сделали компилятор, который компилирует любую программу на Си в последовательность команд MOV. Причём им даже ДУМ удалось скомпилировать, правда один кадр рисуется семь часов. Кстати, такая программа неуязвима для горюшка века — Мелтдауна и Спектра.

Есть небольшая (на 156 страниц и 90% воды) презентация, достаточно популярно объясняющая как этого удалось достичь, но для её чтения надо знать ассемблер, поэтому я позволю себе раскрыть детали трансляции двух инструкций, чтобы пояснить принцип для тех, кто ассемблера не знает или ленится причитать.

Например, сравнение двух чисел делается при помощи следующего псеводокода:

mov [X], 0
mov [Y], 1
mov R, [X]

У нас есть два числа в аргументах «X» и «Y», результат сравнения которых попадает в «R» — там будет ноль, если числа не равны и единица в противном случае. Как же это работает?

Первой командой ноль записывается в ячейку по адресу «X». Это ассемблер, у нас тут всё — число, остальное — человеческие интерператации, поэтому записанное в «X» мы используем как адрес. Второй командой единица записывается в ячейку по адресу «Y». Третьей командой мы читаем значение по адресу «X» и если значения в «X» и «Y» совпадают, то ноль перетрётся единицей (и она попадёт в R), если нет, то в ячейке по адресу «X» ноль останется (который попадёт в R).

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

Возьмём, например, логическое «ИЛИ» («OR»), тут чуточку сложнее:

OR_ADDRS: dd OR_0, OR_1
OR_0: dd 0, 1
OR_1: dd 1, 1
; …
mov eax, X
mov edx, [OR_ADDRS + eax]
mov eax, Y
mov eax, [eax + edx]
mov R, eax

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

Что тут происходит? В регистр (переменную, с которыми работает процессор) «eax» записывается значение «X» (возможные входные значения у нас тут — ноль или единица, численное представление булевых значений).

Далее в регистр «edx» записывается число из адреса, который является суммой адреса массива OR_ADDRS и содержимого регистра eax. Таким образом в eax попадёт OR_0 или OR_1, в зависимости от того былы записаны в eax ноль или единица. Эти значения — тоже числа и являются адресами двух других массивов из двух элементов.

Далее в eax мы записываем аргумент Y, его значение складывается с адресом полученным на предыдущем шаге и из получившегося адреса мы читаем записанное там значение. В переводе на ПХП получается следующее:

function mov_or(int $X, int $Y): int
{
    define('OR_0', [0, 1]);
    define('OR_1', [1, 1]);

    define('OR_ADDRS', [OR_0, OR_1]);

    $R = OR_ADDRS[$X][$Y];

    return $R;
}

Кстати, интересно, что у знаменитого дисассемблера «ИДА» от полученной таким образом программы крепко уносит крышу — при попытке отладки диссасемблер не видит никаких ветвлений и падает на анализе кода. Получился бы неплохой метод защиты от анализа, если бы не производительность.

Интернет-археология: браузер ViolaWWW

Неудачная попытка запуска (12.62КиБ)
Моя попытка запустить браузер под Линукс пока завершилась провалом

Пока читал про «Си-минус-минус», наткнулся на браузер ViolaWWW. Браузер разрабатывался с 1991 года в университете Беркли одним-единственным человеком — Вэй Пей-Юанем.

Эта вещь достойна внимания из-за примечательного факта — там реализованы таблицы стилей, за несколько лет до появления CSS, а так же первый скриптовый язык — задолго до «ДжаваСкрипта» и «Си-минус-минуса»! Причём с событиями и подобием аякса!

Автор написал несколько программ на своём языке, например — шахматы. Я пока не нашёл документацию, зато обнаружил несколько примеров. Например, скрипт выводящий синусоиду:

\class {field}
\name {wave}
\parent {}
\children {wave.sb}
\script {
    switch (arg[0]) {
    case "graph":
        f = float(arg[1]);
        xx = width();
        r  = height() / 2.0;
        theta = 0;
        for (x = 20; x < xx; x += 2) {
            theta = theta + 0.1;
            y = sin(theta * f) * r + r;
            drawLine(x, y, x, y + 1);
        }
        return;
    break;
    }
    usual();
}
\width {300}
\height {200}
\
\class {slider}
\name {wave.sb}
\parent {wave}
\script {
    switch (arg[0]) {
    case "_shownPositionV":
        usual();
        send(parent(), "graph", arg[1]);
        return;
    break;
    }
    usual();
}
\x {2}
\y {2}
\width {15}
\height {200}
\shownSizeV {10}

К сожалению, позапускать программы пока нечем. Исходный код я нашёл, но под Линуксом он компилироваться не захотел, собственно, судя по коду, он никогда под ним и не собирался. Я сделал минимально необходимые правки, код собрался, но попытка запуска завершилась крахом. Подумаю стоит ли тратить силы дальше.

Даже интересно какой бы веб мы увидели сейчас, если бы этот браузер тогда получил дальнейшее распространение! Получается в 90-х он умел больше, чем некоторые браузеры в двухтысячных. Например в скриптовом языке я заметил селекторы nthChild и даже nthWord!

Насколько я могу видеть, поддерживалось более десятка форматов графики, в том числе всем знакомый GIF, правда без анимации и в формате 1987 года, а так же сейчас уже экзотический XBM (до относительно недавнего времени поддерживался «Эксплорером», «Сафари» и «Оперой»).

Военный поиск

Палаточный лагерь (268.97КиБ)
Палаточный лагерь поискового отряда, крайняя левая палатка — моя

Давно хотел присоединиться к военно-поисковому отряду, но всё было недосуг — они ездят в основном на несколько дней, а у меня нет столько времени. А тут повезло — один из отрядов собирался поехать на три дня в алексеевский район — и рядом, и длительность подходящая.

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

Захоронение (290.88КиБ)
Один из откопанных скелетов, в могилах никаких личных вещей не найдено

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

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

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

2017  

Билл «Кон» Гейтс

Устройство CON (184.46КиБ)
Устройство «CON» в 86-DOS версии 1.00

Какой херни только по радио не услышишь! Ехал вчера в такси, а по радио рассказывают про файл с именем CON, который нельзя создать в Винде, якобы потому что это было прозвище Билла Гейтса в детстве и он поклялся, что в его системе такой файл нельзя будет создать!

Ну что за бред?

Во-первых, это специальное имя файла, всё, что в него записывается выводится на CONsole — консоль. Таких имён множество, в основном трёх- и четырёхсимвольных. Например, есть PRN — принтер, COM1 — первый ком-порт и другие. Они достались Винде ещё от ДОСа.

Во-вторых, первые версии системы, которую сейчас называют просто «ДОС» были написаны в «Сиэтл Компьютер Продактсе» Тимом Патерсоном и лишь версия 1.10 была приобретена во владение Микрософтом и переименована из 86-DOS в MS-DOS. Специальные имена файлов были добавлены в версии 0.74, если запустить версию 1.00, легко убедиться, что CON там имеет тот же специальный смысл, причём ещё в те времена, когда система не принадлежала Биллу Гейтсу.

2017  

AppleScript и Тетрис

Тетрис (20.11КиБ)
Непритязательный внешний вид получившегося Тетриса

Я тут книгу читаю про хакеров (в первоначальном смысле слова) — «Хакеры. Герои компьютерной революции». Книга довольно занудная, но тот дух, который она пытается передать, я ещё очень хорошо помню. Ассемблер, такты, хаки, придуманные трудности — всё это было как специи в программировании. Сейчас как-то чем дальше, тем преснее.

И так тоскливо что-то мне стало, так захотелось написать что-нибудь долбанутое, чтобы почуствовать вкус того самого программирования, что как-то написался у меня в промежутках между делами в последние дни отпуска Тетрис на ЭплСкрипте.

Трудности, которые мне тут успешно самому себе удалось придумать, заключаются в том, что ЭплСкрипт в этой плоскости очень бедный язык. Если не сказать нищий. У него нет встроенных средств рисования чего-либо на экране или опроса клавиатуры, поэтому пришлось выкручиваться (те самые специи).

Для тех, кто не знает, надо наверное пояснить. ЭплСкрипт — это язык автоматизации пользовательских сценариев работы, он умеет управлять приложениями (с разной степенью успеха) и кое-какими вещами в «МакОСи».

Так как возможности что-то рисовать в нём нет, то стакан и фигуры сделаны из уменьшенных окошек приложения «TextEdit» — я их создаю по потребности и масштабирую к малому размеру. Получаются такие белые шарики, из которых всё и состоит.

Дольше всего я ломал голову над управлением, пока не придумал следующее — ЭплСкрипт умеет опрашивать значение громкости, так что клавиши уменьшения и увеличения я приспособил под сдвиг фигуры, а кнопку включения/выключения звука — под поворот.

Над скоростью игры я в некоторых местах поработал, но сильно углубляться не стал — ЭплСкрипт относительно шустрый, основную задержку вносит создание окон, это место вряд ли можно как-то ускорить — там несколько строк всего и всё адресовано приложению TextEdit, а оно уж открывает свои окна так быстро как может. Впрочем игровая скорость мне кажется приемлемой, только отрисовка самого стакана происходит дольше, чем хотелось бы.

Кажется это первая и единственная игра в реальном времени на ЭплСкрипте.

Ранее Ctrl + ↓