Эмодзи козла — валидный машинный код 8088. Я собрал из эмодзи целые программы

—

от автора

Осторожно: в этой статье сотни эмодзи. Если вы пользуетесь экранным диктором, проследите, чтобы он не зачитал их все вслух.

Целая куча эмодзи, выстроенных в длинную строку

Целая куча эмодзи, выстроенных в длинную строку

Целая куча эмодзи. Что бы они могли значить?

Этот пост взялся из ниоткуда. Я возился со своим веб-приложением, онлайн-дизассемблером для x86, и заметил, что эмодзи кодируются прямо в URL.

Вставил эмодзи козла 🐐 и увидел кодировку %F0%9F%90%90.

Если вы хоть немного знакомы с ассемблером x86, шестнадцатеричное 90h вам, скорее всего, встречалось. Это опкод пустой операции, NOP.

Я коротко хихикнул над мыслью, что козлы среди эмодзи играют роль NOP, а потом мне стало любопытно. F0h на 8088 это префикс LOCK. Обычно он нужен, чтобы согласовать монопольный доступ к шине с сопроцессором вроде 8087, а для большинства инструкций на 8088 ничего не делает и игнорируется (на более поздних процессорах Intel это изменится). Остаётся 9Fh. 9Fh это LAHF. Весь эмодзи козла оказывается корректным машинным кодом 8088, и читается эта последовательность так:

lock lahfnopnop

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

Можно ли написать программу для 8088, используя только отображаемые эмодзи?

У идеи есть прецеденты. Давно известно, что исполняемые файлы можно собирать только из печатных символов ASCII. Самый знаменитый пример, пожалуй, тестовый файл EICAR: ASCII-строка, которая одновременно служит рабочим исполняемым файлом DOS, печатает EICAR-STANDARD-ANTIVIRUS-TEST-FILE! и завершается. Другие маленькие ASCII-программы печатали в журналах или распространяли иными способами. Такова крошечная терминальная утилита TCOM, весь исходник которой приведён ниже:

