Игра на повышение: как математики приносят миллиарды в казну через аукционы

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

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

Щетинина Анастасия, «GT Lab», экономическое консалтинговое агентство

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

Содержание:

  1. Общефилософское введение

  2. Краткое (прям микроскопическое) введение в теорию аукционов

  3. Какими они бывают и что почитать

  4. Что тут могут сделать математики

Общефилософское введение

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

 Теория аукционов — это триумф экономической науки, редкий случай, когда экономисты могут крайне точно спрогнозировать исход экономического взаимодействия. Аукционы давно используются для распределения благ, хотя у большинства людей аукционы всё ещё ассоциируются с продажей предметов искусства. Это лишь капля в море, отдельный специфический мир коллекционеров и материальных объектов, недоступных обывателю. Есть гораздо более крупные аукционы, как с точки зрения обращающихся денег, так и с точки зрения общественной значимости. Их называют ресурсными аукционами.

Краткое введение в теорию аукционов

В 2019 в России прошел самый крупный ресурсный аукцион в истории, где продавались квоты на вылов крабов. Представьте это так: государство делит морские территории на участки, внутри которых разрешен вылов морских обитателей (ими могут быть не только крабы). В случае, если фирма купит у государства возможность осуществлять вылов на этом участке в течение какого-то времени(квоту), это сулит ей многомиллиардную прибыль. Но конкуренция на рынке между рыболовными компаниями мешает каждой из компаний заполучить то количество квот, которое ей бы хотелось иметь. И мы понимаем, что, вообще говоря, конкуренция это хорошо и правильно, на конкурентном рынке с большей вероятностью будут устанавливаться «справедливые» цены, чем на монополистическом. Более того, присутствие нескольких компаний на рынке как правило положительно влияет на экономическую эффективность, поскольку тогда ресурсы скорее распределятся между наибилее эффективными (оптимально работающими) участниками рынка.

Перед государством, условным Росрыболовством в нашем случае, стоит задача: как правильно распределить эти квоты между несколькими конкурирующими компаниями? Ведь государство должно быть заинтересовано не только в максимизации выручки от продаж, но и в эффективности получившегося распределения. Это значит, что играет роль также способность компаний правильно распорядиться полученными ресурсами. Решение может показаться, на первый взгляд, достаточно тривиальным: должен использоваться аукцион. Математически доказано, что именно аукцион является оптимальным механизмом для распределения благ. Однако задача сразу перестаёт быть такой простой, если учесть, что существует множество типов аукционов, и все они приводят к совершенно разным результатам. Финальная формулировка вопроса, который могут решить учёные-игровики, звучит так: какой механизм (какой тип аукциона) следует использовать в каждом конкретном случае с учётом запроса заказчика? Заказчик, то есть организация, которая проводит аукцион, может преследовать разные цели, вот некоторые из них:

  • максимизация прибыли

  • снижение вероятности сговора между участниками аукциона

  • получение эффективного распределения квот между участниками рынка

Тогда как первые два пункта кажутся интуитивно понятными, последний стоит расшифровать. Экономическая эффективность – это вообще одно из главный понятий, которыми оперируют экономисты. В контексте аукционов это подразумевает, что квоты в итоге достанутся тем участникам аукциона, которые больше всего их ценят. Почему это называется эффективным распределением? Потому что если компания может наилучшим образом распрядиться квотой (то есть у неё лучшая бизнес-модель), она будет готова заплатить за квоту наибольшую цену. Исходя из интуитивных представлений о том, что общественное благосостояние растёт, когда больший объем ресурсов распределяется эффективно, мы можем сделать вывод, что вообще-то это хорошо. Потому что общественное благосостояние это хорошо и важно.

Коротко о вариативности аукционов

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

Для экономистов и математиков — Auction Theory, Vijay Krishna

Auctions: Theory and Practice (The Toulouse Lectures in Economics), Paul Klemperer

В жанре науч-поп — Савватеев, Филатов: Занимательная экономика. Теория экономических механизмов от А до Я

А также небольшую и очень понятную для неподготовленного читателя статью моих коллег:

Крабовый аукцион 2019: история, оценка и альтернативные сценарии. Иванов Д.И., Калинин Н.С., Нестеров А. С., Сусин И.С.

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

Таблица взята из статьи "Крабовый аукцион 2019: история, оценка и альтернативные сценарии. Иванов Д.И., Калинин Н.С., Нестеров А. С., Сусин И.С."

Таблица взята из статьи «Крабовый аукцион 2019: история, оценка и альтернативные сценарии. Иванов Д.И., Калинин Н.С., Нестеров А. С., Сусин И.С.»

 

Методы для проведения такой сравнительной аналитики могут использоваться разные, например анализ данных прошлых подобных аукционов или построение симуляций.

Кроме того, есть особые методы, через которые аукционист может воздействовать на поведение игроков во время торгов. Я выделю два из них, оба из которых применялись в Крабовом аукционе 2019 года:

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

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

Как же учёные могут повлиять на исход аукциона?

А повлиять они могут сразу с двух сторон: с одной стороны, они могут выступать дизайнерами механизма. Это происходит в том случае, если учёные привлекаются в качестве экспертов для проведения аукциона. Тогда они могут предложить аукционисту тот тип и формат аукциона, который будет согласовываться с приоритетом его запросов (см. 3 пункта из введения в теорию аукционов)

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

  1. Фирма может не знать, за какие именно лоты стоит торговаться.

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

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

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

Так наши специалисты в Крабовом аукционе 2019 года помогли одной из Российских рыболовных компаний снизить в процессе торгов среднюю цену лота на 5 процентов. Может показаться: всего каких-то пять процентов! И из-за этого стоило нанимать команду математиков? На деле для компании это вылилось в 2 миллиарда сэкономиленных рублей (оценка, полученная после завершения торгов).

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

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

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

P.S. Следующая статья про биоинформатику и биомедицину в Сириусе и Сеченовке.

P.S.S.S.S…. Как всегда, телеграм: https://t.me/ninelived


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

Нет ветвлений? Нет проблем — Форт-ассемблер

Нет ветвлений? Нет проблем — Форт-ассемблер

Перевод
Оригинальный текст:
22 июня 2021 г. · 36 минут чтения

Эта статья является частью серии «Начальная загрузка» , в которой я начинаю с 512-байтного начального числа и пытаюсь загрузить реальную систему.

Предыдущий пост:
Разместить FORTH в 512 байтах
Следующий пост:
Ветвление: сборка не требуется

Набор слов, доступных после загрузки Miniforth, довольно скуден. Один читатель даже заявил , что, поскольку ветвей нет, он не является полным по Тьюрингу и, следовательно, не достоин называться Фортом! Сегодня тот день, когда мы докажем, что они ошибались.

В предыдущем посте я описал ядро Miniforth размером с загрузочный сектор со всеми хитроумными оптимизациями, которые мне пришлось использовать, чтобы вместить его. Подводя итог, доступны следующие слова:

+ - ! @ c! c@ dup drop swap emit u. >r r> [ ] : ; load s: 

Большинство из них будут знакомы программистам на Forth, но loadмогут s:нуждаться в некоторых комментариях. load ( u -- )является стандартным словом из необязательного набора слов Block — оно загружает блок uи выполняет его как исходный код Forth. 1 Это слово имеет решающее значение для практического использования такого маленького Форта, поскольку, как только вы загрузитесь достаточно далеко, вы можете сохранить свой код на диск, а после перезагрузки возобновить работу с помощью всего лишь 1 load.

Однако, чтобы добраться до этой точки, вам нужно написать довольно много кода. Чтобы сделать исходный код доступным в памяти, как только вы сможете его сохранить, я включил s: ( buf -- buf+len ), что, по сути, представляет собой ввод строки — остальная часть входного буфера копируется в buf. Адрес конца буфера остается в стеке, чтобы его можно было использовать s:на следующей строке, и результат будет конкатенирован.

В этом посте мы начнем с состояния, в котором загружается Miniforth, и:

Нельзя сказать, что это единственный способ. У меня есть реализация ветвей на чистом Форте поверх Miniforth, и я намерен поговорить о ней подробнее примерно через неделю, а пока рекомендую вам попробовать разобраться с этим самостоятельно. Мне действительно любопытно, сколько существует различных подходов.

Тем временем давайте рассмотрим подход, который не отказывается от большей части производительности во имя чистоты. Для ознакомления и удобства экспериментов код из этого поста доступен на GitHub . При объяснении кода я иногда добавляю комментарии, но, поскольку мы еще не реализовали обработку комментариев, на самом деле их нет в коде.

s:- рабочий процесс

Я решил хранить свой исходный код по адресу 1000, в пространстве между стеками параметра и возврата. Первое, что нам понадобится, — это способ запуска кода, который мы туда поместили. Определено InputPtr, чтобы быть по адресу A02, поэтому давайте определим run, который подставляет значение по нашему выбору по этому адресу:

: >in A02 ;  : run >in ! ; 

>in— это традиционное имя для указателя входного буфера, поэтому я выбрал его. 2 Чтобы убедиться, что он также доступен при последующих загрузках, я сохраняю этот фрагмент кода в памяти:

1000 s: : >in A02 ;  : run >in ! ; 

Это хорошее время для просмотра текущего указателя на исходный буфер с помощью dup u.. Если вы не добавили некоторое пространство для записи, ответ будет 101A, и это адрес, на который мы хотим перейти runпозже, чтобы избежать переопределения >inи run. 3

Написав достаточно кода, чтобы протестировать его, я печатал текущий адрес буфера с помощью u., а затем runновый код из предыдущего напечатанного адреса буфера. Во-первых, важно, чтобы адрес буфера не оставался наверху стека, так как Miniforth загружается с адресами встроенных системных переменных в стеке , и мы хотим получить к ним доступ.

Системные переменные

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

latest st base dp disk# 

Обычно мы просто делаем constant disk#, constant hereи так далее. Однако у нас нет constant, или какого-либо способа его определения (пока). literalближе, но нам нужно по крайней мере hereреализовать его и latestпометить как немедленное. Мы можем обойти насущную проблему с помощью [и ], что предполагает следующий порядок действий:

swap : dp 0 [ dup @ 2 - ! ] ; 

Давайте рассмотрим это шаг за шагом, так как это работает довольно сложно. dpозначает указатель данных . Это переменная back here, указатель компиляции, значение которого hereпросто определяется как

: here dp @ ; 

Когда выполняется код внутри квадратных скобок, наша память выглядит так:

Сначала идет заголовок словаря, содержащий поле ссылки и имя.  Затем вызов DOCOL, LIT и 0. HERE указывает на самый конец, после 0.

