The post has been translated automatically. Original language: Russian
In system programming, it is often necessary to work not with the whole number, but with individual bits inside it. A single 32-bit value can simultaneously describe the state of multiple devices, events, channels, or resources.
For example, each bit can indicate the presence of an event, resource occupancy, or device availability. Therefore, the program regularly needs to find the first bit with a certain value and get its number.
In Sekura JS, a separate bit search operation has appeared for this task. It allows you to specify the initial 32-bit value, the initial position, and the search direction.
Why do I need a separate operation?
You can also find the right bit using ordinary logical operations. To do this, the program can sequentially check the bits, perform shifts and comparisons.
For a single case, this approach is quite acceptable. But in system software, bitmasks are used all the time: for events, queues, resource availability, device status, and various small tables.
As a result, the same sequence of actions begins to be repeated in many places of the program.
Therefore, it makes sense to express the search for a bit as an independent operation of the language.
Unit Search
One of the main options is to find the first bit with the value 1.
It is convenient to use this operation when one means the presence of an event or an active state.
For example, 32 bits can correspond to 32 groups of devices. If a certain bit is equal to one, an event has appeared in this group that needs to be processed.
The search operation immediately returns the number of the first suitable position. The program does not need to manually iterate through all 32 bits.
Zero Search
The reverse case is equally useful — searching for the first bit with the value 0.
For example, a mask can describe resource usage.:
1 — the resource is occupied
0 — the resource is freeThen searching for the first zero allows you to quickly identify the first free resource.
This way you can find free buffers, channels, table positions, or other available items.
Two-way search
The operation allows you to choose a direction.
You can start from a certain position and move to the higher numbers of the bits. You can use the same starting position and move in the opposite direction.
For example, the search may take place:
12, 13, 14, ... 31or:
12, 11, 10, ... 0This means that separate left and right search operations are not required.
You can start from any position.
An important feature of the operation is that the search does not necessarily start from the edge of a 32-bit value.
Let's say the program has already found a suitable bit with the number 5 and processed it. The next search can be started immediately from position 6.
This is convenient when sequentially bypassing all active mask elements. You don't need to shift the original value every time or create a new intermediate mask.
What the operation returns
If a suitable bit is found, the result is its number from 0 to 31.
If there is no such bit in the selected direction, the value 32 is returned.
This result is convenient because 32 is not a valid bit number in a 32-bit value. Therefore, a separate indication of the success of the search is not required.
The logic turns out to be simple:
0-31 — bit found
32 — there is no suitable bitOne mechanism for multiple tasks
In fact, one operation covers four main cases:
- searching for a unit to the highest bits;
- searching for the unit to the low-order bits;
- searching for zero to high-order bits;
- searching for zero to the low-order bits.
In all cases, you can also set the starting position.
This allows you not to introduce several almost identical functions into the language and keep one common search model.
Communication with the Memora8 processor
The appearance of this operation in Sekura JS is related to the Memora8 architecture.
The processor considers a hardware unit that searches for the desired bit directly above the 32-bit value. Two forms of machine instruction are provided for it: one works with a parameter from a register, the other with a constant value written directly into the instruction.
The Sekura JS compiler can choose the appropriate form on its own.
If the direction and the starting position are known in advance, one option is used. If they are calculated during the execution of the program, another one is used.
For a programmer, this difference remains hidden.
A language describes a meaning, not a machine command.
Despite the hardware support, Sekura JS does not require the programmer to write specific processor commands.
The source code describes the search operation itself. The compiler already decides how to implement it on the target platform.
This is an important division. The semantics of the language remains stable even if the internal structure of the processor changes over time.
Why is it useful for the system language?
Sekura JS is being developed as a system language, so working with bit masks is a common task for it.
Such masks are used in event processing, device management, resource allocation, and queuing.
If one low-level operation is constantly repeated in system programs and can be performed compactly in hardware, it makes sense to make it part of the language.
At the same time, the operation should remain small and unambiguous in meaning.
From program to hardware without unnecessary intermediate steps
The result is a fairly short chain.:
search operation in Sekura JS
↓
compiler
↓
machine instruction Memora8
↓
hardware bit searchThe programmer describes the task at the language level, and the processor gets the opportunity to perform it directly.
The main idea is simple: if system programs regularly work with 32-bit masks, the search for the desired bit can be expressed in one understandable operation instead of repeating the same sequence of shifts, checks and transitions.
В системном программировании часто приходится работать не с числом целиком, а с отдельными битами внутри него. Одно 32-битное значение может одновременно описывать состояние нескольких устройств, событий, каналов или ресурсов.
Например, каждый бит может показывать наличие события, занятость ресурса или готовность устройства. Поэтому программе регулярно требуется найти первый бит с определённым значением и получить его номер.
В Sekura JS для этой задачи появилась отдельная операция поиска бита. Она позволяет указать исходное 32-битное значение, начальную позицию и направление поиска.
Зачем нужна отдельная операция
Найти нужный бит можно и с помощью обычных логических операций. Для этого программа может последовательно проверять биты, выполнять сдвиги и сравнения.
Для единичного случая такой подход вполне приемлем. Но в системном программном обеспечении битовые маски используются постоянно: для событий, очередей, доступности ресурсов, состояния устройств и различных небольших таблиц.
В результате одна и та же последовательность действий начинает повторяться во многих местах программы.
Поэтому возникает смысл выразить поиск бита как самостоятельную операцию языка.
Поиск единицы
Один из основных вариантов — найти первый бит со значением 1.
Такую операцию удобно использовать, когда единица означает наличие события или активное состояние.
Например, 32 бита могут соответствовать 32 группам устройств. Если определённый бит равен единице, в этой группе появилось событие, требующее обработки.
Операция поиска сразу возвращает номер первой подходящей позиции. Программе не требуется вручную перебирать все 32 бита.
Поиск нуля
Не менее полезен обратный случай — поиск первого бита со значением 0.
Например, маска может описывать использование ресурсов:
1 — ресурс занят
0 — ресурс свободенТогда поиск первого нуля позволяет быстро определить первый свободный ресурс.
Так можно находить свободные буферы, каналы, позиции в таблице или другие доступные элементы.
Поиск в двух направлениях
Операция позволяет выбирать направление.
Можно начинать с определённой позиции и двигаться к старшим номерам битов. Можно использовать ту же начальную позицию и двигаться в противоположную сторону.
Например, поиск может проходить:
12, 13, 14, ... 31или:
12, 11, 10, ... 0Благодаря этому отдельные операции для поиска слева и справа не требуются.
Начинать можно с любой позиции
Важная особенность операции состоит в том, что поиск не обязательно начинается с края 32-битного значения.
Допустим, программа уже нашла подходящий бит с номером 5 и обработала его. Следующий поиск можно начать сразу с позиции 6.
Это удобно при последовательном обходе всех активных элементов маски. Не требуется каждый раз сдвигать исходное значение или создавать новую промежуточную маску.
Что возвращает операция
Если подходящий бит найден, результатом является его номер от 0 до 31.
Если такого бита в выбранном направлении нет, возвращается значение 32.
Такой результат удобен, потому что 32 не является допустимым номером бита в 32-битном значении. Поэтому отдельный признак успешности поиска не требуется.
Логика получается простой:
0–31 — бит найден
32 — подходящего бита нетОдин механизм для нескольких задач
По сути одна операция покрывает четыре основных случая:
- поиск единицы к старшим битам;
- поиск единицы к младшим битам;
- поиск нуля к старшим битам;
- поиск нуля к младшим битам.
Во всех случаях также можно задавать начальную позицию.
Это позволяет не вводить в язык несколько почти одинаковых функций и сохранить одну общую модель поиска.
Связь с процессором Memora8
Появление этой операции в Sekura JS связано с архитектурой Memora8.
В процессоре рассматривается аппаратный блок, который выполняет поиск нужного бита непосредственно над 32-битным значением. Для него предусмотрены две формы машинной команды: одна работает с параметром из регистра, другая — с постоянным значением, записанным непосредственно в инструкции.
Компилятор Sekura JS может самостоятельно выбирать подходящую форму.
Если направление и начальная позиция известны заранее, используется один вариант. Если они вычисляются во время выполнения программы, используется другой.
Для программиста это различие остаётся скрытым.
Язык описывает смысл, а не машинную команду
Несмотря на аппаратную поддержку, Sekura JS не требует от программиста писать конкретные команды процессора.
В исходном коде описывается сама операция поиска. Компилятор уже решает, каким способом реализовать её на целевой платформе.
Это важное разделение. Семантика языка остаётся стабильной даже в том случае, если внутреннее устройство процессора со временем изменится.
Почему это полезно именно системному языку
Sekura JS разрабатывается как системный язык, поэтому работа с битовыми масками является для него обычной задачей.
Такие маски используются при обработке событий, управлении устройствами, распределении ресурсов и организации очередей.
Если одна низкоуровневая операция постоянно повторяется в системных программах и при этом может компактно выполняться аппаратно, есть смысл сделать её частью языка.
При этом операция должна оставаться небольшой и однозначной по смыслу.
От программы к аппаратуре без лишних промежуточных действий
В результате получается достаточно короткая цепочка:
операция поиска в Sekura JS
↓
компилятор
↓
машинная команда Memora8
↓
аппаратный поиск битаПрограммист описывает задачу на уровне языка, а процессор получает возможность выполнить её непосредственно.
Главная идея проста: если системные программы регулярно работают с 32-битными масками, поиск нужного бита можно выразить одной понятной операцией вместо повторения одной и той же последовательности сдвигов, проверок и переходов.