Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Регистрируясь, я даю согласие на обработку данных и условия почтовых рассылок.
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Обычные девчонки Алиса и Вика отправились на поиски друга, который перестал выходить на связь, и угодили в безумный водоворот странных событий на затерянном острове. Им очень нужна ваша помощь! Играйте три-в-ряд и выполняйте задания. Удачи!

ВегаМикс 2

Казуальные, Три в ряд, Головоломки

Играть

Топ прошлой недели

  • solenakrivetka solenakrivetka 7 постов
  • Animalrescueed Animalrescueed 53 поста
  • ia.panorama ia.panorama 12 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

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

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
0 просмотренных постов скрыто
242
PetroBr

Своими разработками c нуля, решил тягаться с Rockwell Automation и Siemens в АСУ ТП⁠⁠

2 месяца назад
Интерфейс 3osheet , среда разработки программ на LD, FBD, частично ST, и на псевдо-ассемблере (инструкции виртуальной машины)

Интерфейс 3osheet , среда разработки программ на LD, FBD, частично ST, и на псевдо-ассемблере (инструкции виртуальной машины)

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

Цели которые поставил перед собой:

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

2) Гибрид LD и FBD. Возможность создавать свои блоки (рисовать, и описывать на псевдо ассемблере для виртуальной машины).

3) Создание среды выполнения программ на стороне - микроконтроллера (или ПК если это SCADA).

4) Разработка изолированой среды выполнения (виртуальная ОЗУ) с заменой кода на лету. Например - отключить задачу, через MODBUS переписать или изменить ее программу, и запустить выполнение, и при этом не останавливать другие задачии и не перезагружая ПЛК физичесски.

Являюсь фанатом - оптимизации, восхищаюсь способностью выжать из минимум ресурсов - максимум эффективности. Потому выполнил важную цель - разработка и запуск виртуальной машины (собственной виртуальной машины, об этом в следующих статьях) выполняющий программу ПЛК на микроконтроллере с 8 KB ОЗУ!

Перейти к видео

Среда разработки. Написана на OpenJDK, Java весом 80мб с самыми примиитивными GUI. Легкая и работает даже на старых Raspberry PI. Если установить IDE(среду разработки с компилятором) и среду выполнения на CPU, получится самодостаточноый ПЛК Сервер, способен сам себя перепрограммировать(пользователем) без внешнего ПК.

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

Трансляция LD\FBD\ST программ на язык инстукций виртуальной машины, а потом компилятором в байткод для машины

Трансляция LD\FBD\ST программ на язык инстукций виртуальной машины, а потом компилятором в байткод для машины

Компилятор. Программная архитектура

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

тут мне пришлось проделать огромную работу компиляторостроения - Memory Manager Layout.

types:

Sensor typedef {

id: word;

value: real;

is_ok: byte;

}

Status typedef {

is_running: byte;

error_code: word;

error_msg: byte[50];

}

ProductionLine typedef {

line_id: word;

sensors: Sensor[10];

production_rate: real[7][24];

status: Status;

};

Таким образом в данный момент, описание пользовательского LD FBD выглядит так:

Data:

line_1: ProductionLine;

program:

//Init

MOVI R1 1;

SDR line_1.line_id R1;

MOVI R1 TRUE;

SDR line_1.status.is_running R1;

MOVIF R2 24.5;

SDR line_1.sensors[0].value R2;

MOVIF R1 105.7;

SDR line_1.production_rate[0, 8] 105.7;

Но уже сейчас работаю над транслятором ST, чтоб можно было создавать свои LD FBD с описанием их на ST.

То есть, самый низкий уровень VM это гибрид ассемблера с высокоуровневыми данными, поддержку этого я намеренно реализовал для возможности в будущем писать код на свою платформу не только на языке ST, да хоть на Java. При этом, напомню, я разрабатывал VM способную работать на микроконтроллерах с ОЗУ от 8Кб. Да возможно если писать на языке ST , то в такой МК влезет всего под сотню строк кода, но ничего не мешает подгружать инструкции с внешней карты (если пользователю не важна строгость выполнения по времени, будут небольшие задержки), ну или взять МК с ОЗУ побольше. VM имеет эфективное адресное пространство 1 мегабайт, то есть - прочитать переменную с адресом меньше <1МБ можно за один раз:

LDR R1 R10 @ADDr(PID_CONTROLLER.setpoint);

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

Что можно выжать из МК с ОЗУ 8 килобайт

Инструкции VM - 4 байтные. Одна булевая LD инструкция занимает 8 - 12 байт:

// 8 Байт, Аналог XIC

LDB R15 Reset;

JFALSE R15 Start;

//12 байт если LD читает целое, но проверяет бит

LDB R15 MPPress;

MSK R15 #5

ISFALSE Branch 2;

таким образом, в однозадачном режиме, если создавать ПЛК на МК с ОЗУ 8КБ ( 4 КБ - виртуальная ОЗУ+4 КБ нативный код СИ - сама машина), на 4 КБ виртуальной ОЗУ можно загрузить 300-400 LD (при булевых переменных - 400 LD ) инструкций и около сотни переменных размером 1-4 байта.

Если режим многозадачный ( парралельные не связанные между собой задачи) то среда разработки допишет свой код, где будет дополнительно уходить 80 байт на каждую задачу для создания виртуального стека, и около 160 байт на простейший менеджер задач, который будет управлять выполнением.

В следующей статье напишиу - как это выглядит уже на микроконтроллере.

Показать полностью 1 1
АСУ ТП Импортозамещение ПЛК Промышленность Компилятор Видео Без звука Длиннопост
67
2
user4740118
user4740118

Создание установщиков (exe) при помощи Inno Setup⁠⁠

4 месяца назад