Сначала идет заголовок словаря, содержащий поле ссылки и имя. Затем вызов DOCOL, LIT и 0. HERE указывает на самый конец, после 0.

То, что мы хотим сделать, это поставить dpтам, где 0в настоящее время. Так как мы запустили swapперед определением нашего слова, адрес dpнаходится на вершине стека. После dup @ 2 -у нас будет указатель на ячейку, содержащую 0, и !мы перезапишем ее. Как видите, the 0не имеет особого значения, мы могли бы использовать любой литерал.

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

: cell+ 2 + ; : cells dup + ; 

Кроме того, поскольку у нас теперь есть dp, давайте напишем allot. Функциональность увеличения переменной может быть выделена в +!:

: +! ( u addr -- ) dup >r @ + r> ! ; : allot ( len -- ) dp +! ; 

Это позволяет определить c,и ,, которые записывают байт или ячейку соответственно в область компиляции:

: c, here c! 1 allot ; : , here ! 2 allot ; 

Далее мы напишем lit,, который добавляет литерал к текущему определению. Для этого нам нужен адрес LITассемблерной процедуры, которая обрабатывает литерал. Мы сохраняем его в 'lit«константе» с помощью трюка, аналогичного тому, что мы сделали для dp:

: 'lit 0 [ here 4 - @ here 2 - ! ] ; : lit, 'lit , , ; 

Это позволяет нам легко обрабатывать остальные переменные в стеке:

: disk# [ lit, ] ; : base [ lit, ] ; : st [ lit, ] ; : latest [ lit, ] ; 

Я вызываю его stвместо state, потому что stateэто должна быть переменная размером с ячейку, где true означает компиляцию, а stпеременная размером с байт, где true означает интерпретацию.

Пользовательские переменные

Если вы в настроении пошалить, вы можете создать переменные из воздуха, просто упомянув их. Отсутствие проверки ошибок превратит их в число, по сути, дав вам случайный адрес. Например, srcpos u.выходы DA9C. Конечно, вы рискуете тем, что эти адреса будут конфликтовать либо друг с другом, либо с чем-то еще, например со стеком или пространством словаря.

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

: [[ 1 st c! ; 

Нам также понадобится непрямой вариант ;. Единственное, что нужно сделать, это скомпилировать exit. Мы не знаем адрес exit, но можем прочитать его из последнего скомпилированного слова:

here 2 - @ : 'exit [ lit, ] ; 

Например, вот как мы будем использовать его для constant:

: constant \ example: 42 constant the-answer   : [[ lit, 'exit , ; 

createопределяет слово, которое помещает адрес сразу после него. Типичное использование

create some-array 10 cells allot 

Чтобы вычислить адрес, который мы должны скомпилировать, нам нужно добавить 3 cells— по одному для каждого из LIT, фактического значения и EXIT.

: create : [[ here 3 cells + lit, 'exit , ; 

variable, то просто allotодна ячейка:

: variable create 1 cells allot ; 

Улучшениеs:

До сих пор указатели передавались s:и runуправлялись вручную. Однако это простой процесс, поэтому давайте его автоматизируем. srcposбудет содержать текущий конец буфера и checkpointбудет указывать на часть, которая еще не была запущена.

То есть в типичной ситуации исходный код начинался бы с 1000, заканчивался бы на srcpos, с контрольной точкой где-то посередине.

То есть в типичной ситуации исходный код начинался бы с 1000, заканчивался бы на srcpos, с контрольной точкой где-то посередине.
variable checkpoint variable srcpos 

Автоматический вариант s:называется s+:

: s+ ( -- ) srcpos @ s: dup u. srcpos ! ; 

Мы также печатаем новый указатель. Это имеет два применения:

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

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

Отложенная часть буфера может быть выполнена с помощью doit:

: move-checkpoint ( -- ) srcpos @ checkpoint ! ; : doit ( -- ) checkpoint @ run move-checkpoint ; 

Настройка этого сводится к чему-то вроде

1234 srcpos ! move-checkpoint 

Эта строка не записывается на диск, так как после перезагрузки точный адрес не пригодится.

Ассемблер четвертого стиля

Обычный синтаксис сборки выглядит так:

    mov ax, bx 

Если бы мы хотели справиться с этим , нам пришлось бы написать модный синтаксический анализатор, а мы никак не сможем сделать это без ветвей. Вместо этого давайте настроим синтаксис для наших целей — если AT&T разрешено это делать, то и мы тоже. Чтобы быть конкретным, давайте сделаем каждую инструкцию Форт-словом, передав аргументы через стек:

    bx ax movw-rr, 

Я решил упорядочить аргументы как src dst instr,, с потоком данных слева направо. Это согласуется с тем, как данные передаются в обычном коде Forth, и является точным отражением синтаксиса Intel. После дефиса я включаю типы аргументов в том же порядке — регистр ( r), память ( m) или непосредственный ( i). Наконец, инструкции, которые могут быть размером как в байт, так и в слово, имеют суффикс bили w, как в синтаксисе AT&T.

Обратите внимание, что необходимость указывать типы операндов вручную не является фундаментальным ограничением ассемблеров Forth. Обычно ничто не мешает встроить в эти слова больше ума, чтобы автоматически подобрать правильный вариант на основе операндов. Однако в данном конкретном случае у нас нет ветвящихся слов (поскольку они и есть наша цель 😄).

кодировка инструкций x86

Проще всего кодировать инструкции, которые не принимают никаких аргументов. Например,

: stosb, AA c, ;  : stosw, AB c, ;  : lodsb, AC c, ;  : lodsw, AD c, ; 

Следующими по простоте являются инструкции, включающие непосредственные аргументы — числовые аргументы, которые идут сразу после кода операции:

: int, CD c, c, ; 

Некоторые инструкции используют битовое поле в байте кода операции. Например, немедленная загрузка, такая как mov cx, 0x1234`, кодирует регистр младшими 3 битами кода операции:

Младшие 3 бита кода операции инструкции «mov r16, imm16» содержат номер регистра, а остальные постоянны.

Младшие 3 бита кода операции инструкции «mov r16, imm16» содержат номер регистра, а остальные постоянны.

Регистры сопоставляются со следующими числовыми значениями:

: ax 0 ;  : cx 1 ;  : dx 2 ;  : bx 3 ;  : sp 4 ;  : bp 5 ;  : si 6 ;  : di 7 ; 

Вы правильно прочитали, это идет AX CX DX BX. Насколько мне известно, это не потому, что кто-то в Intel забыл свои азбуки, а потому, что этимология этих имен регистров выглядит примерно так: «Аккумулятор , Счетчик , Данные , База » , и тот факт, что они являются первые четыре буквы просто совпадение. Или, во всяком случае, в этом суть. Этот пост на retrocomputing.SE содержит некоторые предположения о том, как это может быть полезно для конструкции оборудования, но не содержит твердых фактов.

Соответствующая нумерация для байтовых регистров выглядит так:

: al 0 ;  : cl 1 ;  : dl 2 ;  : bl 3 ;  : ah 4 ;  : ch 5 ;  : dh 6 ;  : bh 7 ; 

Таким образом, мы можем закодировать некоторые movs:

: movw-ir, B8 + c, , ; : movb-ir, B0 + c, c, ; 

Их можно использовать так:

ACAB bx movw-ir, 42 al movb-ir, 

Обратите внимание, что ответственность за использование 8-битного регистра с movb, и 16-битного регистра с movw.

Некоторые другие инструкции, которые закодированы таким образом, incw/decwи push/pop:

: incw, 40 + c, ; : decw, 48 + c, ; : push, 50 + c, ; : pop,  58 + c, ; 

ModR/M

Самые сложные инструкции, с которыми нам придется иметь дело, используют байт ModR/M . Это механизм кодирования, отвечающий за такие инструкции, как add ax, [bx+si+16], но также и за такие простые, как mov ax, bx.

Сам код операции определяет шаблон, например mov r16, r/m16. В данном случае это означает, что адресатом является регистр, а источником является либо регистр, либо память. Байт ModR/M, который следует за кодом операции, определяет детали операндов:

Байт ModR/M идет сразу после кода операции.  Это битовое поле с тремя полями.  Старшие биты 7 и 6 образуют поле mod. Вместе с младшими тремя битами оно определяет режим адресации для операнда r/m.  Три бита в середине определяют другой операнд, который всегда является регистром.

Байт ModR/M идет сразу после кода операции. Это битовое поле с тремя полями. Старшие биты 7 и 6 образуют поле mod. Вместе с младшими тремя битами оно определяет режим адресации для операнда r/m. Три бита в середине определяют другой операнд, который всегда является регистром.

Три бита в середине определяют r16часть, а остальные определяют часть r/m16в соответствии с этой таблицей:

поле reg/[regs]

mod: 00

mod: 01

mod: 10

mod: 11

0

[BX+SI]

[BХ+SI+d8]

[BХ+SI+d16]

AL/AX

1

[BX+DI]

[BХ+DI+d8]

[BХ+DI+d16]

CL/CX

2

[BP+SI]

[BP+SI+d8]

[BP+SI+d16]

DL/DX

3

[BP+DI]

[BP+DI+d8]

[BP+DI+d16]

BL/BX

4

[SI]

[SI+d8]

[SI+d16]

АХ/SP

5

[DI]

[DI+d8]

[DI+d16]

CH/BP

6

[d16]

[BP+d8]

[BP+d16]

DH/SI

7

[BХ]

[BХ+d8]

[BХ+d16]

BH/DI

Как видите, если в поле mod установлено значение 3, то младшие 3 бита просто кодируют другой регистр в том же порядке, что и раньше. В противном случае мы выбираем одну из восьми возможностей для вычисления адреса с необязательным смещением, которое может быть либо 8, либо 16 бит. Упомянутое смещение идет сразу после байта ModR/M и при необходимости расширяется по знаку до 16 бит.

Есть одна неточность: если мы попытаемся закодировать a [BP]без какого-либо смещения, вместо этого мы получим жестко закодированный адрес, такой как mov bx, [0x1234], который должен идти после самого байта ModR/M. 4 Если вы помните, именно из-за отсутствия было выгодно [BP]переключение стека возврата на использование вместо него.DI

Специфическим аспектом этого кодирования является то, что операции между регистрами могут быть закодированы двумя разными способами. Возьмем xor cx, dx, например:

С одной стороны, вы можете использовать код операции «xor r/m16, r16» и поместить DX в поле регистра, а CX — в поле r/m.  Это дает байты 31 D1.  С другой стороны, вы можете использовать код операции «xor r16, r/m16» и соответствующим образом переупорядоченный байт ModR/M для кодирования той же инструкции, что и 33 CA.

С одной стороны, вы можете использовать код операции «xor r/m16, r16» и поместить DX в поле регистра, а CX — в поле r/m. Это дает байты 31 D1. С другой стороны, вы можете использовать код операции «xor r16, r/m16» и соответствующим образом переупорядоченный байт ModR/M для кодирования той же инструкции, что и 33 CA.

В любом случае, давайте это реализуем. Во-первых, вариант от регистрации к регистрации. Я выбрал слово для компиляции такого байта ModR/M , означающее, что в поле rm-r,есть регистр, который также может быть emory, за которым следует еще один регистр. У нас нет битовых смещений, но мы можем обойти это повторным добавлением:r``m``r

: 2* dup + ; : 3shl 2* 2* 2* ; : rm-r, ( reg-as-r/m reg -- ) 3shl + C0 + c, ; 

При использовании rm-r,нам нужно убедиться, что используемый код операции соответствует шаблону r/m16, r16— в противном случае нам потребовались бы swapдва регистра:

: movw-rr, 8B c, rm-r, ; : addw-rr, 03 c, rm-r, ; : orw-rr, 0B c, rm-r, ; : andw-rr, 23 c, rm-r, ; : subw-rr, 2B c, rm-r, ; : xorw-rr, 33 c, rm-r, ; : cmpw-rr, 3B c, rm-r, ; 

Варианты памяти для регистрации не намного сложнее. Мы определяем режимы адресации так же, как мы это делали для регистров.

: [bx+si] 0 ;  ; [bx+di] 1 ;  ; [bp+si] 2 ;  ; [bp+di] 3 ; : [si] 4 ;  ; [di] 5 ;  ; [#] 6 ;  ; [bp] 6 ;  ; [bx] 7 ; 

[#]режим абсолютного адреса, который следует использовать, собирая адрес вручную после инструкции, например

[#] ax movw-mr, some-addr , 

Я также включаю [bp], который конфликтует с [#], так как слова режима адреса могут использоваться совместно с режимами [??+d8]и [??+d16].

Аналогично rm-r,имеем m-r,:

: m-r, ( mem reg -- ) 3shl + c, ; 

r-m,то же самое, просто поменяйте местами операнды:

: r-m, ( reg mem -- ) swap m-r, ; 

Нет необходимости определять каждую инструкцию с операндами памяти, movдостаточно просто s:

: movw-mr, 8B c, m-r, ; : movw-rm, 89 c, r-m, ; 

Существует также одно несколько иное использование байта ModR/M. А именно, если инструкции требуется только один операнд (например, not bxили jmp ax), r/mфактически используется только он. В этом случае поле регистра вместо этого повторно используется как дополнительные биты для самого кода операции.

В руководстве Intel для этого используется обозначение opcode /regbits. Например, непрямой переход — это FF /4, а непрямой вызов — это FF /2совместное использование основного байта кода операции. Мы можем кодировать такие инструкции, просто введя нужное значение перед вызовом rm-r,.

: jmp-r, FF c, 4 rm-r, ; : notw-r, F7 c, 2 rm-r, ; 

Чтобы на самом деле собрать примитивное слово, нам также понадобится способ создания его заголовка. Самый простой способ сделать это — вызвать normal :, а затем перемотать dpна три байта назад, чтобы удалить вызов DOCOL:

: :code : [[ here 3 - dp ! ; 

Чтобы закончить такое определение, мы компилируем NEXT:

: next, lodsw, ax jmp-r, ; 

Обратите внимание, что next,не определяется с помощью :code— это эквивалент макроса ассемблера.

В качестве примера простого собранного примитива рассмотрим реализацию 1+:

:code 1+ bx incw, next, 

Дисковый ввод-вывод

На самом деле этого достаточно, чтобы записать нашу работу на диск. Как и в случае с load, нам нужно создать пакет адресов дисков, а затем вызвать int 0x13. Одно примитивное слово может служить как для чтения, так и для записи, поскольку единственная разница заключается в значении, которое AXвам нужно. Крайне важно сохранить SI— я имел неудовольствие узнать это эмпирически .

create packet 10 allot :code int13   si push,              \ push si   packet si movw-ir,    \ mov si, packet   bx ax movw-rr,        \ mov ax, bx   disk# dl movb-ir,     \ mov dl, disk#   13 int,               \ int 0x13   ax bx movw-rr,        \ mov bx, ax   si pop,               \ pop si next, 

Обратите внимание, что мы сохраняем возвращаемое значение AXback в стеке. Это связано с тем, что ненулевое AHзначение сигнализирует об ошибке.

Чтобы заполнить packetданные, я использую вариант, ,который записывает в контролируемое место вместо here:

variable pos : pos, ( val -- ) pos @ ! 2 pos +! ; : make-packet ( block buffer -- )   packet pos !   10 pos, \ size of packet   2 pos,  \ sector count   pos, 0 pos, \ buffer address   2* pos, 0 pos, 0 pos, 0 pos, \ LBA ; 

Для чтения мы используем AH = 0x42, как и раньше. Запись использует AH = 0x43, но в этом случае значение определяет, ALхотим ли мы, чтобы BIOS проверял запись — мы делаем это, поэтому я установил для него значение 0x02.

: read-block make-packet 4200 int13 ; : write-block make-packet 4302 int13 ; 

Меры предосторожности

Было бы неплохо убедиться, что наш новый код собран правильно, прежде чем запускать его. В идеале мы бы написали небольшую утилиту hexdump, но у нас пока нет никакого способа зациклиться. Однако есть способ обойти это — просто введите нужное слово несколько раз подряд:

: p ( buf -- buf+1 ) dup c@ u. 1 + ; \ later... here 10 - p p p p p p p p p p p p p p p p drop 

Еще одна хорошая проверка работоспособности — убедиться, что ничего, чего мы не ожидали, не было помещено в стек — обычно это происходит из-за того, что неопределенные слова плохо преобразуются в числа. Это можно сделать следующим образом dup u.: пустой стек приведет к ответу E0E, происходящему из-за безобидного опустошения стека, которое мы только что вызвали. Одним из примеров обнаруженной ошибки является опечатка, когда я набрал movb-it,вместо movb-ir,.

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

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

Первый доступ к диску, который я попробовал, был 0 4000 read-block u. 41fe @ u.. Это показывает AA55магическое число в конце загрузочного сектора. Затем я записал свой исходный код в блоки 1 и 2 и прочитал их в отдельный буфер, чтобы убедиться, что он работает. Оглядываясь назад, возможно, было бы неплохо прочитать блок, отличный от 0, перед попыткой записи, чтобы убедиться, что предоставление LBA работает правильно. К счастью, эта конкретная ошибка была чисто гипотетической.

Я также записал те же данные в блоки 0x101 и 0x102. Таким образом, я могу восстановиться, если когда-нибудь сломаю загрузку с обычными номерами блоков.

Прыжки

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

Чтобы быть конкретным, значение относится к концу инструкции перехода, так что оно соответствует количеству пропущенных байтов в случае перехода вперед:

74 02 кодирует условный переход, который пропускает следующие 2 байта инструкций.  74 FD, который равен -3 в дополнении до двух, создаст петлю с еще одним байтом в нем, а также с двумя байтами перехода.

74 02 кодирует условный переход, который пропускает следующие 2 байта инструкций. 74 FD, который равен -3 в дополнении до двух, создаст петлю с еще одним байтом в нем, а также с двумя байтами перехода.

Чтобы составить дистанции прыжков, я использую две пары слов — одну для прыжков вперед, а другую для прыжков назад:

jnz, j> ... >j \ forward jump j< ... jnz, <j \ backward jump 

Правило состоит в том, что стрелки показывают направление прыжка, и стрелки должны быть «внутри» — другими словами, если вы получили два слова рядом друг с другом, эти стрелки должны подойти как влитые. Два слова просто общаются через стек. Например, j<просто запомнит текущее местоположение:

: j< here ; 

Затем это используется функцией <j, которая вычитает текущую позицию и компилирует смещение:

: <j here 1 + - c, ; 

Для прыжков вперед мы составляем фиктивное смещение, чтобы переписать его позже:

: j> here 0 c, ; : >j dup >r 1 + here swap - r> c! ; 

Наконец, сами инструкции по прыжкам. Некоторые прыжки имеют несколько названий. Например, поскольку флаг переноса устанавливается, когда при вычитании требуется заимствование, a jcведет себя точно так же, как беззнаковое сравнение jump, если below. То же самое относится к jeи jz, но это достаточно интуитивно для меня, поэтому я не чувствовал необходимости определять оба имени.

: jb, 72 c, ;  ; jc, 72 c, ;  ; jae, 73 c, ;  ; jnc, 73 c, ; : jz, 74 c, ;  ; jnz, 75 c, ;  ; jbe, 76 c, ;  ; ja, 77 c, ; : jl, 7C c, ;  ; jge, 7D c, ;  ; jle, 7E c, ;  ; jg, 7F c, ; 

Ветви

При компиляции в определение ветки выглядят так:

Диаграмма демонстрирует стратегию компиляции структуры if-else.  IF компилируется в две ячейки, где первая — (0branch), а вторая — цель перехода, которая указывает сразу после ELSE.  Перед этой целью перехода ELSE вводит безусловное (ответвление) в позицию THEN.

Диаграмма демонстрирует стратегию компиляции структуры if-else. IF компилируется в две ячейки, где первая — (0branch), а вторая — цель перехода, которая указывает сразу после ELSE. Перед этой целью перехода ELSE вводит безусловное (ответвление) в позицию THEN.

По соглашению имена слов, которые компилируются в определение, но не используются напрямую, заключены в круглые скобки, поэтому наши ветки называются (branch), что является безусловным, и (0branch), что выталкивает значение из стека и выполняет ветки, если оно равно нулю.

Мы можем прочитать цель перехода из последовательности указателей с помощью lodsw:

:code (branch)   lodsw,           \ lodsw   ax si movw-rr,   \ mov si, ax next, 

В случае условного перехода важно всегда читать (или пропускать) цель перехода, независимо от того, верно ли условие перехода.

:code (0branch)   lodsw,           \ lodsw   bx bx orw-rr,    \ or bx, bx   jnz, j>          \ jnz .skip   ax si movw-rr,   \ mov si, ax >j               \ .skip:   bx pop,          \ pop bx next, 

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

: br> here 0 , ; : >br here swap ! ; : br< here ; : <br , ; 

Поток управления

Чтобы логика, которая компилирует ifs, действительно выполнялась во время компиляции, нам нужно пометить эти слова как немедленные. Для этого мы используем immediate, который устанавливает непосредственный флаг последнего скомпилированного слова:

: immediate ( -- )   latest @      \ получить указатель на слово   cell+         \ пропустить поле ссылки   dup >r c@     \ прочитать текущее значение  из length+flags поля   80 +          \ установить flag   r> c!         \ запись обратно ; 

Нам также понадобится compile, который при вызове как compile xдобавляется xк слову, которое компилируется в данный момент. На самом деле нам не нужно делать его непосредственным словом, которое само по себе анализирует следующее слово, достаточно просто прочитать адрес xlike litили do it:(branch)

: compile r> dup cell+ >r @ , ; 

ifэто просто условная прямая ветвь:

: if compile (0branch) br> ; immediate : then >br ; immediate 

elseнемного сложнее. Нам нужно скомпилировать безусловную ветвь, переходящую к then, а также разрешить ifпереход к точке сразу после безусловного перехода. Мне нравится использовать для этого слова манипулирования стеком возврата, поскольку стрелки совпадают со стрелками, используемыми >brи облегчают чтение кода:

: else >r compile (branch) br> r> >br ; immediate 

Далее нам понадобятся циклы. Во-первых, простой begin ... againбесконечный цикл:

: begin br< ; immediate : again compile (branch) <br ; immediate 

begin ... untilне намного сложнее — просто используйте условный переход в конце:

: until compile (0branch) <br ; immediate 

Наконец, уникальный цикл Форта begin ... while ... repeat, где условие цикла находится в середине цикла:

Диаграмма иллюстрирует стратегию компиляции для BEGIN-WHILE-REPEAT.  BEGIN ничего не компилирует, а просто сохраняет местоположение.  WHILE выполняет (0ветвь) после цикла, а REPEAT выполняет безусловную (ветвь) обратно к точке НАЧАЛА.

Диаграмма иллюстрирует стратегию компиляции для BEGIN-WHILE-REPEAT. BEGIN ничего не компилирует, а просто сохраняет местоположение. WHILE выполняет (0ветвь) после цикла, а REPEAT выполняет безусловную (ветвь) обратно к точке НАЧАЛА.
: while ( backjmp -- fwdjmp backjmp )   compile (0branch) br> swap ; immediate : repeat ( fwdjmp backjmp -- )   compile (branch) <br >br ; immediate 

Сравнения

Ветвление не так уж полезно без возможности сравнивать вещи. Одной из общих проблем среди всех слов сравнения является превращение флага процессора в логическое значение Forth. Вспомним, что в Форте все биты логических значений либо установлены, либо не установлены:

: false 0 ; : true FFFF ; 

Я решил сгенерировать эти логические значения, сначала установив axзначение 0, а затем, возможно, уменьшив его на основе результата сравнения. Этот код можно разложить следующим образом:

: :cmp :code ax ax xorw-rr, ; : cmp; j> ax decw, >j ax bx movw-rr, next, ; 

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

:cmp 0= bx bx orw-rr, jnz, cmp; :cmp 0<> bx bx orw-rr, jz, cmp; :cmp 0< bx bx orw-rr, jge, cmp; :cmp 0<= bx bx orw-rr, jg, cmp; :cmp 0> bx bx orw-rr, jle, cmp; :cmp 0>= bx bx orw-rr, jl, cmp; :cmp = cx pop, bx cx cmpw-rr, jnz, cmp; :cmp <> cx pop, bx cx cmpw-rr, jz, cmp; :cmp u< cx pop, bx cx cmpw-rr, jae, cmp; :cmp u<= cx pop, bx cx cmpw-rr, ja, cmp; :cmp u> cx pop, bx cx cmpw-rr, jbe, cmp; :cmp u>= cx pop, bx cx cmpw-rr, jb, cmp; :cmp < cx pop, bx cx cmpw-rr, jge, cmp; :cmp <= cx pop, bx cx cmpw-rr, jg, cmp; :cmp > cx pop, bx cx cmpw-rr, jle, cmp; :cmp >= cx pop, bx cx cmpw-rr, jl, cmp; 

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

:code or ax pop, ax bx orw-rr, next, :code and ax pop, ax bx andw-rr, next, :code xor ax pop, ax bx xorw-rr, next, :code invert bx notw-r, next, 

Ура, циклы! Что теперь?

До сих пор многие слова, которые могли бы улучшить рабочий процесс редактирования кода в памяти, просто невозможно было определить, поскольку они по своей сути используют цикл. Это меняется сейчас. Во-первых, давайте определим type, который печатает строку:

: type ( addr len -- )   begin dup while 1 - >r     dup c@ emit 1 +   r> repeat drop drop ; 

В моем текущем рабочем процессе последний определенный блок завершается нулевым байтом. Поиск этого места необходим для добавления элементов в этот блок. Вот что seekделает:

: seek ( addr -- end-addr ) begin dup c@ 0<> while 1 + repeat ; 

Затем он используется для appendingустановки srcposи checkpointсоответствующим образом:

: appending ( addr -- ) seek dup u. srcpos ! move-checkpoint ; 

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

Вместо номеров строк я печатаю адрес, с которого начинается каждая строка. Это и проще реализовать, и полезнее. Во-первых, у нас есть show-line, который показывает одну строку:

\ cr emits a linebreak : cr 0D emit 0A emit ;  40 constant line-length 10 constant #lines : show-line ( addr -- next-addr )   dup u.                    \ номер линии   dup line-length type cr   \ содержимое линии   line-length + ; 

Затем он вызывается 16 раз в цикле с помощью list. Поскольку у нас еще нет doloop, это довольно сложно.

: list ( addr -- )   #lines begin     >r show-line r>   1 - dup 0= until   drop drop ; 

Иногда нам нужно переместить некоторый код. Для этого нам понадобится move. Это похоже на C memmoveв том, что он копирует данные с правого конца, так что результат правильный, даже если источник и место назначения перекрываются. Мы реализуем это с помощью инструкции x86 rep movsb, которая, по сути, состоит memcpyиз одной инструкции. Давайте пока обучим ассемблер остальным строковым инструкциям:

: rep, F2 c, ; : movsb, A4 c, ;  ; movsw, A5 c, ;  ; cmpsb, A6 c, ;  ; cmpsw, A7 c, ; 

Затем он используется cmove, который копирует данные вперед. 5 Эта оболочка несколько длинная, так как нам нужно сохранить значения siи di.

:code cmove ( src dest len -- )   bx cx movw-rr,   si ax movw-rr, di dx movw-rr,   di pop, si pop,   rep, movsb,   ax si movw-rr, dx di movw-rr,   bx pop, next, 

Далее нам понадобится cmove>, который начинается с конца буферов и копируется в обратном направлении. Стрелка >указывает, что это правильное слово для использования, если данные должны быть перемещены по более высокому адресу, т. е. вправо. Чтобы запустить такую копию, мы запускаем ее rep movsbс включенным флагом направления x86. Это предполагает, что регистры будут содержать адреса концов буферов , поэтому мы запускаем саму копию в (cmove>), а потом фактическое cmove>отвечает за вычисление правильного адреса.

: cld, FC c, ;  ; std, FD c, ; :code (cmove>)   bx cx movw-rr,   si ax movw-rr, di dx movw-rr,   di pop, si pop,   std, rep, movsb, cld,   ax si movw-rr, dx di movw-rr,   bx pop, next, : cmove> ( src dest len -- )   dup >r                  \ сохранить длину на стеке возвратов   1 -                     \ нам нужно добавить len-1, чтобы получить конечный указатель   dup >r + swap r> + swap \ настроить указатели   r> (cmove>) ; 

Наконец, moveсравнивает два адреса и выбирает подходящее направление копирования:

: over ( a b -- a b a ) >r dup r> swap ; : move ( src dest len -- )   >r   over over u< if     r> cmove>   else     r> cmove   then ; 

Реализация fillпохожа, и она полезна для стирания любых остатков после moves.

:code fill ( addr len byte -- )   bx ax movw-rr,   cx pop,   di dx movw-rr, di pop,   rep, stosb,   dx di movw-rr,   bx pop, next, 

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

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

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

Заголовки слов содержат имя в виде строки с подсчетом, что означает, что первый байт хранит длину. countберет указатель на такую подсчитанную строку и превращает ее в типичное addr lenпредставление:

: count ( addr -- addr+1 len )   dup 1+ swap c@ ; 

Учитывая указатель на заголовок словаря, >nameизвлечет из него имя:

1F constant lenmask : >name ( header-ptr -- addr len )   cell+     \ skip link pointer   count lenmask and ; 

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

: visible? ( header-ptr -- t | f )   cell+ c@ 40 and 0= ; 

Нашими последними вспомогательными словами являются space, которое просто печатает пробел, и #bl(обозначает пробел ), представляющее собой константу, в которой хранится ASCII-значение пробела. 6

: #bl 20 ; : space #bl emit ; 

Все это затем используется функцией words-in, которая принимает указатель на первое слово в списке. Это облегчит адаптацию, как только наш Форт получит поддержку словарей. 7

: words-in ( dictionary-ptr -- )   begin dup while \ loop until NULL     dup visible? if       dup >name type space     then     @   repeat   drop ; : words latest @ words-in ; 

Разбор

Со временем мне нужно будет заменить внешний интерпретатор codegolf на другой, написанный на Forth. Это позволит мне добавить такие вещи, как правильная обработка неопределенных слов, знакомая okподсказка, а также словари и обработка исключений. 8 Первым шагом к этому является parse ( delim -- addr len )слово, которое будет анализировать ввод до тех пор, пока не встретится указанный символ-разделитель. Для обычного синтаксического анализа это будет пробел, но если мы установим его равным ), у нас, наконец, появятся комментарии.

parseхранит разделитель в переменной, чтобы его могли использовать вспомогательные слова.

variable sep 

Разбор может завершиться из-за того, что мы нашли разделитель или из-за того, что у нас закончились входные данные, что обозначается байтом NULL.

: sep? ( ch -- t | f ) dup 0= swap sep @ = or ; 

После завершения цикла разбора у нас будет указатель на разделитель. Если это настоящий разделитель, мы хотим удалить его из ввода — в конце концов, он )не существует как слово. Однако, если мы остановились из-за того, что ввод закончился, то мы не должны продвигаться дальше нулевого терминатора. +sepобрабатывает это и продвигает указатель ввода только в том случае, если он не указывает на нулевой байт.

: +sep ( ptr -- ptr' ) dup c@ 0<> if 1+ then ; 

Цикл parseудерживает два указателя в стеке. Один не двигается и отмечает начало жетона. Другой продвигается в каждой итерации. В конце мы сохраняем перемещенный указатель в >in, а затем вычисляем длину, вычитая два указателя.

: parse ( sep -- addr len )   sep ! >in @ dup begin ( begin-ptr end-ptr )     dup c@ sep? invert   while 1+ repeat   dup +sep >in !  \ обновить >in   over -          \ вычислить length ; 

Это работает, когда мы хотим проанализировать комментарий, но для анализа слова нам действительно нужно сначала пропустить начальные пробелы. Это обрабатывается skip, который также принимает разделитель в качестве аргумента и продвигается вперед >in, чтобы больше не указывать на разделитель.

: skip ( sep -- sep ) begin dup >in @ c@ = while 1 >in +! repeat ; 

tokenсочетает в себе два.

: token ( sep -- addr len ) skip parse ; 

Затем он используется функцией char, которая возвращает первый символ следующего токена — мы можем использовать его как символьные литералы.

: char #bl token drop c@ ; 

Однако, чтобы включить такой литерал в скомпилированное слово, нам нужно [char]:

: [char] char lit, ; immediate 

Наконец, (это непосредственное слово, которое запускает )синтаксический анализ с разделителями и отбрасывает результат.

: ( [char] ) parse 2drop ; immediate 

Голое железо

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

В первый раз я попытался реализовать ветки перед записью на сам диск. Сам код ветвления был в порядке, но мой тест на зацикливание — нет. Попробуйте найти ошибку:

: foo begin dup u. 1 - 0= until ; 5 foo 

Показать подсказку

Код вылетел вот так:

После выполнения 5 foo появилось около 6 строк вывода до зависания.  Выходные данные начинаются: 5 E0E 1F0E 1707 5BC и т. д., заканчиваясь на DB69 10 1, нижний левый символ рисования границы, 4, стрелка вправо, 1B 1) 10

После выполнения 5 foo появилось около 6 строк вывода до зависания. Выходные данные начинаются: 5 E0E 1F0E 1707 5BC и т. д., заканчиваясь на DB69 10 1, нижний левый символ рисования границы, 4, стрелка вправо, 1B 1) 10

Показать решение

Потребляет 0=счетчик циклов в стеке, что означает, что каждая итерация опускается дальше в стек. Поскольку защиты от этого нет, код будет выталкивать что-то до тех пор, пока не начнет перезаписывать код, достаточно важный, чтобы вызвать сбой.

Другая ошибка была в int13самом слове. Как я упоминал ранее, я забыл сохранить SI, который является указателем выполнения для многопоточного кода. Он рухнул, как только запустился next. По иронии судьбы, если бы я не был так осторожен и не выполнил write-blockсвою первую операцию, большая часть кода была бы сохранена 🙃

Помимо ошибок, есть еще одна проблема с запуском на «голом железе»: публикация кода на GitHub. Я решил эту проблему, написав скрипт, splitdisk.pyкоторый извлекает код из образа диска. Поскольку я загружаюсь с USB-накопителя, получение кода не займет много времени.

Поскольку там нет разрывов строк, я написал эвристику, чтобы разбить его на строку для каждого определения. Благодаря Python difflibон даже сохраняет любые корректировки форматирования, сделанные вручную при извлечении обновленной версии блока.

Что дальше?

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

Между тем, я рекомендую вам попробовать выполнить начальную загрузку поверх Miniforth вплоть до ветвления _без_использования каких-либо дополнительных собранных примитивов. Не то чтобы в таком ограничении себя есть смысл, но это интересная проблема. Я объясню свое решение через неделю, а также любые существенно отличающиеся решения, найденные такими читателями, как вы. Я создал отдельную ветку для обсуждения этой проблемы, поэтому, пожалуйста, избегайте спойлеров в комментариях под статьей 🙂

Понравилась эта статья?

Возможно, вам понравятся и другие мои посты . Если вы хотите получать уведомления о новых, вы можете подписаться на меня в Твиттере или подписаться на RSS-канал .

Я хотел бы поблагодарить моих спонсоров GitHub за их поддержку: Michalina Sidor и Tijn Kersjes.


1

Есть небольшое отличие от стандартного поведения в том, что my loadпросто перенаправляет входной указатель, и блок будет выполняться только один раз, непосредственно перед тем, как выполнение достигнет REPL верхнего уровня.

2

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

3

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

4

Если бы это было что-то вроде mov [0x1234], 0x5678, то использовался бы точный порядок: код операции, ModR/M, адрес, немедленный.

5

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

6

Теперь до меня доходит, что я мог бы определить это constantвместо этого. Я, вероятно, изменю это, когда загрузлю подходящий текстовый редактор.

7

Словари Forth, также известные как списки слов, представляют собой способ разделения слов на несколько отдельных «словарей», которые можно динамически добавлять и удалять из порядка поиска.

8

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


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

Показываем и рассказываем про ЦКП «Визуализация высокого разрешения» на базе «Сколтеха»

В 2018 году в «Сколтехе» был создан Центр коллективного пользования (ЦКП) «Визуализации высокого разрешения», оснащённый современными электронными микроскопами, в том числе просвечивающий электронный микроскоп с корректором сферических аберраций Titan Themis Z, двухлучевой сканирующий электронный микроскоп Helios G4 Plasma FIB Uxe и сканирующий электронный микроскоп Quattro S с возможностью работы в низком вакууме. Героем сегодняшнего интервью стала Шахова Ярослава Эдуардовна — руководитель ЦКП «Визуализация высокого разрешения». Ярослава подробно рассказала об истории Центра, его достижениях и богатом техническом оснащении.

Для знакомства с лабораторией можно посетить виртуальный тур

Для знакомства с лабораторией можно посетить виртуальный тур

Какие ключевые этапы в истории развития Центра можете указать?

В качестве первого этапа я хотела бы отметить закупку просвечивающего электронного микроскопа Themis Z, которая состоялась в конце 2016 года по инициативе профессора А.М. Абакумова. На тот момент ЦКП «Визуализация высокого разрешения» (далее – Центр) ещё не был создан формально, но уже было фундаментальное понимание концепции центра электронной микроскопии, который бы соответствовал мировым стандартам по оборудованию и компетенциям. Концепцию разрабатывал А.М. Абакумов. Сегодня он научный руководитель Центра, и я ему активно в этом помогала.

В рамках разработанной концепции мы планировали закупку 6 микроскопов (3 сканирующих электронных микроскопа и 3 просвечивающих электронных микроскопа) и организацию лаборатории по пробоподготовке, поскольку электронная микроскопия требует очень тщательной подготовки образцов для проведения исследований. Нам в значительной мере удалось реализовать наши планы, у нас сегодня 3 сканирующих электронных микроскопа и 1 просвечивающий плюс хорошо оснащенная лаборатория пробоподготовки, что позволяет нам выполнять практически все поступающие к нам запросы.

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

С 2019 года мы планировали расширение Центра и последующую закупку ещё двух микроскопов, просвечивающего и сканирующего. На сегодняшний день мы заканчиваем ремонт в помещениях, однако возможность закупки нового оборудования остается открытой. Мы прорабатываем разные варианты. В 2021 в «Сколтехе» был создан Центр исследовательской инфраструктуры, который объединил все ЦКП «Сколтеха» в один центр с уникальной исследовательской инфраструктурой и на сегодняшний день продолжает развивать и улучшать научно-исследовательскую инфраструктуру в самых разных направлениях.

Опишите сферы в области компетенции ЦКП и их особенности.

Центр обладает широким спектром компетенций по работе с самыми разным образцами и задачами, с которыми к нам приходят заказчики, от изучения морфологии частиц на сканирующем электронном микроскопе Quattro S до решения кристаллической структуры нового вещества на просвечивающем электронном микроскопе Themis Z.

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

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

  2. вокруг области интереса удаляется материал с 3-х сторон с использованием ионного пучка, формируя каналы вокруг области интереса и «обнажая» фронтальное сечение области интереса;

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

  4. фронтальное сечение области интереса «захватывается» с использованием электронного пучка, для чего можно использовать различные детекторы, установленные в сканирующем электронном микроскопе, например, детектор вторичных электронов, детектор обратнорассеянных электронов, внутрилинзовый детектор (его можно использовать только для немагнитных материалов, в силу конструктивных особенностей детектора), или же можно совмещать детекторы вторичных и обратнорассеянных электронов для получения изображений;

  5. с использованием ионного пучка с фронтального сечения области интереса удаляется слой материала заданной толщины, операции 4 и 5 повторяются необходимое количество раз, для получения массива данных;

  6. с использованием различного программного обеспечения выполняется реконструкция 2D массива данных в 3D масштаб.

Морфология поверхности геологического образца перед проведением эксперимента по AutoSlice&View

Морфология поверхности геологического образца перед проведением эксперимента по AutoSlice&View

Аналогичным образом можно изучать элементный состав или же кристаллическую структуру образца. Нужно просто использовать другие детекторы, например, EDX (energy dispersive X-Ray spectroscopy) или EBSD (Electron back scattering diffraction). У нас богатый опыт проведения подобных экспериментов на различных геологических образцах. Задача по изучению пористости в материале очень актуальна для нефтегазовой промышленности, поскольку в породе нефть находиться в порах, поэтому для оценки потенциала месторождения важно определить размер пор, их взаимосвязанность и многие другие параметры.

Или же у вас есть, например, титан, который подвергли воздействию интенсивной пластической деформации для улучшения его механических свойств, и вам необходимо определить размер ёрен. Решить такую задачу можно используя методику EBSD на сканирующем электронном микроскопе, что позволит получить изображение зёренной структуры вашего образца, при этом кристаллографическая ориентация зёрен будет определена. Используя специальное ПО, которое поставляется в комплекте с детектором, можно определить углы разориентировки как на границе зёрен, так и внутри зерна. Но метод имеет физическое ограничение — нельзя определить угол разориентировки менее 2°, определить плотность дислокаций, посчитать размер зёрен и многое другое.

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

Суть эксперимента заключается в следующем: в процессе выполнения эксперимента пучок перемещается по поверхности образца в каждой точке которого происходит запись картины Кикучи-линий, затем происходит сравнение экспериментальной и теоретической картин (теоретическая картина определяется материалом образца, то есть необходимо выбрать фазу из базы данных в ПО). На основании выполненного сравнения происходит построение изображения зёренной структуры образца. Параметры проведения сьёмки, например, область интереса и шаг сьёмки, зависят от материала и предполагаемого размера зёрен. Чем мельче размер зерён, тем меньше будет область интереса и меньше шаг сьёмки. Выполнять сьёмку можно не только на маленьких областях, у сотрудников Центра есть опыт работы с большими полями, например, сьёмка области 1×1 мм2, при этом время сьёмки не будет очень большим за счёт использования высокоскоростной камеры, установленной на микроскопе Tescan Solaris. Использовать методику EBSD можно для различных материалов, но, важно помнить, что если в образце есть две фазы с одинаковым типом решётки, например, гранецентрированная кубическая решётка. Программа не сможет их разделить, несмотря на то, что есть различия в параметрах кристаллической решётки. 

Ещё один пример: вы синтезировали катодный материал и вам необходимо изучить его кристаллическую структуру и элементный состав. Решить такую задачу можно используя методики HAADF-STEM (high angle annular dark field scanning transmission electron microscopy), EDX и EELS (electron energy loss spectroscopy) на просвечивающем электронном микроскопе. Применение методики HAADF-STEM позволяет визуализировать кристаллическую решётку образца, изучить наличие дефектов в кристаллической структуре. Однако HAADF-STEM позволяет визуализировать только тяжёлые элементы, то есть одновременно на изображении нельзя увидеть атомы лития и кобальта.

Поскольку одновременное изучение положения лёгких и тяжёлых элементов представляет большой интерес в последние несколько лет, была разработана методика iDPC (integrated differential phase contrast), которая позволяет визуализировать одновременно лёгкие и тяжёлые элементы. Сочетание методик HAADF-STEM и EDX или HAADF-STEM и EELS с атомным разрешением позволит определить положение конкретного элемента в кристаллической решётке. EDX можно применять и для изучения гомогенности распределения элементов в образце, это поможет оптимизировать параметры синтеза. В катодных материалах важно изучение не только кристаллического строения, но и электронного строения переходных металлов для решения этой задачи можно использовать методику EELS.

Использовать указанные выше методики можно для изучения широкого спектра материалов, например, гетероструктур, металлов, тонких плёнок, наночастиц и т.д. Возвращаясь к теме катодных материалов, изучение кристаллической структуры катодного материала является критически важной задачей. Основная масса современных катодных материалов, которые используют в наших телефонах, ноутбуках и т.д., характеризуется слоистой структурой, и очень важно понимать, как происходит движение лития внутри кристаллической решётки в процессе зарядки и разрядки аккумулятора. Благодаря указанным выше методикам можно получить исчерпывающую информацию о процессах в кристаллической решетке материала.

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

Кристаллическую структуру можно изучать не только с использованием HAADF-STEM, но и используя электронную дифракцию. Это позволит определить тип кристаллической решётки. Одним из интересных примеров применения электронной дифракции является решение кристаллической структуры нового вещества, например, нового синтезированного катодного материала, электронная томография обратного пространства.

Суть эксперимента заключается в том, что оператор получает изображения электронной дифракции, при этом каждое последующее изображение получено после поворота образца на 1°. Также есть нулевое положение образца, и его наклоняют как в положительном направлении, так и в отрицательном. У нас есть специальный держатель для выполнения такого эксперимента, который позволяет наклонять образец на ±90°. Таким образом получается набор изображений электронной дифракции, которые затем подвергают обработке с использованием различного ПО, что в итоге позволяет определить тип кристаллической решётки образца и реконструировать элементарную ячейку кристаллической решетки. Эту задачу можно решить и используя рентгеновскую дифракцию, но иногда, по разным причинам, применение рентгеновской дифракции невозможно, например, недостаточное количество образца. С такой задачей к нам чаще всего приходят коллеги, которые заниматься разработкой катодных материалов для нашей с вами портативной электроники, но не только. Как я уже говорила выше изучение кристаллической решетки катодного материала является очень важной задачей, поскольку она оказывает влияние на свойства, например, на количество циклов разрядки-зарядки аккумулятора, но не только.

Какое оборудование и ПО используется в центре? Как его удалось достать?

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

Сегодня в Центре установлено 4 электронных микроскопа, 3 сканирующих электронных микроскопа (производство ThermoFisher Scientific и Tescan) и 1 просвечивающий электронный микроскоп с пробкорректором (производство ThermoFisher Scientific). При этом из 3-х сканирующих микроскопов 2 являются двухлучевыми, то есть у них две колонны одна — электронная, для визуализации, и вторая — ионная, для травления. Один из них — это Helios G4 Helios G4 Plasma FIB Uxe, в момент закупки это было первое поколение микроскопов, в котором использовали ксенон в качестве источника ионов, и второй — это Tescan Solaris, в котором в качестве источника ионов выступает галлий.

Двухлучевой сканирующий электронный микроскоп Helios G4 Plasma FIB Uxe оснащён двумя колонами — электронной Elstar с высокоточной технологией UC+ для получения изображений с высоким разрешением и ионной Phoenix для наиболее точной пробоподготовки образцов для просвечивающей электронной микроскопии. Также он оснащён как стандартными детекторам, такими как ETD, BSE и TLD, которые позволяют изучать морфологию поверхности, так и детекторами EDX для изучения элементного состава и EBSD для изучения кристаллической структуры. Поскольку наличие ионной колоны позволяет готовить тонкие ламели с толщиной менее 100 нм для изучения на просвечивающем электронном микроскопе, на Helios G4 Plasma FIB Uxe установлен детектор STEM 3+, который позволяет работать в сканирующем просвечивающем режиме в BF, DF и HAADF режимах. Паспортное разрешение прибора 0,6 нм при ускоряющем напряжении 2 кВ. 

Подготовка ламели из катодного материала для исследования на просвечивающем электронном микроскопе. Источник: «Сколтех»

Подготовка ламели из катодного материала для исследования на просвечивающем электронном микроскопе. Источник: «Сколтех»

Двухлучевой сканирующий электронный микроскоп Tescan Solaris оснащён аналогичными детекторами как и Helios G4 Plasma FIB Uxe, но в дополнение к ним на этом приборе можно проводить исследования элементного состава с использованием методики TOFS-SIMS и механические испытания внутри камеры микроскопа, в частности, наноидентирование.

Ещё у нас есть просвечивающий электронный микроскоп Themis Z, который может работать в двух режимах: обычном просвечивающем и сканирующем просвечивающем. Разница в двух режимах заключается в схеме формирования электронного пучка при освещении образца.

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

В сканирующем просвечивающем режиме электронный пучок при настройке должен сфокусироваться в точку на поверхности образца и изображение образца формируется в результате перемещения пучка по поверхности образца. Микроскоп Themis Z оснащён пробкорректором сферических аберраций, что существенно позволяет улучшить разрешающую способность микроскопа, так разрешающая способность в сканирующем режиме 60 пм, что позволяет нам визуализировать атомы. Важным преимуществом сканирующего просвечивающего режима над просвечивающим является возможность прямой интерпретации данных. При работе в сканирующем режиме обычно используют ABF или HAADF детекторы, но не только. Формирование контраста на изображении зависит от порядкового номера (Z) элемента в таблице Менделеева. При использовании HAADF детектора контраст на изображении формируется за счёт некогерентно рассеянных электронов на большие углы (~70-185 мрад), в этом случае контраст будет очень чувствительным к атомному номеру элемента Z и интенсивность рассеяния электронов увеличивается в соответствии с Zn (n<2). Поскольку контраст в HAADF сильно зависит от Z, то легкие элементы практически невидимы на изображении.

Кристаллическая структура катодного материала в просвечивающем электронном микроскопе, методики ABF и HAADF. Источник: «Сколтех»

Кристаллическая структура катодного материала в просвечивающем электронном микроскопе, методики ABF и HAADF. Источник: «Сколтех»

При использовании ABF детектора формирование контраста на изображении происходит за счёт сочетания среднеуглового Брэгговского рассеяния и дальнеуглового некогерентного рассеяния электронов, в результате чего зависимость интенсивности от Z изменяется в соответствии с Z1/3, что позволяет визуализировать положение легких элементов (кислород и литий) в атомной структуре. Таким образом, оператор может напрямую интерпретировать изображения, например, для HAADF изображения (изображение выше) белые точки на изображении это атомы в кристаллической решётке.

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

Как было отмечено выше, сложно визуализировать одновременно лёгкие и тяжёлые элементы. Однако относительно недавно был разработан новый детектор, который позволяет это сделать. В рамках последнего апгрейда микроскопа Themis Z в 2021 году мы установили такой детектор, что позволяет нам визуализировать одновременно лёгкие и тяжёлые элементы в кристаллической решетке образцов, методика называется integrated Differential Phase Contrast. Themis Z можно использовать в широком интервале ускоряющих напряжений, 80, 120, 200 и 300 кВ, что позволяет исследовать и чувствительные к воздействию электронного пучка.

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

И последний микроскоп в нашем Центре — это сканирующий электронный микроскоп Quattro S с возможностью работы в низком вакууме и в насыщенных парах воды, что позволяет нам исследовать биологические объекты и другие непроводящие образцы, например, геологические. Микроскоп Quattro S оснащён EDX детектором для исследования элементного состава образцов. Разрешающая способность Quattro S немного хуже, чем у микроскопов Helios G4 Plasma FIB Uxe и Tescan Solaris, и составляет 1 нм при ускоряющем напряжении 30 кВ, но этого достаточно для задач как внутренних, так и внешних заказчиков.

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

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

Какая доля отечественного/зарубежного ПО и оборудования в ЦКП?

В процессе закупки микроскопов мы, конечно, формировали пул необходимого нам ПО для обработки данных, которые генерируются в процессе экспериментальных исследований, и в большинстве случаев всё ПО входило в комплект поставки оборудования.. Например, на двухлучевом сканирующем электронном микроскопе Helios G4 Plasma FIB Uxe установлены детектор для определения элементного состава и детектор для сьёмки микродифракции картин обратно рассеянных электронов (Electron Back Scattering Diffraction — EBSD), что требует наличия специализированного ПО для обработки полученных данных, и ПО идёт в комплекте, но только лицензия на 1 компьютер. Если необходимы лицензии для большего количество пользователей, необходимо покупать отдельно. И так с большинством ПО, которое у нас есть в Центре.

Зёренная структура стали 316L, полученная с использованием методики микродифракции обратнорассеянных электронов

Зёренная структура стали 316L, полученная с использованием методики микродифракции обратнорассеянных электронов

В качестве дополнительного ПО мы включали в комплект поставки ПО для проведения эксперимента AutoSlice&View, что позволяет нам изучать пористость внутри материала, при стандартном эксперименте, когда мы просто визуализируем поверхность области интереса с использованием электронной колоны. Используя AutoSlice&View эксперимент можно изучать элементный состав или кристаллическую структуру по глубине образца используя или EDX или EBSD детектор. Таким образом, можно получить информацию о пористости, элементном составе или кристаллической структуре образца в 3D.

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

Отдельно мы закупали ПО Avizo, которое позволяет проводить реконструкцию экспериментальных данных из 2D в 3D. У Avizo высокие требования по «железу», и для его установки мы специально собирали ПК, который будет удовлетворять требованиям ПО. Всё ПО, которое мы используем в Центре, является зарубежным, его разработчиком являются компании, которые производят электронные микроскопы и различные детекторы для электронных микроскопов, отечественных аналогов нет. 

Всё оборудование, которое используется в Центре зарубежного производства, у нас, к моему большому сожалению, не производят ни одну позицию из того оборудования, которое у нас установлено. 

Вы используете нейросети в работе?

Нет, мы не используем нейросети в своей работе.

Насколько сложно поддерживать систему в условиях санкций? Техническая поддержка, замена вышедших из строя блоков и так далее.

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

В то же время, я могу сказать, что совсем без сервиса мы не остались, потому что у многих поставщиков оборудования есть свои команды сервисных инженеров, которые проходили обучение у производителей оборудования и обладают всеми необходимыми навыками для ремонта и восстановления работоспособности оборудования. Иногда бывают ситуации, когда сервисные инженеры не могут решить проблему, и в этом случае была возможность обратиться к производителю оборудования для решения проблемы силами его сервисных инженеров. Отсутствие такой возможности сейчас является тревожной для Центра. По поставкам необходимых запчастей и расходных материалов мы решаем проблемы по мере их поступления.

С чем чаще работаете — с частными компаниями или госструктурами и институтами? Расскажите про заказчиков и как их искали.

Мы работаем с разными заказчиками, основной группой наших заказчиков являются научные Центры «Сколтеха». Но здесь я хочу отметить, что сотрудникам Центров «Сколтеха» мы предоставляем доступ для самостоятельной работы на приборах, не на всех, но, например, они могут пройти обучение по работе на микроскопе Quattro S, который можно использовать для решения рутинных задач. 

В качестве внешних заказчиков выступают и научные институты, и университеты, и частный сектор. В поиске новых заказчиков нам помогает один из конкурсов Российского научного фонда для объектов исследовательской инфраструктуры. Наш Центр уже дважды участвовал в этом конкурсе в 2021 и 2023 годах. По результатам конкурса 2021 года наш Центр выиграл 5 проектов, в 2023 году — 7 проектов. Проекты 2021 посвящены самым разным темам, например, в рамках выполнения проектов 2020 года мы занимаемся изучением катодных материалов, углеродных материалов, полимеров с эффектом памяти формы и функциональных наносистем на основе ультрамалых частиц.

Организации, которые выиграли в конкурсе 2021 года — это МГУ им. М.В. Ломоносова, МИСИС, ИХТТМ СО РАН и КФУ. В 2023 году выиграли проекты по изучению полупроводниковых нанокристаллов для биомедицины, топологических изоляторов для применения в сверхпроводниковой электронике и спинтронике, дисперсных частиц в неравновесных титановых и магниевых сплавах, оптических латеральных логических вентилей на основе поляритонных конденсатов, диэлектрических наноструктур, планарных структур и функциональных магнитных микросфер. Из 7 проектов победивших в конкурсе 2023 году, два проекта от «Сколтеха», два проекта от Университета ИТМО и по одному проекту от МФТИ, БашГУ, МГУ им. М.В. Ломоносова.

Но мы работаем не только с научными институтами и университетами. Нашими заказчиками бывают и компании, например, компания «Крокус Наноэлектроника», «Метаклэй», «Самсунг», QRate, «Геодерма» и др. Здесь я бы хотела отметить, что специфика работы центра определяет наличие значительной долю интереса к Центру именно со стороны научных институтов и университетов, мы очень много работ выполняли для МГУ им. М.В. Ломоносова, МИСИС, РНИМУ им. Н.И. Пирогова, ИХ ДВО РАН, ОИЯИ. До 2022 года мы выполняли работы и для иностранных коллег, например, для College de France, Kyoto University, Kanagawa University, Université de Bordeaux.

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

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

Да, Центр себя обеспечивает по расходным материалам и частично при закупке запчастей для оборудования. Это наши операционные расходы по содержанию лаборатории, я не включаю в них зарплату сотрудников Центра. Результат действительно очень хороший, потому что с учётом стоимости всего оборудования, которое установлено в Центре, мы не можем говорить об окупаемости оборудования. Максимум, что можно достичь — это покрытие операционных расходов Центра. Я думаю, что получить такой получилось за счёт повышения узнаваемости Центра, поскольку нас уже рекомендуют для проведения исследований те для кого мы проводили исследования ранее, что говорит о высоком уровне компетенций сотрудников Центра.

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

***

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


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

Как мы повышаем CTR по запущенной в ПромоСтраницах статье

Бывает, запустишь статью в продвижение на ПромоСтраницах, а ее не читают. Большинство пользователей просто не замечают рекламное объявление. Рассказываю, как это исправить.

Привет, меня зовут Паша Молянов, я руковожу агентством контент-маркетинга «Сделаем». У нас есть правило: после запуска рекламной кампании мы как минимум раз в неделю анализируем обложки статьи и оптимизируем их. Так получается увеличить CTR — отношение числа кликов к числу показов. В статье поделюсь нашим опытом и цифрами клиентов.

Обложки в ПромоСтраницах — это изображение + заголовок + описание. Алгоритм сам подбирает наиболее удачные комбинации и чаще показывает их аудитории. Можно менять изображения и заголовки, если результаты не нравятся

Обложки в ПромоСтраницах — это изображение + заголовок + описание. Алгоритм сам подбирает наиболее удачные комбинации и чаще показывает их аудитории. Можно менять изображения и заголовки, если результаты не нравятся

Начали читать, не зная, что такое ПромоСтраницы?

Это брендформанс-инструмент от Яндекса. С ним можно работать на всю воронку продаж — от формирования нового спроса на продукт до подталкивания к покупке.

Для продвижения нужно написать рекламные статьи. После запуска алгоритм сформирует объявления, которые будут вести на текст, и будет показывать их в сервисах Яндекса и на сайтах-партнерах Рекламной сети Яндекса.

Аудитория РСЯ: около 96 млн посетителей.

Что такое CTR и когда начинать переживать, что он низкий

CTR (Click-Through Rate) — метрика, которая показывает, сколько процентов тех, кто видел объявление, перешли на страницу со статьей.

Метрика условная. Например, если вы продаете лежанки для собак, нормальным значением, скорее всего, будет CTR от 0,5 до 1%. Собачников много, тем более алгоритм старается показывать объявления наиболее подходящим пользователям — например, тем, кто уже искал что-то о животных или зашел на тематический сайт. Но среди этой аудитории не так много тех, кому будет интересно почитать о лежанке.

Зато, если вы продвигаете бренд одежды, можете ожидать CTR до 2%.

ПромоСтраницы даже составили усредненные бенчмарки для каждой категории. Полностью полагаться на них не стоит — можно опираться на эти данные в начале продвижения, но не забывайте сравнивать метрики с вашими другими рекламными каналами. Например, если через соцсети или Директ CTR хороший, а на ПромоСтраницах едва дотягивает до 1%, — скорее всего, работа с обложками улучшит ситуацию. Даже если бенчмарки говорят, что для вашей сферы 0,8–0,9% — это нормально.

В погоне за высоким CTR важно не забыть и про другие метрики. Разберем на примере.

У обложки с заголовком «Кто оценит портрет больше, чем букет» низкий CTR, всего 0,5%. Можно поднять его, если попробовать другие заголовки, например: «Показываем 10 оригинальных портретов». Допустим, так CTR вырастет до 1,5%.

Можно лучше: заголовок «Читайте про самый оригинальный подарок на любой праздник» может поднять CTR до 2% и выше. Но так ухудшатся другие метрики: дочитывания и переходы. Первый показатель говорит о том, сколько людей остались в статье надолго, а второй — сколько перешли на сайт после чтения. Читатели будут активно переходить в статью, но часть из них будет сразу понимать, что им неинтересно: может быть, они не любят портреты или ожидали здесь почитать инструкцию к DIY-сюрпризу. Они будут уходить из статьи после первых же абзацев. А алгоритму будет сложно понять, какая аудитория является целевой.

Поэтому важно смотреть на всё в комплексе: следите, чтобы дочитывания были не ниже 40%, а переходы не ниже 30%.

Шаг 1. Поменять заголовки

Хорошие заголовки помогают привлечь в статью больше читателей. Статьи из галереи были в топе ПромоСтраниц за 2022 год — у них самый высокий CTR. И судя по высокому проценту дочитываний (от 50%), они привлекали нужную аудиторию и честно говорили о том, что будет в самом тексте. Смотрите примеры →

В заголовке половина успеха обложки, поэтому, если CTR низкий — в первую очередь смотрите на заголовки.

ПромоСтраницы собирают статистику не только по обложкам, но и по каждому отдельному заголовку. В редакторе вы сможете удалить заголовки, которые плохо сработали, и вместо них придумать новые

ПромоСтраницы собирают статистику не только по обложкам, но и по каждому отдельному заголовку. В редакторе вы сможете удалить заголовки, которые плохо сработали, и вместо них придумать новые

Ловите несколько советов, которые помогут придумать крутые заголовки.

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

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

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

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

  • Подборка летних шин для 4 разных стилей вождения

  • 4 важных вопроса про ополаскиватели для полости рта

  • Как страховка туриста поможет сэкономить в поездке?

  • Мифы о клещах, в которые хозяевам собак не стоит верить

  • Гайд: что такое умный дом и как его организовать

  • Проверьте, соблюдаете ли вы все этапы ухода за волосами

  • Бесплатный эвакуатор: какие еще есть услуги у каско

  • Новый ЖК в Питере: сосны за окном и кафе на первом этаже

Чтобы увидеть общую картину по рекламным кампаниям, мы собираем все данные в одну таблицу. Если видим, что общий CTR низкий, например 0,9%, — начинаем работать с заголовками. Смотрим, какие сработали хуже всего, и их отключаем, помечаем себе хорошие и добавляем новые. В примере на скриншоте это помогло увеличить CTR до 2,3%. А потом мы увеличили бюджет, и CTR снова просел (ведь алгоритм стал искать в два раза больше аудитории), но остался в нормальных рамках.

Описание дополняет заголовок и стоит в объявлении сразу под ним. Вот как написать его:

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

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

3. Описание есть не во всех объявлениях. Иногда посетители видят только изображение и заголовок. Поэтому не ставьте в описание важную информацию. Заголовки должны быть полноценными и интересными без описания.

Смотрите примеры:

● Рассказываем, в какой школе индивидуальный подход и интересные курсы

● Выясняем, насколько сложно получить выплату и застраховать неновое авто по каско

● Рассказываем о функциях органа и о веществах, необходимых печени

Шаг 2. Меняем изображения на обложках

Качественное изображение помогает выделить объявление среди остальных похожих.

Здесь все изображения неплохие. Но лучше сработают, скорее всего, верхние. Первую картинку трудно не заметить на странице, а вторая зацепит тех, у кого есть подобная проблема

Здесь все изображения неплохие. Но лучше сработают, скорее всего, верхние. Первую картинку трудно не заметить на странице, а вторая зацепит тех, у кого есть подобная проблема

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

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

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

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

Шаг 3. Добавляем быстрые ссылки

Функцию быстрых ссылок в ПромоСтраницы добавили в феврале. Это такие короткие теги в объявлениях, кликнув на которые читатель переходит прямо в статью. Объявление становится заметнее, привлекает больше внимания пользователей, усиливает любопытство, а в результате — повышается CTR.

Вот как выглядят быстрые ссылки в рекламных объявлениях

Вот как выглядят быстрые ссылки в рекламных объявлениях

Вот что можно в них писать:

  • преимущества продукта;

  • адаптированные подзаголовки;

  • интересные цифры, которые не влезли в заголовки и описание.

Честно, у нас нет кейсов, которые бы доказали, что CTR может вырасти из-за быстрых ссылок. Мы везде их добавляем просто потому, что это возможно, но отдельно не тестировали эффективность. Зато их могли тестировать другие компании, которые продвигаются через Промо. Если интересно, можете посмотреть на странице с кейсами.

Если ничего не помогло — остается лишь перезапустить рекламную кампанию. Бывает, что статьи просто не зашли, и алгоритму спустя первые несколько «неудачных» дней уже сложнее настроиться. Это нестрашно. Если отключить РК и сделать новую, алгоритм начнет учиться заново, и метрики могут улучшиться.

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


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

Что такое функциональный генератор, и как им пользоваться


Привет, Хабр! Какие и насколько значительные искажения, (или преобразования, если они желательные), привносит в сигнал тот или иной прибор, цепь или узел?

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

Сегодня мы соберём и опробуем такие генераторы на специализированных микросхемах ICL8038 и XR2206, а также простейший вариант на NE555.

Лабораторным функциональным генератором на микросхеме XR2206 мы уже пользовались в статье про самодельный ламповый усилитель.

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

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

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

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

Так как интегрирующая цепь является фильтром нижних частот (ФНЧ), завал фронтов свидетельствует о спаде амплитудно-частотной характеристики (АЧХ) в области высоких частот. Что характерно, например, для гитарных кабелей и соединительных кабелей аудиоаппаратуры.

Дифференцирующая цепь является фильтром верхних частот, ослабляющим низкочастотную составляющую сигнала. Применительно к аудиотехнике это потеря басов. На экране осциллографа наблюдается подъём фронтов.

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

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

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

▍ Схема на XR2206

Этот набор с Алиэкспресс позволяет собрать неплохой функциональный генератор в прозрачном акриловом корпусе. Он «умеет» выдавать синусоидальный сигнал, треугольную волну и прямоугольные импульсы, снабжён регулировкой усиления, имеет грубую и точную регулировку частоты в 4 поддиапазонах:

  • 1 — 10 Гц;
  • 10 — 100 Гц;
  • 100 — 3000 Гц;
  • 3 — 65 кГц;
  • 65 кГц — 1 МГц.

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

Может быть, дело в том, что вывод 11 микросхемы называется не «square wave output», а «sync output», то есть выход синхронизации? То есть, при разработке чипа XR2206 компания EXAR не предусматривала высококачественного меандра. Ведь для синхронизации достаточно просто фронта импульса.

На самом деле нужно просто переключить вход осциллографа из режима сопряжения по переменному напряжению (AC coupling) в сопряжение по постоянному (DC). Эти два режима различаются тем, что в режиме DC щуп подключён через конденсатор, отсекающий постоянное смещение.

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

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

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

На частоте 420 Гц меандр остаётся прекрасным.

На частоте 125 кГц видим уже небольшое искажение меандра. Аналоговая полоса пропускания карманного осциллографа JYE Tech DSO Coral 112А составляет 0 — 2 МГц. То есть, сигналы частотой до 200 кГц он должен показывать — как они есть.

Вместо нормального щупа, тут простые провода с крокодилами без подстроечного конденсатора. При наблюдении тестового сигнала 100 кГц с генератора самого осциллографа видим такой же зубец.

Меандр 1 МГц на экране DSO Coral 112А выглядит как синусоида, а точнее, как синусоида, искажённая лампой. Дело в том, что аналоговый тракт осциллографа не пропускает частот выше второй гармоники этого сигнала. Чтобы адекватно наблюдать форму сигнала частотой 1 МГц, нужна полоса пропускания до 10 МГц.

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

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

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

На частоте 285 кГц вершины треугольных импульсов выглядят скруглёнными, но это уже связано с полосой пропускания осциллографа.

▍ Изучаем микросхему XR2206

Теперь посмотрим на схему генератора. Времязадающие конденсаторы C4 — C8 задают частотные поддиапазоны и переключаются джампером P2.

Переменный резистор R8 осуществляет грубую, а R7 — точную настройку частоты, благодаря тому, что они соединены последовательно, и сопротивление R7 вдвое меньше, чем у R8. Можно было сделать и более тонкую подстройку, если бы сопротивления различались, например, в 5 раз.

R6 ограничивает минимальное сопротивление составного времязадающего резистора. Данная конструкция использует всего один вход под резистор, а в микросхеме XR2206 их два. Конденсатор при этом используется один и тот же.

Переключение двух резисторов, и, соответственно, двух частот, осуществляется через вывод 9 — Frequency Shift Keying Input, FSKI. Если напряжение на нём ниже 1 вольта, генерируется частота, задаваемая резистором, подключённым между выводом 8 и землёй схемы. А если выше 2 вольт, активен вывод 7, и соответствующий резистор.

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

Frequency Shift Keying — это частотная манипуляция, то есть модуляция, при которой скачкообразно изменяется частота несущего сигнала в зависимости от значений символов информационной последовательности.

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

Резисторы R3 и R5 делят напряжение питания пополам. Образованная ими средняя точка, причём не заземлённая по переменному току (в отличие от схем из справочного листка к микросхеме), подключена к выводу 3 микросхемы через переменный резистор R2. Его сопротивление задаёт усиление и, соответственно, амплитуду выходного синусоидального и треугольного сигналов. На амплитуду меандра этот регулятор не влияет.

Схема из документа AN-14 «А high quality function generator system using the XR2206 chip» предлагает регулировать не только амплитуду выходного сигнала, но и его смещение, посредством потенциометра R9.

Переменным резистором R10 можно подстроить форму синусоиды для получения минимума гармонических искажений. У генератора из набора с Али эта подстройка отсутствует, но как мы видим, хорошая синусоида получается и с постоянным резистором 330 Ом. На треугольную волну этот резистор не влияет, так как режим треугольной волны активируется отключением данного резистора.

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

А для амплитудной модуляции разработчики XR2206 предусмотрели выход 1, который у китайского генератора также не задействован.

Электролитический конденсатор, подключаемый к выводу 10, заземляет по переменному току внутренний источник опорного напряжения. Такое мы видели в обвязки многих аналоговых микросхем.

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

Вывод прямоугольных синхроимпульсов 11, являющийся выходом с открытым коллектором, нужно подтягивать резистором к плюсу питания. Схема из AN-14 предусматривает делитель R5R6, позволяющий получить выходы с полной и с половинной амплитудой.

А чтобы получить колебания с разным коэффициентом заполнения, например, ШИМ или развёртку для ЭЛТ осциллографа, следует просто соединить выход синхросигнала со входом переключения частотнозадающих резисторов. Тогда положительная и отрицательная полуволны будут составлять не половину периода колебаний, а его часть, соответствующую соотношению сопротивлений времязадающих резисторов.

▍ Схема на ICL8038

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

Можно заказать и нарядную версию с акриловым корпусом и удобными ручками переменных резисторами.

Есть и третий вариант. Он поставляется в виде собранного модуля с 10-оборотными подстроечными резисторами и пригодится тем, кому важна точность настройки.

В отличие от XR2206, микросхема ICL8038 имеет отдельные выходы для меандра, треугольника и синусоиды. Подстроечный резистор RP1 задаёт частоту колебаний. RP5 — регулятор амплитуды выходного сигнала. RP3 дополнительно настраивает амплитуду прямоугольных импульсов.

RP2 регулирует коэффициент заполнения ШИМ. Иными словами, влияет на временной баланс положительной и отрицательной полуволн.

RP4 настраивает смещение формирователя синусоиды.

Прямоугольник и пила выглядят прекрасно.

Приближаясь к верхней границе частотного диапазона, синусоида искажается, прямоугольник выглядит как синусоида, а зубья пилы становятся серповидными. Но такова полоса пропускания осциллографа DSO Coral 112А.

▍ Схема на NE555

И напоследок опробуем примитивное решение на универсальном таймере NE555.

Здесь меандр последовательно проходит через три одинаковых RC интегратора, а затем поступает на базу транзистора во включении с общим эмиттером, коллектор которой соединён с базой через конденсатор. (Резистор 1 МОм обеспечивает смещение базы). Переставляя джампер, можно наблюдать, что происходит с сигналом на каждой стадии.

▍ Выводы

На специализированных микросхемах XR2206 и ICL8038 получаются прекрасные функциональные генераторы для любительской электронной лаборатории.

Что касается простой схемы на таймере 555, аппроксимация синусоиды получилась неожиданно неплохой. Тогда как плато меандра искажены дифференцирующей цепочкой, пила вместо отрезков прямой имеет куски экспоненты, (чтобы получить ГЛИН, — генератор линейно изменяющегося напряжения, — надо заряжать конденсатор не постоянным напряжением через резистор, а источником стабилизированного тока), а вершины треугольников, разумеется, скруглены интеграторами.

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

Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх 🕹️


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