XPHPD[0GG0G,0G51G31GB'(G+(G:u'0g?(G>(GE1G@arwIV_F*=US@>1|_,5wXNg-7muTu(41m0ss1k260s@3G1g360@3G0i7t2g3A1g350@3G2E1=0C1g350@3T2M0^\1g3>0@3T=1s2g0T1g3;0@3ToN2g391g0t@3G0^F1k0s2?0@3T4

Любопытное решение для «аварийного терминала»: если других способов загрузить исполняемый файл на компьютер нет, его можно просто ввести с клавиатуры.

Меня удивляет, что идею напрямую исполнять эмодзи, судя по всему, никто ещё не исследовал.

Hello (World)!

Разумеется, первым делом стоит попробовать Hello World! на эмодзи. Ради экономии места и отчасти из-за мучений с любой арифметикой на эмодзи мы выведем только строку HELLO.

Вот программа целиком:

🐸☺️🐰🐎♐🗃️🧯🧯🧯🐮💗🦮🪏♐🐰🐹🗃️🧯🧯🧯🧯💗🪗🧯😗🧮🫪😗🧮😗🐮😪😔⭐

Вставьте её в текстовый редактор и сохраните в UTF-8 без BOM с расширением .COM. Должен получиться файл размером 141 байт с суммой MD5 0a5c91475ca2de33e36aacc2f0b7b840.

Дизассемблированный листинг всей программы можно посмотреть здесь. Если эмодзи плохо копируются из текста, возьмите их по этой ссылке.

Некоторые эмодзи могут отображаться как «тофу», то есть пустые прямоугольники. Зависит от браузера и от того, в каком году вы это читаете.

  • 🪏 это лопата, она появилась в Unicode 16.0 в 2024 году. До обновлений шрифтов такие глифы доползают не сразу.

  • 🪗 это аккордеон, его добавили в Unicode 13.0 в 2020 году, но в Chrome на Windows 10 он почему-то до сих пор не виден. Поди разбери.

  • 🫪 это Distorted Face («Искажённое лицо»), совсем новый символ из Unicode 17.0, утверждённого в 2025 году.

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

Программа опирается на несколько недокументированных псевдонимов инструкций 8088, поэтому ей нужно достаточно точное ядро 8088. Посмотрим, что она делает в DOSBox-X с настройкой cpu cputype=8086:

Окно DOSBox-X: в правом нижнем углу экрана выведено слово HELLO, одна буква L зелёная

Окно DOSBox-X: в правом нижнем углу экрана выведено слово HELLO, одна буква L зелёная

Программа «Hello (World!)» выполняется в DOSBox-X

Обратите внимание, что программа начинается с 🐸☺️. Эта последовательность делает важную подготовку и объясняет, откуда берётся указатель на видеопамять. Эти эмодзи дают последовательность байтов F09F90B8E298BAEFB88F.

00000000  F0 9F     lahf00000002  90        nop00000003  B8 E2 98  mov ax,98E2h00000006  BA EF B8  mov dx,B8EFh00000009  8F        db 0x8F

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

Эмодзи 💗, он же F09F9297, переносит наш видеосегмент в DI.

0000012C  F0 9F  lahf0000012E  92     xchg dx,ax0000012F  97     xchg di,ax

Буквы синтезируются начиная с H. Здесь очень выручает 🗃️, он же F09F9783EFB88F:

00000146  83 EF B8  sub di,FFB8h

Вычесть FFB8h то же самое, что прибавить 48h. А какой ASCII-код у H? 48h. Изящно.

Остальные буквы приходится неуклюже собирать по одной. L, понятное дело, можно повторить. Вы заметите, что одна из L зелёная. Причина в том, что одна из инструкций LAHF перезаписывает AH. Так уж вышло, что содержимое регистра флагов даёт видимый байт атрибута символа, в данном случае зелёный. Атрибут можно было бы сбросить ценой ещё нескольких байтов, но мне, пожалуй, нравится это несоответствие. Маленький намёк на проклятые дела, которые творятся за кулисами.

Справочник по эмодзи-ассемблеру

Если вам хватит смелости поэкспериментировать с кодом на эмодзи самостоятельно, вот справочные материалы.

Самостоятельные эмодзи

Есть несколько самостоятельных эмодзи, которые дают полезные инструкции или пары инструкций.

Эмодзи

Байты UTF-8

Интерпретация на 8088

Полезный эффект и типичное применение

🐐

F0 9F 90 90

LAHF; NOP; NOP

Четырёхбайтовое заполнение. Ещё полезен внутри тела цикла, когда нужно точное смещение перехода.

🐮

F0 9F 90 AE

LAHF; NOP; SCASB

DI += 1. Маленькое чистое приращение указателя.

😯

F0 9F 98 AF

LAHF; CBW; SCASW

DI += 2. Плотнее двух 🐮; AX становится знаковым расширением AL.

🧮

F0 9F A7 AE

LAHF; CMPSW; SCASB

SI += 2, DI += 3. Полезно, когда SI тоже может сдвигаться. Читает DS:SI и ES:DI, меняет флаги.

🧯

F0 9F A7 AF

LAHF; CMPSW; SCASW

SI += 2, DI += 4. Компактный сдвиг на четыре байта. Также пригодится в случае 🔥.

🤐

F0 9F A4 90

LAHF; MOVSB; NOP

Копирует один байт из DS:SI в ES:DI, затем увеличивает оба указателя.

😬

F0 9F 98 AC

LAHF; CBW; LODSB

Загружает один байт из DS:SI в AL, затем увеличивает SI.

🐪

F0 9F 90 AA

LAHF; NOP; STOSB

Записывает AL в ES:DI, затем увеличивает DI.

😖

F0 9F 98 96

LAHF; CBW; XCHG AX,SI

Переносит знаково расширенный AL в SI, сохраняя старый SI в AX. Полезно после получения гарантированного нуля.

😗

F0 9F 98 97

LAHF; CBW; XCHG AX,DI

Передаёт знаково расширенный байт между AX и DI. Полезно, чтобы превратить AL=F0h в DI=FFF0h.

📗

F0 9F 93 97

LAHF; XCHG AX,BX; XCHG AX,DI

Прокручивает значения через AX, BX и DI. Записывающий байты код использует это, чтобы восстановить сохранённый указатель вывода и получить синтезированный байт в AL.

👁️

F0 9F 91 81 EF B8 8F

LAHF; XCHG AX,CX; SUB DI,8FB8h

Прибавляет 7048h к DI. Отлично подходит для больших сдвигов указателя по модулю; портит AX и CX.

Эмодзи с открытым хвостом

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

Эмодзи

Байты UTF-8

Открытый хвост

Типичное применение

🐸

F0 9F 90 B8

MOV AX,imm16 нужны два байта

Поглощает начало ☺️ и даёт MOV AX,98E2h.

☺️

E2 98 BA EF B8 8F

Первые два байта могут быть непосредственным значением; завершающему 8Fh нужен ModR/M

После 🐸 поставляет MOV AX,98E2h; MOV DX,B8EFh и открывает POP.

🐰

F0 9F 90 B0

MOV AL,imm8 нужен один байт

Поглощает следующий F0h или E2h в начале ☃️.

🐹

F0 9F 90 B9

MOV CX,imm16 нужны два байта

Поглощает заголовок F0 9F следующего эмодзи и загружает CX=9FF0h.

🐎

F0 9F 90 8E

MOV Sreg,r/m16 нужен байт ModR/M

Вместе с E2h из ♐ даёт псевдоним MOV ES,DX, который есть только на 8088.

😿

F0 9F 98 BF

MOV DI,imm16 нужны два байта

Поглощает заголовок F0 9F следующего эмодзи и сбрасывает DI=9FF0h.

🍽️

F0 9F 8D BD EF B8 8F

POP r/m16 нужен байт ModR/M

Сначала прибавляет B8EFh к DI; следующий F0h завершает недокументированный POP AX, поэтому SP += 2.

☃️

E2 98 83 EF B8 8F

Начинается и заканчивается байтами, предназначенными для соседей

После того как 🐰 поглотит его E2h, середина выполняет SUB DI,-72; завершающему 8Fh нужен ModR/M.

🗓️

F0 9F 97 93 EF B8 8F

Завершающие B8 8F поглощают следующий F0h

Сохраняет указатель вывода в BX, перенося аккумулятор байта в DI. Также выполняет OUT DX,AX.

⭐

E2 AD 90

Первые два байта это LOOP -83

Трёхбайтовый хвост цикла, когда тело цикла размещено точно на нужном смещении.

Полезные гаджеты

Это законченные полезные последовательности из нескольких эмодзи.

BunnySad: 🐰😔, починка стека

Эта восьмибайтовая последовательность намеренно заменяет текущий указатель стека на FFF0h:

0000: F0 9F    lahf0002: 90       nop0003: B0 F0    mov al,F0h0005: 9F       lahf0006: 98       cbw0007: 94       xchg sp,ax

Последний байт кролика B0h поглощает ведущий F0h грустного лица и загружает AL=F0h. Второй LAHF идёт перед CBW, который превращает значение в AX=FFF0h, а XCHG делает его указателем стека.

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

BunnySnowParty: 🐰☃️🐰😔, безопасное сложение DI += 48h

Эта 18-байтовая последовательность увеличивает DI на 48h (72 в десятичной системе), поглощает висящий POP снеговика и чинит стек:

0000: F0 9F       lahf0002: 90          nop0003: B0 E2       mov al,E2h0005: 98          cbw0006: 83 EF B8    sub di,FFB8h0009: 8F F0       pop ax000B: 9F          lahf000C: 90          nop000D: B0 F0       mov al,F0h000F: 9F          lahf0010: 98          cbw0011: 94          xchg sp,ax

Первый кролик поглощает E2h снеговика. B8h это знаковый непосредственный операнд -72, поэтому SUB DI,-72 прибавляет 72. Завершающий 8Fh снеговика поглощает F0h следующего кролика и даёт недокументированную кодировку POP AX в виде 8F F0. Последняя пара из кролика и грустного лица восстанавливает SP=FFF0h.

Это один из первых найденных гаджетов. Гаджеты с глазом и тарелкой обычно эффективнее, но этот приведён для полноты.

PlateGoat: 🍽️🐐, увеличение SP и сдвиг DI

Тарелке нужен следующий байт, чтобы завершить её последний 8Fh. Удобный безвредный хвост даёт козёл-заполнитель.

0000: F0 9F          lahf0002: 8D BD EF B8    lea di,[di-4711h]0006: 8F F0          pop ax0008: 9F             lahf0009: 90             nop000A: 90             nop

B8EFh это 16-битное представление -4711h, поэтому LEA выполняет DI += B8EFh. 8Fh тарелки поглощает ведущий F0h козла как недокументированный POP AX, а оставшиеся 9F 90 90 это LAHF; NOP; NOP.

Тарелки сдвигают SP на два и заодно перемещают DI на значительное расстояние. Для арифметики с указателями они превосходны, но их влияние на стек нужно учитывать.

CatGoat: 😿🐐, абсолютный сброс DI

Плачущий кот открывает MOV DI,imm16. Козёл-заполнитель поставляет непосредственный операнд.

0000: F0 9F       lahf0002: 98          cbw0003: BF F0 9F    mov di,9FF0h0006: 90          nop0007: 90          nop

Этот восьмибайтовый гаджет сбрасывает DI в 9FF0h независимо от прежнего значения. Если заменить козла другим эмодзи, его ведущие F0 9F всё равно станут операндом, но оставшиеся байты выполнятся как хвост и могут дополнительно изменить DI.

CamelWrite: 🗓️ + арифметика + 📗🐪, генерация и запись байта

Обобщённая форма занимает 15 фиксированных байтов плюс выбранную арифметическую последовательность. Вот простейший конкретный пример, 🗓️🐮📗🐪, где корова прибавляет единицу:

0000: F0 9F       lahf0002: 97          xchg di,ax0003: 93          xchg bx,ax0004: EF          out dx,ax      ; spurious OUT to B8EFh0005: B8 8F F0    mov ax,F08Fh0008: 9F          lahf0009: 90          nop000A: AE          scasb000B: F0 9F       lahf000D: 93          xchg bx,ax000E: 97          xchg di,ax000F: F0 9F       lahf0011: 90          nop0012: AA          stosb

На входе DI содержит настоящий указатель вывода, а AX содержит арифметическую затравку. 🗓️ переносит затравку в DI и сохраняет указатель вывода в BX.

Средняя последовательность эмодзи выполняет арифметику над этим временным DI. Корова в примере выше прибавляет единицу.

📗 восстанавливает указатель вывода и переносит вычисленный младший байт в AL, а 🐪 его записывает.

Календарь также выполняет OUT DX,AX. Стандартный запуск задаёт DX=B8EFh, порт, на который обычно ничего не отображено. На настоящем железе используйте с осторожностью!

FrogStrap: 🐸☺️😖🐰😗😯😯😯😯😯😯😯, общая инициализация регистров

Эта 50-байтовая последовательность получает гарантированный ноль из обычного стека при входе в COM-файл и задаёт определённое состояние регистров:

0000: F0 9F       lahf0002: 90          nop0003: B8 E2 98    mov ax,98E2h0006: BA EF B8    mov dx,B8EFh0009: 8F F0       pop ax000B: 9F          lahf000C: 98          cbw000D: 96          xchg si,ax000E: F0 9F       lahf0010: 90          nop0011: B0 F0       mov al,F0h0013: 9F          lahf0014: 98          cbw0015: 97          xchg di,ax0016: F0 9F       lahf0018: 98          cbw0019: AF          scasw001A: F0 9F       lahf001C: 98          cbw001D: AF          scasw001E: F0 9F       lahf0020: 98          cbw0021: AF          scasw0022: F0 9F       lahf0024: 98          cbw0025: AF          scasw0026: F0 9F       lahf0028: 98          cbw0029: AF          scasw002A: F0 9F       lahf002C: 98          cbw002D: AF          scasw002E: F0 9F       lahf0030: 98          cbw0031: AF          scasw

🐸☺️ загружает DX=B8EFh и оставляет висящий 8Fh. Первый байт 😖 завершает POP AX, получая гарантированный ноль по адресу SS:FFFEh и заворачивая SP в 0000h. Остальная часть 😖 переносит этот ноль в SI.

🐰 поглощает ведущий F0h из 😗, давая AL=F0h, после чего CBW; XCHG DI,AX устанавливает DI=FFF0h. Семь инструкций SCASW доводят его до FFFEh.

Итоговое состояние: DX=B8EFh, SI=0000h, DI=FFFEh и SP=0000h.

Значение B8EFh в DX, если использовать его как сегмент, попадает в нижнюю часть видеопамяти CGA.

Ещё один 😯 может прокрутить DI до 0000h. У значения FFFEh в DI есть вероятное применение в качестве константы -2.

🐸☺️🐰🐎♐, загрузка сегмента CGA

Эта 21-байтовая последовательность использует недокументированный псевдоним сегментного регистра исходного 8088 и задаёт ES=B8EFh:

0000: F0 9F       lahf0002: 90          nop0003: B8 E2 98    mov ax,98E2h0006: BA EF B8    mov dx,B8EFh0009: 8F F0       pop ax000B: 9F          lahf000C: 90          nop000D: B0 F0       mov al,F0h000F: 9F          lahf0010: 90          nop0011: 8E E2       mov es,dx0013: 99          cwd0014: 90          nop

Простой загрузчик

Честно говоря, писать прямо на эмодзи-ассемблере это мучительная каторга: ни нормальных непосредственных значений, ни арифметических операций, ни вменяемых смещений переходов. Поэтому разумно сделать загрузчик, который просто соберёт код 8088 в памяти и перейдёт на него.

Вся хитрость в том, как закодировать в эмодзи произвольные байты. Графем эмодзи меньше 4000, так что на 16-битную таблицу поиска они никак не тянут. Более того, в наборе четырёхбайтовых графем на третьей и четвёртой позициях встречаются далеко не все 256 восьмибитных значений. Однако по чистому везению 8-битную таблицу поиска можно построить из двухбайтовых хвостов набора из 256 уникальных эмодзи.

Основная идея такая:

bits 16org 0    push di    pop  si                         ; SI = encoded emoji data    mov  di,0100h    push di                         ; RET target after reconstruction    mov  cx,RAW_SIZE.decode:    lodsw                           ; discard the fixed F0 9F prefix    lodsw                           ; AL=third UTF-8 byte, AH=fourth    aad  8Fh                        ; AL=(AL + 8Fh*AH) & FFh; AH=0    stosb    loop .decode    ret                             ; execute reconstructed COM at 0100h

Первый lodsw читает двухбайтовый префикс каждой «графемы данных» и отбрасывает его. Второй lodsw читает 16-битный хвост, который преобразуется в 8-битное значение с помощью магической константы 8Fh. Ключевая деталь здесь это особенность инструкции aad на 8088: она позволяет передать недесятичное основание непосредственным операндом.

Разумеется, всё это не сработает, если lahf постоянно затирает AH, поэтому сам 17-байтовый декодер сначала нужно собрать в памяти. Это можно сделать описанным выше гаджетом CamelWrite.

Минус здесь в том, что эффективность закодированных данных всего 25%, но любой другой подход заметно усложнил бы декодер и, следовательно, код, который его выводит.

Демо для VGA на эмодзи

Можно ли сделать простенькое демо для VGA из одних эмодзи? С нашим эмодзи-декодером довольно просто упаковать простое демо для VGA, декодировать его в память и перейти на него.

Вот вся программа:

🐸☺️😖🐰😗😯😯😯😯😯😯😯😹😯🕳️😯🐮🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐⭐🍽️🍽️🍽️🍽️🐮🐰😔😬😬🗓️🍽️👁️📗🐪🗓️🧮🧯📗🐪🐮🗓️😿🧯🧯🧯🧯📗🐪🗓️🐮📗🐪🗓️🧮🧮🧯🧯👁️📗🐪🐮🗓️🧮🧯🧯🧯🧯🧯🧯📗🐪🗓️😿🧯🧯🧯🧯📗🐪🗓️😿🍽️🍽️🍽️🍽️🐮📗🐪🐮🗓️😯🍽️🍽️👁️📗🐪🐮🐮🐮🗓️😿🧮🧮🧮📗🐪🗓️🧮👁️👁️🍽️👁️📗🐪🐰😔🐐🐐♿🇹🇭⏪✋💕🐀🍥🐐📣🈚🌌🌋🏐🌕👻🌺🌻🍵🆙🌮🍝🌐🌋🍠🌋🐅🍜💒🌳👹🎇👹🉑🎎🉑💞🆖🌳🆎🎇👹🉑🎎🉑💞🐖👯🆖🌻🕕🌿🐐🍙👺👽🌳👹🎇💗🉑🎎🉑💞🖕🎎🌙👻🌺🌻🐻🎂🌻🌳👮🐖🐸🍤🕕🌻🐠🐻🍝🌻🌳🌷🐎🌷🍭🌌💗👻🐖🐖🌜🌛📛🍕🍓🍪🍷🌙🍘🍾🍪👻🌺🌻🌙🌘🌙🐗🌊🏐💗🎐🧯🔥🌉

Если сохранить её как COM-файл, размер должен быть 1092 байта, а сумма MD5 9ed65cc927b257b113a298dee37215cc. Полный дизассемблированный листинг можно посмотреть здесь. Если эмодзи плохо копируются из текста, возьмите их по этой ссылке.

Прим. пер.: на странице автора в этой строке есть десять лишних символов U+FE0F, и скопированный оттуда текст занимает 1122 байта. Мы взяли байты из файла в репозитории автора: 1092 байта, совпадают с дизассемблером по ссылке выше. Их MD5 равен 95482be7ae8d8ddcefca5a1ebbc7363f, это же значение указано в README репозитория. Сумма из поста с ними не сходится.

Эта программа запустится в любой версии DOSBox.

Не хочу портить вам сюрприз, если вы предпочтёте запустить её сами. А если готовы поверить на слово и посмотреть результат, откройте спойлер ниже.

Спойлер: нажмите, чтобы увидеть результат
Результат работы демо для VGA

Результат работы демо для VGA

Думаю, концепцию я доказал к собственному удовлетворению. Осталось разве что сделать более эффективный упаковщик и декодер, возможно, с компрессией LZ4. Утилита COM2EMOJI получилась бы довольно простой, а может, и EXE2EMOJI.

Можно ли собрать эмодзи-BIOS? Целую операционную систему на эмодзи? Будет ли у нас EmojiDOOM?

Другой исполняемый Unicode

Эмодзи не единственные графемы Unicode, которыми можно представить машинный код 8088. Следующие японские каны печатают в DOS «Hello World!».

ヹほむゐダぐビヘビヿぐツめぁツめしツめみギツめぁツめがツめみギツめぴツめみギツめぁツめけツめみギツめうギツめぁツめぼギツめぁツめぽギツめかツめみギツめぐギツめてツめみギツめぁツめぢツめみギツめぁツめぜツめみギツめぉギツめぁツめぬツめみギツめぐギツめふツめみギツめぁツめぬツめみギツめぁツめぢツめみギツめぉギツめぁツめちツめみギツめけギツめぁツめどギツめぇギツめごババババババババババババババババババババババ

Сохранённый как COM-файл, этот текст должен занимать 609 байт с суммой MD5 8df97d77cf17a9ad64b22d554eaebd37. Если не получается вставить символы, скопируйте их из дизассемблера здесь.

Следующий корейский хангыль тоже печатает «Hello World».

컓쿃뺰콙꾆퐀가긨숑낀가굀꿀꿨숑삺가꿀꿨숑킨숐뀺가꼀꿨숐쀺가가가가꺨숐퀀가가가깨숓넺가꼀꿨숓섺가김꿨숓턺가꿀꿨숒낺가가가가귀꿨숒삺가가가가깨숒킀가궨숑냀꺨숑샺가가꼀꿀꿨숑탺가곀꿀꿨숐끀걀꿀꿀꿀꿨숐쁺가가꼀꿀꿨숐큺가검꿀꿨숓녀깨숓셀가김꿀꿀꿨숓텀곀꿨숒냀글꿀꿀꿨숒샀귀꿀꿀꿨숒탺가글꿀꿨숑넀굀꿨숑섀관꿨숑턀가꿀꿀꿀꿨숐낀가귨숐삀괨숐킺가꿀꿨숓놀껨숓솀곀꿀꿀꿀꿨숓톀가가깨숒넀글꿀꿀꿨숒섀가글꿀꿨숒턺가글꿀꿨숑듀굀꿨숑쓀관꿨숑퓀가꿀꿀꿀꿨숐둺가가글꿨숐쑀궨숐푺가가검꿀꿨숓땻뀃밃밃뺃뿃뿃뿀가검꿨숗뀀가꺨숗쀀가글꿨숗퀐뀀

Сохранённый как COM-файл, этот текст должен занимать 768 байт с суммой MD5 b3b0a19cde830932f0b0d09ff8fd3d88. Дизассемблированный листинг здесь.

Новые примеры исполняемого Unicode я буду собирать в этом репозитории на GitHub.

ссылка на оригинал статьи https://habr.com/ru/articles/1104704/