Вот вы захотели, чтобы у вас был удобный файл для установки игры или программы. Для этого мы скачаем Inno Setup (https://jrsoftware.org/isdl.php), так как он полностью бесплатный, в отличие от кучи других программ с ограничениями.

Для примера я возьму DWARF FORTRESS CLASSIC (https://www.bay12games.com/dwarves/).

Вот мы скачали и установили Inno Setup, и теперь его запускаем. Нас встречает окно приветствия, и нам не нужно его закрывать, так как нам нужен пункт "Create a new script file using the Script Wizard" (Создайте новый файл сценария с помощью мастера создания сценариев):

Дальше нас встретит окно с описанием мастера создания сценариев Inno Setup и тут мы просто нажимаем "Next".

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

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

Вот мы и подобрались к самому интересному. Тут мы выбираем, где находиться основной исполняемый файл и все файлы программы. Если нет основного исполняемого файла, то отмечаем пункт "The application doesn't have a main executable file". При добавлении файлов программы лучше всего использовать добавление папки.

Теперь у нас спрашивают, как назвать дополнительные файлы нашего установщика. Если программа большая, то в один exe всё не получится уместить, и вместе с ним будут созданы bin-файлы. Лучше всего не менять названия для них, так как будет понятнее, какие файлы к чему относятся.

Мы переходим в пункт с ярлыками, и лучше тут ничего не трогать. Поэтому идём дальше.

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

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

Мы дошли до выбора языков установщика. Лучше всего выбрать все языки. Но, конечно же, можно отметить только конкретные.

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

Мы можем скачать иконку из интернета, либо мы можем конвертировать (обязательно квадратный) PNG в формат ICO.

Вот для примера сайт для такой конвертации: https://www.aconvert.com/icon/png-to-ico/

В предпоследний раз нажимаем на "Next", и с основной частью мы закончили.

В пункте "Inno Setup Preprocessor" ничего не трогаем и просто нажимаем "Next".

На вопрос "Would you like to compile the new script now?" выбираем "Нет".

Так как DWARF FORTRESS CLASSIC небольшая программа, можно уже сейчас нажать на кнопку для начала компиляции, но большинство программ имеют большой размер и поэтому нам нужно немного дополнить код.

Для начала после "[Setup]" на следующие же ниже строчки вставляем это:

DiskSpanning=true

DiskSliceSize=2100000000

Затем мы должны выбрать уровень сжатия.

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

https://jrsoftware.org/ishelp/index.php?topic=setup_compress...

В пункте "Compression=" после равно вписываем подходящий нам уровень сжатия:

lzma2/ultra64

Теперь мы можем запустить компиляцию. Для этого мы нажимаем на значок с синей стрелкой, направленной вниз:

Запускаем, выбираем хотим ли мы сохранить этот сценарий.

И вот у нас готовый установщик:

Показать полностью 16
[моё] Компилятор Установка Установщик Программное обеспечение Программа Бесплатно Dwarf Fortress Exe Длиннопост
3
57
Mercury13
Серия Доступно об АйТи

Ответ на пост «Потому что кожаные должны страдать?»⁠⁠1

5 месяцев назад

Доступно об АйТи: Почему Python сам не может добавить кавычки?

У меня есть две серии, «Детские вопросы» и «Доступно об АйТи» — вопрос подходит к обеим.

Мем, вызвавший мою заметку

Мем, вызвавший мою заметку

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

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

Я не настолько силён в Python, писать простенькие скрипты могу, но синтаксис ещё не засел в подкорку — так что разрешите за пример брать Паскаль и Си. Начнём со строчки Паскаля (не совсем стандартного, скорее Delphi, но пусть будет).

procedure Print(x : string = '');

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

ключевое слово PROCEDURE
идентификатор (имя) PRINT
знак (
идентификатор X
знак :
идентификатор STRING
знак =
строка пустая
знак )
знак ;

Этот поток слов и знаков идёт на синтаксический анализ, и он происходит так.

  1. Видим ключевое слово PROCEDURE, переходим в режим «заголовок процедуры».

  2. Видим идентификатор PRINT, это название процедуры.

  3. Видим знак (, переходим в режим «список параметров».

  4. Видим идентификатор X, переходим в режим «однотипные параметры».

  5. Видим знак :, переходим в режим «тип».

  6. В режиме «тип» получается считать только идентификатор STRING.

  7. В режиме «однотипные параметры» видим знак равенства и считываем значение по умолчанию (пустую строку), разрешите дальше не расписывать.

Вот этот разбор «видим-переходим» самый простой и пишется опытным программистом по наитию.

Язык Си действует сложнее, аналогичную строку

void print(char* x = "")

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

<direct-declarator> ::= <identifier>
| ( <declarator> )
| <direct-declarator> [ {<constant-expression>}? ]
| <direct-declarator> ( <parameter-type-list> )
| <direct-declarator> ( {<identifier>}* )

(специально нашёл именно тот кусок языка Си, что относится к нашей строчке.)

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

А что будет, если язык будет подчищать за человеком такие ошибки?

Первое. Часто подобные предположения неоднозначны. Возьмём процедуру посложнее:

procedure Print(x : string = ''; y : integer = 0);

…и вызовем её Print('text, 10); Оба места, где можно поставить закрывающуюся кавычку — после text или после 10 — дают корректный вызов. А может, программист вообще не хотел открывать кавычку и text — это чьё-то имя (идентификатор)?

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

Третье. Если окидывать постоянно, начнётся такое: при удлинении текста вдвое время сборки повысится вчетверо. Мой хобби-проект «Юникодия» (только собственные файлы, написанные человеком — без библиотек, программно генерируемых и файлов данных) занимает 1,2 мегабайта на языке Си++. Мой рабочий проект, который пишется бригадой примерно из 15 прогеров,— сотни мегабайт. Компиляция таких монстров будет занимать вечность!

Ускоритель компиляции Си++ под названием Unity (не путать с одноимённым игровым движком!) работает так: когда программа состоит из тысячи модулей, он объединяет их по 10, и получается 100 штук. Работает Unity именно потому, что в Си++ всё наоборот: один длинный модуль компилируется быстрее десяти коротких.

Четвёртое. Это бессмысленно удлиняет спецификацию, а главное — стройная теория формальных языков, которую задел по поверхности, перестаёт работать. Даже если условный Бьярне Гослинг (комбинация имён Бьярне Строуструп, автор Си++, и Джеймс Гослинг, автор Java) напишет свой личный язык с таким сервисом, существует множество программ более тупых, чем компиляторы, которым, тем не менее, нужен корректный исходный текст.

  • Начнём с форматёров — они берут исходный текст и расставляют в нём отступы в соответствии с принятой в конторе системой.

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

  • В ту же степь — вышеупомянутый ускоритель Unity.

  • Есть система локализации Gettext — она просматривает программу на предмет строк и спрашивает у программиста: какие из них подлежат переводу? Те, что подлежат, она вносит в языковый ресурс.

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

Привело это к тому, что годятся не все стили текста.

func f() { // Этот стиль работает

}

func g() // А этот нет — тут автомат ложно поставит точку с запятой

{

}

Вот как-то так, спасибо за внимание!

Показать полностью 1
[моё] Юмор Скриншот IT IT юмор Программирование Компилятор Ответ на пост Длиннопост Текст
28
georgiyozhegov
georgiyozhegov
Лига программистов
Серия Программирование

Используем C в Ассембли⁠⁠

7 месяцев назад

Разрабатывая стандартную библиотеку для своего языка, столкнулся с проблемой: как связывать код написанный на C с ассембли. Первый подход – компиляция C в ассембли и ручное копирование кода – оказался не самым удобным. Две проблемы этого способа это несовместимость синтаксиса GCC и Nasm и постоянное дублирование кода при малейших изменениях.

Решение

Теперь расскажу о способе, который является оптимальным – линковке объектных файлов.

Пример

Приведу пример из моего языка программирования – функция для печати целых чисел.

debug.c

Важно, что функция объявлена с модификатором extern, то есть доступна глобально.


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

debug.c

debug.h

Теперь, создаём объектный файл.

gcc -nostdlib -no-pie -fno-stack-protector -c debug.c -o debug.o

Флаги -no-pie и -fno-stack-protector нужны для совместимости с ассембли.

main.asm

Компилируем и компонуем с объектным файлом стандартной библиотеки

nasm -f elf64 main.asm -o main.o

gcc -nostdlib -no-pie main.o debug.o -o main

Получаем одиночный бинарный файл, в котором включены и стандартная библиотека и главный файл.

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


P.S: Тело функции

Показать полностью 5
[моё] Программирование Языки программирования Компиляция Компилятор Гайд Обучение Длиннопост
13
28
Skyscrew
Skyscrew
Лига Сисадминов

Код на сорок строк⁠⁠

8 месяцев назад
Код на сорок строк
Показать полностью 1
Картинка с текстом Мемы IT юмор Компилятор Код Ошибка
13
19
georgiyozhegov
georgiyozhegov
Лига программистов
Серия Программирование

Путь от Кода до Бинарного Файла⁠⁠

8 месяцев назад

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

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

Этапы

1. Lexing

На этом этапе исходный код в виде строки разделяется на отдельные части, то есть токены. Этот этап – самый простой во всём процессе компиляции.

Вход

let a = 10 + 2

if a > 8 then

debug "A больше 8"

else

debug "А либо меньше, либо равно 8"

end

Выход

[

Let, Identifier("a"), Equal, Integer(10), Plus, Integer(2),

If, Identifier("a"), Greater, Integer(8), Then,

Debug, String("A больше 8"),

Else,

Debug, String("А либо меньше, либо равно 8"),

End,

]

2. Parsing

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

[

Let {

identifier: "a",

value: Binary(Add, Integer(10), Integer(2)),

},

If {

condition: Binary(Greater, Identifier("a"), Integer(8)),

then: [Debug(String("A больше 8"))],

else_: [Debug(String("А либо меньше, либо равно 8"))],

},

]

3. Промежуточное представление (IR)

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

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

Граф потока управления (CFG)

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

Блоки, не содержащие условий

{

0: [

Let {

identifier: "a",

value: Binary(Add, Integer(10), Integer(2)),

},

],

1: [Debug(String("A больше 8"))],

2: [Debug(String("А либо меньше, либо равно 8"))],

3: Empty,

}

Блок Empty – это пустой блок, который не содержит в себе инструкций, и служит только для удобства построения CFG.

И условные переходы между блоками

{

0: Branch { # переход с условием

condition: Binary(Greater, Identifier("a"), Integer(8)),

true_: 1,

false_: 2,

},

1: Direct(3), # прямой переход без условия

2: Direct(3),

}

Трёхадресный код (3AC)

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

Первый блок

[

Label(0),

LoadInteger { to: 0, value: 10 },

LoadInteger { to: 1, value: 2 },

Add { to: 2, left: 0, right: 1 },

Set { identifier: "a", from: 2 },

Get { to: 3, from: "a" },

LoadInteger { to: 4, value: 8 },

Greater { to: 5, left: 3, right: 4 },

JumpIf { condition: 5, label: 1 },

Jump(2),

Второй

Label(1),

LoadString { to: 6, value: "A больше 8" },

Debug { value: 6 },

Get { to: 7, from: "a" },

LoadInteger { to: 8, value: 8 },

Greater { to: 9, left: 7, right: 8 },

JumpIf { condition: 9, label: 3 },

Jump(2),

Третий

Label(2),

LoadString { to: 10, value: "А либо меньше, либо равно 8" },

Debug { value: 10 },

И последний, пустой блок

Label(3),

]

Или в виде псевдо-кода

@0:

#0 = 10

#1 = 2

#2 = add #0 #1

$a = #2

#3 = $a

#4 = 8

#5 = gt #3 #4

jump @1 if #5

jump @2

@1:

#6 = "A больше 8"

debug #6

#7 = $a

#8 = 8

#9 = gt #7 #8

jump @3 if #9

jump @2

@2:

#10 = "А либо меньше, либо равно 8"

debug #10

@3:

4. Ассембли

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

section .data

str_0: db "A больше 8", 0

str_1: db "А либо меньше, либо равно 8", 0

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

section .bss

a: resq 1

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

section .text

global _start

_start:

Делаем _start глобально видимым для того, чтобы линкер смог собрать бинарный файл.

L0:

mov rax, 10

mov rbx, 2

mov rcx, rax

add rcx, rbx

mov [a], rcx

a = rcx = rax + rbx = 10 + 2 = 12.

mov rax, [a]

mov rbx, 8

cmp rax, rbx

mov rcx, 0

setg cl

rcx = rax > rbx = a > 8 = 1 то есть true.

cmp rcx, 1

je L1

jmp L2

Если rcx = 1, то есть true, то переходим в L1, иначе – в L2.

L1:

mov rax, str_0

call debug

debug – это какая-то функция, которая печатает строки в консоль. В целях соблюдения компактности, я не стал её включать в код. Регистр rax – первый аргумент.

mov rax, [a]

mov rbx, 8

cmp rax, rbx

setg rcx

cmp rcx, 1

je L3

jmp L2

L2:

mov rax, str_1

call debug

L2 – начало блока else.

L3:

mov rax, 60

mov rdi, 0

syscall

Выходим из программы, производя системный вызов (syscall). В rax находится номер вызова – 60, то есть выход (SYS_exit). А в rdi лежит статус завершения программы, в данном случае 0, то есть успешное завершение.

Полезное

  • Мой блог про программирование и не только

  • Классика –Crafting Interpreters

  • Исходники компилятора Rust

  • BabyGo – маленький компилятор для Go

  • Серия видео по разработке Porth с нуля

Заключение

Надеюсь вам понравилась эта статья! Она написана на основе моего хобби-компилятора, поэтому если у вас есть желание внести свою лепту в проект – отправляйте пул-реквест в репозиторий!

Показать полностью
[моё] Программа Обучение Гайд Assembler Asm Компиляция Компилятор Программирование Текст Длиннопост
9
18
Skyscrew
Skyscrew
Лига Сисадминов

Смех глобальной переменной⁠⁠

11 месяцев назад
Смех глобальной переменной
Картинка с текстом Мемы Компилятор Переменные
1
636
Skyscrew
Skyscrew
Лига Сисадминов

Что-то забыл⁠⁠

1 год назад
Что-то забыл
Показать полностью 1
Картинка с текстом Мемы Компилятор Программист Рекурсия IT юмор Два с половиной человека
71
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии