- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
// https://govnokod.ru/26890#comment571155
// bormand 2 часа назад #
// Можно брейнфак запилить на операторах. Как раз вроде унарных хватает.
// & * - ~ ! -- + ++ --
#include <array>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <limits>
struct Brainfuck {
public:
using IPType = uint16_t;
constexpr static size_t MAX_MEMORY = std::numeric_limits<IPType>::max();
std::array<uint8_t, MAX_MEMORY> memory{};
std::vector<char> app{};
IPType ip = 0;
IPType cell = 0;
IPType find_matching_tag(IPType cur_ip, char open, char close, int ip_direction)
{
size_t stack_size = 0;
do {
if (app[cur_ip] == close) {
--stack_size;
}
if (app[cur_ip] == open) {
++stack_size;
}
cur_ip += ip_direction;
} while (stack_size > 0);
return cur_ip - ip_direction;
}
IPType find_matching_close_tag(IPType cur_ip)
{
return find_matching_tag(cur_ip, '[', ']', 1);
}
IPType find_matching_open_tag(IPType cur_ip)
{
return find_matching_tag(cur_ip, ']', '[', -1);
}
void loop_open()
{
if (memory[cell] == 0) {
ip = find_matching_close_tag(ip);
} else {
++ip;
}
}
void loop_close()
{
if (memory[cell] != 0) {
ip = find_matching_open_tag(ip);
} else {
++ip;
}
}
void exec(char op)
{
switch (op) {
case '>': ++cell; break;
case '<': --cell; break;
case '+': ++memory[cell]; break;
case '-': --memory[cell]; break;
case '.': std::putchar(memory[cell]); break;
case ',': memory[cell] = static_cast<uint8_t>(std::getchar()); break;
case '[': loop_open(); return; // no ip advancing
case ']': loop_close(); return; // no ip advancing
}
ip++;
}
void run()
{
while (ip < app.size()) {
exec(app[ip]);
}
}
public:
Brainfuck & operator++() { app.push_back('>'); return *this; }
Brainfuck & operator--() { app.push_back('<'); return *this; }
Brainfuck & operator+() { app.push_back('+'); return *this; }
Brainfuck & operator-() { app.push_back('-'); return *this; }
Brainfuck & operator*() { app.push_back('.'); return *this; }
Brainfuck & operator&() { app.push_back(','); return *this; }
Brainfuck & operator!() { app.push_back('['); return *this; }
Brainfuck & operator~() { app.push_back(']'); return *this; }
Brainfuck & operator>>(const Brainfuck &) { run(); return *this; }
};
gost # 0
Перевод из классического «Брайнфака» в крестовый DSL:
bormand # 0
gost # 0 ⇈
bormand # 0 ⇈
MAKAKA # 0 ⇈
Какой еще язык можно так быстро реализовать?
а гост ебанутый малость, это уже очевидно
gost # 0 ⇈
> Его спецификация настолько проста, что ты написал его реализацию за два часа.
И бо́льшая часть времени заняла реализация циклов (только под самый конец осознал, что [ может сразу же переместиться к ], поэтому просто последовательно по одному символу проходить не получится).
bormand # 0 ⇈
bormand # 0 ⇈
Закрывающая скобка цикла "пушит" правую часть в отдельное поле и начинает новую пустую цепочку. Открывающая скобка заворачивает эту цепочку в цикл и пристегивает к запушенному куску.
Ну и у всего этого есть невиртуальный оператор (). Должно неплохо оптимизироваться если в глубину инлайнов не упрется.
bormand # 0 ⇈
S<Plus, Plus, Plus, Loop<Plus, Right, Minus, Left>, Out>
S::operator() { dummy(args()...); } где dummy ничего не делает.
Это вроде лучше инлайниться должно.
bormand # 0 ⇈
bormand # 0 ⇈
Fike # 0 ⇈
MAKAKA # 0 ⇈
bormand # 0 ⇈
TOPT # 0 ⇈
admin # 0 ⇈
TOPT # 0 ⇈
MAKAKA # 0 ⇈
bormand # 0 ⇈
Осталось в операторы обмазать.
bormand # 0 ⇈
bormand # 0 ⇈
Всё, заебало, будет без украшательств. Работает и ладно.
Кстати в компайлтайме проверяет баланс циклов.
bormand # 0 ⇈
gost # 0 ⇈
YpaHeLI_ # 0 ⇈
Для рынка этот язык никчемный.
rotoeb # 0 ⇈
YpaHeLI_ # 0 ⇈
bormand # 0 ⇈
guest # 0
какой чел прекрасный)))
https://github.com/fabianishere/boot2flappy
>Flappy Bird for UEFI written in x86 Assembly.
Борманд, нахуйя под UEFI на асме писать?
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
З.Ы. Ну в CSM ещё фрагменты есть для общения с 16-битной хуйнёй. Но тут явно не этот случай.
guest # 0 ⇈
Вообще круто конечно, я когда учил асм -- змейку писал на псевдографике:)
bormand # 0 ⇈
MAKAKA # 0 ⇈
у меня почти все проги под реальный режим вообще были tiny, это я помню.
Но хуйню, которая грузится с загрузочной дискеты и выводит ":)" я тоже делал когда mbr изучал, а вот про uefi я знаю только в теории(
bormand # 0 ⇈
Да там ничего особо интересного. Гуиды да интерфейсы. Получаешь интерфейс по гуиду да зовёшь методы. Той магии, что была на биосе, там уже нет.
guest # 0 ⇈
bormand # 0 ⇈
32-битный уефи ты в природе хер найдёшь. Вроде больше не выпускают девайсов с ним.
guest # 0 ⇈
Может и стоит в это прыгнуть, но современное железо дохуя сложное.
Классический PC был как-то понятный: вот контроллер прерываний, вот контроллер клавиаутуры (и похуй, что они в чипсет спрятаны уже давно), а теперь понавертели всего.. В ACPI например я хуй знает с какой попытки врублися, и то наверняка не всё про него знаю
bormand # 0 ⇈
В железо тебе там лезть не надо, там всё очень высокоуровневое. Даже к pci лазить будешь через интерфейс а не напрямую.
В прерывания тоже лезть не надо, там все на таймерах да ивентах. Да там кроме таймерного их и нет, лол.
Это по сути простенькая однозадачная ось.
MAKAKA # 0 ⇈
>Даже к pci лазить будешь через интерфейс.
Там прямо сишные функции "энумирейт бас", "считать доступные адреса из спейса" и "настроить девайс"?
> на таймерах да ивентах.
Колбеки типа?
bormand # 0 ⇈
Ну вот разве что у дисплея ты можешь захотеть напрямую порисовать. Там интерфейс тормознутый (адрес, разрешение и формат пикселя он тебе расскажет).
MAKAKA # 0 ⇈
Это может быть важно, чтобы игрушки писать. А для загрузочного экрана наверное пофиг. Тащемто биосный API для видео тоже тормозил.
А для USB? SATA? Для этого говна тоже есть API, или там напрямую не нужно?
bormand # 0 ⇈
Есть интерфейсы для дисков. Рид да врайт.
Есть интерфейс для файлухи. Но изкоробки только фат да исо. Разделы и т.п. само подхватывает и публикует.
В принципе там плуг энд плей даже.
MAKAKA # 0 ⇈
Так прошивка сама всё конфигурит (это ведь и есть плуг энд плей), но ты можешь потом переконфигурить под себя?
А вот ты говоришь, что там си, да? А там надо статически рунтайм весь в себя линковать?
bormand # 0 ⇈
Да, прошивка сама все что может распознает и конфигурит. Лоу-левел интерфейсы это если ты свои дрова собрался писать.
MAKAKA # 0 ⇈
типа
?
Я просто не понял, а откуда я возьму printf?
> Лоу-левел интерфейсы это если ты свои дрова собрался писать.
Кстати, а что случилось с биосами устройств?
Если я сделаю карточку, и хочу чтобы uefi мог с нее грузиться, я могу в карточке разместить какой-то код под efi, который сэмулирует из нее например диск или mass storage usb?
bormand # 0 ⇈
Аллокаторы, сосноль, всё через те таблички.
MAKAKA # 0 ⇈
то есть ответ на мой вопрос про рантайм -- хуй. Ну ок, тоже ничего.
Остался вопрос про биосы устройств
bormand # 0 ⇈
А для всяких usb все и на дженерик дровах взлетает. Мышки, клавы, флешки и т.п.
MAKAKA # 0 ⇈
Спасибо)
bormand # 0 ⇈
guest # 0 ⇈
А на чем дебажить? На виртуалках?
bormand # 0 ⇈
MAKAKA # 0 ⇈
bormand # 0 ⇈
MAKAKA # 0 ⇈
или у виртуалок есть интерфейсы для дебага uefi?
bormand # 0 ⇈
MAKAKA # 0 ⇈
MAKAKA # 0 ⇈
куему может
bormand # 0 ⇈
MAKAKA # 0 ⇈
мои первым кодом было мигание лампочками на клаве.. там был io порт вроде, и туда надо было писать
bormand # 0 ⇈
guest # 0 ⇈
HoBorogHuu_nemyx # 0 ⇈
AHCKujlbHblu_netyx # 0 ⇈
guest # 0 ⇈
в паскале тоже?
bormand # 0 ⇈
guest # 0 ⇈
я чото не помн
вот в сишечке помню даже макрос(?) был для сегмент-смещение
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
Я всё проебал уже.
У меня бывают иногда мысли запилить такой хакатон для реконструкторов: берешь досбокс, борландсишечку третью, и хуячишь чонить под реальный режим. Ну типа как чуваки некоторые викингов косплеят
bormand # 0 ⇈
А фиг знает, возможно в старых бекапах есть. Я давно туда не заглядывал. Может быть уже и проебал.
HoBorogHuu_nemyx # 0 ⇈
guest # 0 ⇈
А как еще быть?
near, far, huge, ой, как вспомню...
HoBorogHuu_nemyx # 0 ⇈
guest # 0 ⇈
Просто ключ словами не срут уже в современном мире, но расширения компилятора вполне могут сделать.
__alignof__ например
defecatinho # 0 ⇈
OCETuHCKuu_nemyx # 0
nymuH_XyuJlo # 0
3.14159265 # 0
Pig # 0
bormand # 0 ⇈
guest # 0 ⇈
Сколько питухов на это наступило -- это просто пиздец
Pig # 0 ⇈
guest # 0 ⇈
просто не понятно какие именно
bormand # 0 ⇈
Нет. Чтение неинициализированных данных - UB. Вплоть до полного разрушения логики и true = false в других местах программы.
Не надо так делать.
guest # 0 ⇈
А такое в реальной жизни может быть?
>Не надо так делать.
никогда так не делал, конечно
bormand # 0 ⇈
Ну с int или char, скорее всего, ничего особо страшного не случится.
guest # 0 ⇈
Если енум может быть 1,2,3 а там 4, то буй знает, как он будет работать дальше
bormand # 0 ⇈
А флоат просто крашнуть процесс может. Хотя это обычно отключено.
guest # 0 ⇈
a == b
а в другом на false проверяется как a == 0
если у тебя в a == 1, а в b 2, то они оба true, но не равны
типа такого?
>А флоат просто крашнуть процесс может.
FPU охуеет от мусора?
bormand # 0 ⇈
guest # 0 ⇈
хорошо, что никогда так не делал
зы: прикольно, что клюнуть тебя это может через 4 часа в другом месте программы на конкретном CPU, например
охуеть)
guest # 0 ⇈
guest # 0 ⇈
кстати, в с89 нет никаких булен
именно потому я за борлад си 3
но float всё равно есть
bormand # 0 ⇈
Там вроде только при нормальном касте в инт гарантируется единичка. А в самом буле запросто может лежать FF.
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
guest # 0 ⇈
или нет?
guest # 0 ⇈
guest # 0 ⇈
потому что (bool)1 не обязан был байтом?
guest # 0 ⇈
bormand # 0 ⇈
Ну и ты забиваешь его единичками а не true.
guest # 0 ⇈
guest # 0 ⇈
если bool больше char, то я отсосу
>Ну и ты забиваешь его единичками а не true.
так разве (bool) не должен превратить единичку в true?
ну ок, а если бы там true было?
отсос правда все равно будет, если бул больше байта
guest # 0 ⇈
guest # 0 ⇈
вот так тоже нельзя?
guest # 0 ⇈
Но true может быть и 0xFF
guest # 0 ⇈
каст единицы в бул разве не должен представить его в настоящее представление бул? Это же не реинтерпретер по сути, а статик, не?
всё, понял: (int)true == 1, даже если там не 1
bormand # 0 ⇈
Каст була в инт возвращает 0 или 1. Независимо от внутренного представления була.
Каст инта в бул возвращает false для 0 и true для остального. Независимо от внутренного представления була.
guest # 0 ⇈
guest # 0 ⇈
guest # 0 ⇈
memset нифига не "байтами" заполняет, а интами
ужасно
bormand # 0 ⇈
Ну он чарами заполняет. Просто исторически сложилось, что он в интерфейсе инт принимает.
guest # 0 ⇈
(int32 g[100500])
guest # 0 ⇈
Если бы там был char, то был бы каст в чар, а толку
bormand # 0 ⇈
Нельзя. Ты заполняешь единичками а не true ибо memset принимает int, а (int)true это 1. Он не шаблон.
std::fill(std::begin(bools), std::end(bools), true) и не еби мозг.
guest # 0 ⇈
ох ебать
guest # 0 ⇈
bormand # 0 ⇈
Но memset принимает int. А (int)(bool)1 это 1. А true это не обязательно 1. И вообще бул может быть больше байта (хотя я такого идиотизма нигде не видел).
bormand # 0 ⇈
guest # 0 ⇈
так
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
Ну, по крайней мере, там будет false а не UB.
guest # 0 ⇈
ладно, так то можно?
?
bormand # 0 ⇈
З.Ы. А, это MS так позиксовые функции уродует.
guest # 0 ⇈
>уродует
да, у них есть CopyMemory свой
bormand # 0 ⇈
Имхо, лучше уж явно проверить в начале, возможно даже static_assert'ом. А потом и обычный memcpy сойдёт.
guest # 0 ⇈
CopyMemory(bools2, bools, sizeof(bools));
или как-то так
bormand # 0 ⇈
guest # 0 ⇈
bools[FOO] ..
bools2[FOO]..
же
bormand # 0 ⇈
guest # 0 ⇈
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
А потом присвою ему массив на 200 интов?
я не пишу на крестах просто, я и на няшной раз в год пишу, и стараюсь всё делать явно, чтобы не словить багра
bormand # 0 ⇈
Только одного типа и размера можно присваивать друг другу.
guest # 0 ⇈
а конструктора тоже нет? нельзя myArray(hugeArray)?
bormand # 0 ⇈
guest # 0 ⇈
в моем жабоёбном мире анскилябров все говно работает через указатели, так что можно присваивать, размер там чисто динамическое понятие
guest # 0 ⇈
bormand # 0 ⇈
Ну вектора и мапы всякие с кучей работают.
guest # 0 ⇈
vector растет динамически, и делает это в куче?
bormand # 0 ⇈
Ну как ваш ArrayList.
guest # 0 ⇈
А бывают такие платформы, где нету кучи, а только стек?
Если да, то там C++ не работает получается?
В няшной по идее в них можно было бы убрать malloc, и всё
bormand # 0 ⇈
И даже вообще без стандартной либы. Но это уже просто няшная с RAII и шаблонами.
guest # 0 ⇈
bormand # 0 ⇈
И исключения тоже, по крайней мере в gcc. Там чуть-чуть аллокатор зовётся при старте. Возможно и потом при каких-то условиях (слишком жирное исключение или второе подряд?) Я сильно не изучал.
Придётся на них тоже забить если кучи нету.
guest # 0 ⇈
bormand # 0 ⇈
sizeof(bool) is not required to be 1
guest # 0 ⇈
или сделать массив bool, взять его адрес, и местенуть?
MAKAKA # 0 ⇈
кроме чара и байта вроде, это довольно логично
вероятно, и массив байтов можно читнуть
gost # 0 ⇈
MAPTbIwKA # 0 ⇈
if an indeterminate value of type unsigned char or std::byte (since C++17) is assigned to another variable of type (possibly cv-qualified) unsigned char or std::byte (since C++17)(the value of the variable becomes indeterminate, but the behavior is not undefined);
https://en.cppreference.com/w/cpp/language/default_initialization
Если я верно понимаю, то написано так:
Да, ты можешь считать любое значение. Но компьютер не сгорит. А если ты считаешь его из булена, например, то у тебя может нарушиться true != false или еще что-то такое
gost # 0 ⇈
Ты можешь присвоить indeterminate value из одного байта только другому байту. Если ты потом попытаешься получить доступ к этому indeterminate value (например, попробуешь его вывести на экран) — всё равно получишь UB.
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
Хотя, с другой стороны, они обычно volatile поэтому конпелятор не выёбывается.
guest # 0 ⇈
MAPTbIwKA # 0 ⇈
Ну ведь это же логично: один байт всегда валиден, какое бы говно ты туда ни пихнул.
А int совсем нет.
Допустим, на какой-то системе старший бит инта обязан быть единицией. Или обязан быть чексуммой. Если это не так, то процессор взрывается.
А ты сунул туда говно, и всё сломалось.
> Если ты потом попытаешься получить доступ
хм.
А вот тут я не уверен: является ли UB вывод этого байта в cout?
bormand # 0 ⇈
Хотя... если он прям сразу в буфер с байтами пишется...
MAPTbIwKA # 0 ⇈
char a;
char b[1];
b[0] = a;
так можно?
C++ стоит учить именно ради того, чтобы вести такие беседы,лол
bormand # 0 ⇈
Хотя, емнип, примеры в стандарте не являются нормативными и на них нельзя строить пруфы.
MAPTbIwKA # 0 ⇈
А взять любые 4 байта и сказать "вот инт" я не могу: это может быть не правдой.
Так я трактую cppref, но надо читат стандарт
gost # 0 ⇈
§ 6.7.4/2
bormand # 0 ⇈
MAPTbIwKA # 0 ⇈
пускай я хочу чтобы там был любой мусор в зависимости от желания компилятора
зачем мне тратить инструкцию на заплнение инта чем-то?
bormand # 0 ⇈
MAPTbIwKA # 0 ⇈
bormand # 0 ⇈
З.Ы. Но по стандарту там и на входе и на выходе конечно же байты.
gost # 0 ⇈
Все выводящие байт функции (put, putchar, fputc, etc.) принимают int, поэтому вывод через них — является. Аргументы всех функций форматированного вывода (fprintf, printf, etc.) сначала integer promotятся, поэтому через них тоже вывести не получится. А поведение basic_ostream::operator<<(..., unsigned char) по Стандарту я сейчас подробно изучаю.
MAPTbIwKA # 0 ⇈
интресно про стрим
Pig # 0 ⇈
gost # 0 ⇈
Pig # 0
Скобки нахуя?
gost # 0 ⇈
MAKAKA # 0 ⇈
Так понимаю, что до 11 у тебя вообще выбора не было: фигурные скобочки писать было нельзя, а круглые (благодаря Most vexing parse) -- тоже.
gost # 0 ⇈
Pig # 0
gost # 0 ⇈
Pig # 0
Так вот зачем лалки придумали «cstdio» вместо «stdio.h».
gost # 0 ⇈
Pig # 0
bormand # 0 ⇈
Ибо массив на 65535 элементов вместо 65536.
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
Да это-то похуй, несбалансированные циклы — это UB. А вот память задумывалась полноценно циклической.
bormand # 0 ⇈
Слова не мальчика, но крестостандартизатора.
YpaHeLI_ # 0 ⇈
Что-то гугл мне не помог по этому понятию, где о них почитать?
У Кнута?
bormand # 0 ⇈
bootcamp_dropout # 0 ⇈
Pig # 0
gost # 0 ⇈
guest # 0
Типичные крестовики это Борманд и Гост, постоянно пишущие, что С++ -- монструозное говно.
А типичный PHPшник это Конардо.
Я пришел к выводу, что программисты на С++ более интеллектуально развиты, и как следствие более склонны к рефлексии. Подобный паттрен мы наблюдает не только у программистов: умные люди часто путаются и рвутся, думая "а не хуйню ли я сделал?", в то время как дебилы всегда жизнерадостны, и полностью уверены в своей правоте.
Думаю, дело в этом.
Да?
bootcamp_dropout # 0 ⇈
guest # 0 ⇈
bootcamp_dropout # 0 ⇈
Получается что php получилось довести до совершенства только за 7 версий,
а с++ и за 20 не смогли
guest # 0 ⇈
bootcamp_dropout # 0 ⇈
наверное сишники опять проебались и случилось переполнение численного типа
guest # 0 ⇈
По какой-то причине win10 новее win95, хотя очевидно же, что 10 меньше!
Ебланы
bootcamp_dropout # 0 ⇈
guest # 0 ⇈
блин, переписали бы ее на JS, работала бы быстрее!
Myxa # 0 ⇈
https://bellard.org/jslinux/
Да, тот самый Фабрис.
rotoeb # 0 ⇈
Myxa # 0 ⇈
Pig # 0
> public:
Структура и так public. И по смыслу здесь не структура, а класс.
guest # 0 ⇈
Pig # 0 ⇈
gost # 0 ⇈
Pig # 0
Просто охуенное название переменной.
Pig # 0 ⇈
Первое о чём подумал, нахуя здесь тип айпишника, и при чем он в brainfuck.
gost # 0 ⇈
Pig # 0 ⇈
bootcamp_dropout # 0 ⇈
guest # 0 ⇈
Pig # 0
Pig # 0
std::string
Программа по смыслу - это строка.
gost # 0 ⇈
Ну и по-хорошему там вообще должен быть std::deque<char> и push_front() в операторах.
bormand # 0 ⇈
Ну видимо потому что вектор позже появился. А хреновых строк уже понаписали.
Pig # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
В первых крестах даже контейнеров и алгоритмов то не было, стринг да иострим.
guest # 0 ⇈
bormand # 0 ⇈
А вот для вектора он явно требует амортизированное О(1).
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
И комитет всегда реально ссыт кому-то что-то сломать.
Там до смешного доходит, когда новые классы добавляют вместо того, чтобы пофиксить старые. И теперь у тебя есть выбор между scoped_lock, unique_lock и lock_guard.
guest # 0 ⇈
Можно хранить capacity в первых байтах строки, а саму строку со сдвигом.
bormand # 0 ⇈
guest # 0 ⇈
UPD: всё, понял
Если я передам в какую-то другую либу новую строку, то она охуеет.
bormand # 0 ⇈
Oh, my sweet summer child...
bormand # 0 ⇈
Надо глянуть, может там добавили пункт про О(1) у строки.
defecate-plusplus # 0 ⇈
bormand # 0 ⇈
bormand # 0
Или код длиннее 65к - тоже UB?
Pig # 0 ⇈
bormand # 0 ⇈
Pig # 0 ⇈
gost # 0 ⇈
Подтверждаю, инженерный отдел напутал cell и app.
> Или код длиннее 65к - тоже UB?
А и то правда!
Pig # 0 ⇈