Запойный сладкоежка
Около пятнадцати лет назад я бросил пить алкоголь. Точнее не помню, но припоминаю, что в том же году моя тогдашняя кошка родила котят, о чём осталась запись, датированная
Много воды утекло и я уже
Я больше года занимаюсь с тренером, которая так же составляет для меня диету. Ничего фантастического, но от потребления сахара пришлось отказаться. Я всю жизнь считал себя заядлым сладкоежкой (несколько лет назад я ел по шоколадке в день), но оказалось, что для меня это не такой уж и трудный шаг.
Так вот, оказалось, что отказаться о сахара, это примерно как отказаться от алкоголя — многим кажется, что меня заставили, что я бедный и несчастный, что меня надо освободить от этой кабалы. Многие предлагают съесть,
Сижу и думаю — не лишусь ли в этот раз ещё части друзей. Вдруг меня с ними объединяет только сахар?
Чёрная перфолента
Дмитрий Радищев, околокомпьютерные обзоры которого я с удовольствием читал на его застывшем в янтаре сайте, прислал для нашего музея компьютерной техники перфокарт и бобину неиспользованной чёрной перфоленты с двумя пробитыми обрывками.
Если бы не обрывки, вряд ли можно было бы быстро догадаться для чего эта лента предназначалась — чёрную перфоленту я никогда в жизни не видел и даже не задумывался о наличии других цветов, кроме белого.
Кстати, одно время перфолента широко использовалась в советских журналах, как элемент оформления различных компьютерный статей, некий символ тогдашнего айти. Уже ушедший символ, вслед за которым почти уже ушла дискета, которую с большим трудом теперь заменяют на облако со стрелочкой. И вот ещё думаю, современным детям уже трудно будет объяснить, почему трубку телефона «кладут» или «бросают», сам телефон «звонит» даже на вибрации, а «берут» трубку, сдвигая непонятный символ, похожий на перевёрнутую кратку над буквой «Й».
Дима, большое спасибо за подарок музею на Новый год!
Мой цвет волос в детстве
На новогодние праздники приехали в гости родители и по моей просьбе захватили два пакетика с моим детскими локонами —
Дочка у меня относительно светлая и мне стало любопытно сравнить её цвет с тем, что у меня был в детстве.
Увы, не смог сфотографировать как видно глазами, видимо
Тухандредкоины
Я их в руках не держал, сфотографировать не могу,
Так вот, за купюрами в 200 и 2000 рублей сейчас охотятся коллекционеры, но так как их становится всё больше, то котируется не каждая купюра, а только серия «АА», причём чем больше нулей после серии, тем лучше — то есть ценятся купюры первых партий. На «Авито» народ надеется выручить от 100 до 4000 рублей за такие купюры, но считается, что их стоимость будет ещё расти.
Эта охота за нулями очень мне напомнила другие популярные денежки — биткоины. Дело в том, что там закрывающие блоки имеют определённую сложность, чтобы считать их было трудно, поэтому подбирается специальное значение (хеш), так, чтобы в начале было определённое количество нулей. Мне показалось смешным, что майнеры и коллекционеры охотятся за нулями, одни за виртуальными, другие — за нарисованными.
Кстати, всех, кто всё ещё хочет понять, что такое биткоины, отсылаю к гениальной статье Вастрика «Блокчейн изнутри: как устроен биткоин» — его сайт, кстати, для меня стал открытием года. Получаю громадное удовольствия от чтения всех его статей.
Сказки от прабабушки
Есть такая штука, немного пафосно называемая «связью поколений». Я довольно далеко продвинулся в исследовании дерева своего рода и могу сказать, что она ощущается только в том случае, если с предком связны хоть
Хотелось бы оставить дочке хоть
Перерыл все «дневники», сказок не нашёл. Видимо записал
Зато много интересного про себя вычитал. Например,
Что есть истина?
У нашего бывшего сотрудника в фейсбуке увидел ссылку на любопытную задачку — может ли (a == 1 && a == 2 && a == 3) быть «истиной» в ДжаваСкрипте?
Не заглядывая в статью, я предложил два варианта, вполне очевидный первый:
a = ((counter) => ({valueOf:() => ++counter}))(0)
// {valueOf: ƒ}
a == 1 && a == 2 && a == 3
// trueИ второй — на суррогатных парах. Но по ссылке есть ряд других занимательных способов — через геттеры, похожие символы Юникода (мне приходил в голову такой вариант, но я не смог подобрать три символа, одинаковых на вид), другие специальные методы и прочее. Больше всех мне понравился такой способ:
a = [1,2,3];
a.join = a.shift;
a == 1 && a == 2 && a == 3
// trueОчень просто и элегантно — массив при преобразовании в скаляр в ДжаваСкрипте, всегда сначала преобразуется в строку значених, объединённых через запятую. В коде выше метод для объединения заменяется методом, который забирает из массива первый элемент. И всё работает как требуется — при каждом сравнении массива с числом, забирается первый элемент массива.
Дизассемблируй это ★
В моей жизни последовательно сменяли друг друга три ассемблера. Первый, для компьютера
В те времена я думал, что всю жизнь буду программировать на ассемблере, на деле же последнюю программу на нём написал в начале
В ассемблере есть такая команда — 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;
}Кстати, интересно, что у знаменитого дисассемблера «ИДА» от полученной таким образом программы крепко уносит крышу — при попытке отладки диссасемблер не видит никаких ветвлений и падает на анализе кода. Получился бы неплохой метод защиты от анализа, если бы не производительность.
Ассемблер под Линукс ★
Заметка про полноту по Тьюрингу команды присваивания в ассемблере натолкнула меня на мысль, что я
Тогда не довелось, решил вчера попробовать. Теорию в очень общих чертах я знал — есть системные вызовы (сисколы), которые можно дёргать
MOV RAX, 3 ; sys_read
MOV RBX, 0 ; stdin
MOV RCX, string ; адрес строки, которую выведем на экран
MOV RDX, len ; длина строки
INT 0x80Но я
MOV RAX, 0 ; sys_read
MOV RDI, 0 ; stdin
MOV RSI, string ; адрес строки, которую выведем на экран
MOV RDX, len ; длина строки
SYSCALLК тому времени меня посетила мысль сделать простенький аналог линуксовой утилитки tee, но для этого нужно было
Так как системный вызов для открытия файла (sys_open) как раз требует на вход сишную строку, я передал указатель, который взял со стека, в сискол, ожидая, что всё заработает. Это было моей ошибкой. Я потратил не меньше часа, разбираясь, что я сделал не так, перебирал способы передачи параметров, ползал по стеку при помощи отладчика gdb, ничего не помогало, пока не забрезжила догадка, что сами параметры командной строки тоже лежат на стеке и системному вызову это может не нравится.
Попробовал скопировать строку оттуда в данные и всё заработало. Не знаю что это было, пока не гуглил, возможно сделано из соображений безопасности. Времени потерял изрядно.
Пока получилась очень простая утилитка, но хочу её дописать как выпадет свободный вечер — сделать поддержку указания нескольких файлов и флага для режима присоединения. Размер радует, кстати, — всего 752 байта.
🍎 + 🍍 + 🍌 = 🥗 ★
По интернету ходят сотни картинок, где надо «решить фрукты» — в уравнение в качестве имён переменных подставлены
Когда я увидел картинку выше, ради развлечения сунул её в «Вольфрам» — хотелось посмотреть как ему указать, что числа должны быть целые. Заинтересовало, что решения не нашлось. Я задумался и внимательно посмотрел на фрукты, в них подвоха тоже не увидел.
Оказалось, что картинка выше — пранк по мотивам статьи на «Кьюоре». Решить уравнение, которое на ней, сможет лишь небольшое количество людей со специальными знаниями, а прямой перебор значений займёт совершенно нереальное время.
Минимальные подходящие числа для уравнения такие (ответ проверял на ЯП «Эр»):
`🍎` <- 154476802108746166441951315019919837485664325669565431700026634898253202035277999
`🍌` <- 36875131794129999827197811565225474825492979968971970996283137471637224634055579
`🍍` <- 4373612677928697257861252602371390152816537558161613618621437993378423467772036
print(`🍎` / (`🍌` + `🍍`) + `🍌` / (`🍎` + `🍍`) + `🍍`/(`🍎` + `🍌`)) # [1] 4Это числа от 79 знаков и больше! Где уж такое решить!