- 1
- 2
#define add(x, y) &((void*)x)[y];
#define mul(x, y) (sizeof (char[x][y]))
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+6
#define add(x, y) &((void*)x)[y];
#define mul(x, y) (sizeof (char[x][y]))
из свитера
Воды одриснённой, нечистой.
С лица его падал пот, сажи следы,
Услышал он речь машиниста.
https://godbolt.org/z/YaKK8P
Тут же нет разыменования: мы берём & от данных, а с самими данными ничего не делаем.
а чтобы я еще лучше понял, мне пи lea показал
Так сказано, будто это что-то плохое.
Кстати первая версия и в сишке не компилилась.
Я второпях забыл что в compound literals нужно ставить скобки вокруг типа.
Даже в препроцессоне?
if уже есть.
Деление можно будет и скобенировать.
Мысль хорошая. Но там ещё финальный сдвиг вправо нужен.
Только это на константу.
Для пельменных так не получится.
Пока что не могу откастить массив int32_t в массив char
Я уже в struct их пихал, чтобы сделать flexible array member.
Думаю через вложенные макросы и массивы массивов массивов это реализуемо.
Дерзай.
Переменный показатель можно реализовать рекурсией. Но это уже не то...
Постоянное основание иногда можно реализовать через сдвиги. Но как вытянуть сдвиги из указателей, я не знаю.
В общем случае можно двойку возводить в степень произведения показателя на логарифм основания по основанию 2. Но если основание не является степенью двойки, вылезет плавпитух... Ну и опять же, как вытянуть этот логарифм, я не знаю.
Делит!
https://ideone.com/sNzX8P
Я сейчас пытаюсь по модулю 2 реализовать через структуру, [0...100]={{0,1}}, и каст с чар
не получаеццо (((
И отрицательные тоже, лол.
https://ideone.com/F5CPSJ
Асемблерный выхлоп чист как слезинка лалки:
Я чото не могу распарить, пойду посплю.
Упростил до невозможности ценой UB.
When two pointers are subtracted, both must point to elements of the same array object or just one past the last element of the array object (C Standard, 6.5. 6 [ISO/IEC 9899:2011]); the result is the difference of the subscripts of the two array elements. Otherwise, the operation is undefined behavior.
Массив — это указатель (с оговорками).
Инкремент указателя, увеличивает его значение на размер типа.
Типичная ошибка начинающих:
По сути можно считать инкремент указателя «перегруженным» аки итератор в крестах.
Edit: кстати там нужно было наоборот, return y-x; но всё-равно это UB-говнище )))
https://en.cppreference.com/w/c/types/ptrdiff_t
Там разложены забавные грабли:
ptrdiff_t is used for pointer arithmetic and array indexing, if negative values are possible. Programs that use other types, such as int, may fail on, e.g. 64-bit systems when the index exceeds INT_MAX or if it relies on 32-bit modular arithmetic.
Only pointers to elements of the same array (including the pointer one past the end of the array) may be subtracted from each other.
If an array is so large (greater than PTRDIFF_MAX elements, but less than SIZE_MAX bytes), that the difference between two pointers may not be representable as ptrdiff_t, the result of subtracting two such pointers is undefined.
For char arrays shorter than PTRDIFF_MAX, ptrdiff_t acts as the signed counterpart of size_t: it can store the size of the array of any type and is, on most platforms, synonymous with intptr_t).
ptrdiff_t — знаковый (т.к. разность).
size_t — беззнаковый (т.к. размер).
Потому PTRDIFF_MAX может быть меньше SIZE_MAX.
Из-за этого случаются забавные багры.
https://govnokod.ru/5026#comment65072
https://govnokod.ru/5026#comment65075
Действительно, массив не обязан иметь ничего общего с указателями, особенно если вспомнить сегментную модель
В реальном режиме вместо каста нужно применять формулу segment*16+offset. Обратно тоже можно, хотя обратное преобразование уже не будет однозначным (в смещение можно поместить от 4 битов до полного размера смещения).
В защищённом для получения линейного адреса нужно брать базу из таблицы дескрипторов: ldt[selector].base+offset (псевдокод). А вот обратного преобразования из линейного адреса в указатель уже может не быть. Если нет готового селектора с подходящей базой, его нужно создавать.
Не массив не имеет ничего общего с указателем, а линейный адрес. Разность указателей, преобразование линейного адреса в указатель становятся нетривиальными задачами.
В «обычных» размер массива был ограничен размером смещения (near ptr), например, 64K для 16-битного кода. Ну чтобы сегменты не переключать.
В huge размер массива не был ограничен. Кодогенератор высирал очень сложный код, который при итерации массиву отслеживал границы сегментов, чтобы в нужный момент переключить селектор.
intptr_t и uintptr_t в сегментной модели не имеют смысла. В сегментной модели длинные указатели по сути являются структурой из двух полей: сегмент(селектор) и смещение. Так что знаковость/беззнаковость нужно применять не к указателю, а к отдельным его полям.
Короткие указатели — да, числа. В моделях, кроме huge, максимальное значение короткого указателя совпадает с максимальным размером массива (минус один).
Где intptr_t и uintptr_t могут иметь смысл? В несегментных моделях, в которых по какой-то причине максимальный размер массива не совпадает с размером адресного пространства.
Забавно, что мы как-то с Бормандом про это говорили, и я жаловался, что даже в 64х битной джаве или .net у меня размер массива 32х битный int
Поэтому там мапается какой-то небольшой кусок (на 52 бита что ли?). А остальные биты по знаковым правилам догоняются до 64. И получается положительный кусок для юзера и отрицательный кусок для ядра, а между ними дырка. Чтобы когда интел добавит больше битов в пейджтейблы твои указатели продолжили работать без изменений в коде.
| память юзера | ... дырка на будущее... | память ядра |
Там сверху будет оборудование, а снизу ram, и адрес ограничен макс объемом памяти cpu?
Да там ёбаная помойка из-за легаси же. Дырки под хуйню в первом мегабайте. Дырки под иса хуйню чуть выше. Дырки под apic и флешку в конце четвертого гига. Ну дальше вроде всё ровно.
Интересно, сколько пирфоманса в кремнии теряется из-за этой совместимости.
* http://lkml.iu.edu/hypermail/linux/kernel/0008.0/0465.html
(но чел не прав, кмк, туда видяха мапилась)
>, сколько пирфоманса в кремнии теряется из-за этой совместимости.
Скока вообще всего теряется из за реального режма, сегментов, хардварного переключения тасок и прочей хуиты
Ну это и есть isa memory hole, не?
То есть не всех исов, а именно видях
А потом люди жалуются почему в жабе всё знаковое и массив на всю память не пильнуть...
З.Ы. Кому вообще понадобилась отрицательная разность указателей? Вот реально, кто-то вычитает больший из меньшего?
Сказали бы, что вычитать надо в правильном порядке, иначе 2s complement. Хотя это и сейчас можно через каст в uintptr_t перед вычитанием.
> cppreference
Кстати код можно было записать и короче, убрав касты.
Однако в этом случае появляются ворнинги.
Это же божественная сишка. А в кресты VLA разве ещё не завезли?
Другое дело, то что VLA дополнительно завёрнут в структуру.
в вижалси их нет
у тебя вижал си?
Нет, он просто крестовик.
Вероятно, шкуз из той же оперы.
> Да и щас можно сраться.
> Pig (U, R) ☓ насрал в #3323
> Ладно, я сам обосрался.
)))
А разгадка проста:
Читать далее ==>
Это UB и конпелятор вообще забил на этот кейс, просто idiv, который он писал для положительных, проканал?
Интересно что он ставит также imul.
Думаю со сложениями неправильно и не получится. Ведь в дополнительном коде операции со знаковыми и беззнаковыми по сути одинаковы.
Потому когда оно неявно кастит unsigned size_t в int то результат эквивалентен.
Вот в прямом и обратном коде это не сработает, но где же взять такую машину или хотя бы компилятор?
Edit: Я бегло глянул на других архитектурах там тоже умножение знаковое.
Лол, т.е. сишники смеялись над жабой, что там знаковый размер массива. А на деле он и в сишке через знаковое умножение вычисляется?
А вообще - попробуй беззнаковые инты на входе.
Везде умножение знаковое.
Я уж думал из-за интов, написал ему явно:
>unsigned mul(size_t x, size_t y) {
Выхлоп не меняется.
В MIPS кстати сложение беззнаковое addu $2,$4,$5
Но, как я указал выше, для сложения побитовый результат, интерпретированный как signed будет верным.
Впечатляет.
https://godbolt.org/z/9n6MKc
Я не могу понять почему такой выхлоп.
На остальных рахитектурах нормально. Например RISC V
Ты же сам писал:
>>> When two pointers are subtracted, both must point to elements of the same array object or just one past the last element of the array object (C Standard, 6.5. 6 [ISO/IEC 9899:2011]); the result is the difference of the subscripts of the two array elements. Otherwise, the operation is undefined behavior.
y здесь точно не является элементом того же массива, что и x, поэтому на любом входе это UB.
Даже если сделать без UB (через массив), то ассемблерный выхлоп вообще не меняется.
На ARM64 он нормальный, а вот на ARMе какая-то питушня:
ARM
ARM 64
Нетипизированное B-style распиздяйство до добра не доводит.
На отрицательных компилятор ругается:
Так же мне удалось найти баги:
https://ideone.com/ukiT12
Несмотря на явное указание int32_t оно похоже считает их беззнаковыми.
Беда в том, что в сишке типизация слабая, и тут int32_t кастится в size_t даже без ворнингов.
А ICC возвращает константу.
https://godbolt.org/z/TEd47s6oW
А в С++ вообще нет никаких VLA.
> констэкспрами можно что-нибудь сделать
Думаю ими можно почти всё. Но тогда весь смысл хака исчезнет, подменившись шаблонюшней.
При этом все компиляторы начинают работать правильно, если задать у массивов фиксированные значения.
Причём свёртывают (включая TCC) в компайл-тайме.
То есть макрос будет хорошо работать только на заранее известных константах, которые можно вычислить в compile-time.
Не понял. А зачем такие костыли с VLA?
Можно же без него. См. начало треда.
FMA = fuzzed mul-add = x*y+z.
Или так:
*везде кроме убогого MSVC
error C2148: total size of array must not exceed 0x7fffffff bytesx86 msvc v19.0 (WINE) #1
> можно было min(x, y) = sum(x, y) - max(x, y)
Вот, пужулуйста
Тоже неплохо.
https://ideone.com/ywg924
Кстати вариант с минусами считал 0 максимальным. А с побитовыми отрицанием такого бага нет.
Там же будут два типа указателей: на данные (вроде void *) и на код (вроде void(*)(void)). У этих указателей может не совпадать размер, если мощности пространства данных и пространства кода разные.
Это не к этому коду, просто вопрос.
Был же такой прикол, когда у тебя есть Child, а ты его кастишь в void*, а потом реинтерпретером в Parent, и пихаешь в функцию, ожидающую Parent.
В жабке или C# было бы ничего стращного, но в крестах будет бадабум
в крестах так не принято, к счастью
Так что даже в long mode не чистый flat, а смешанная модель.
Луникс иногда использовал FS для внутренних нужд. За это отвечал один бит в этом регистре.
И установить его можно было только сискалом.
Однако Штеуд внедрил инструкции для прямой записи в эти регистры.
И это приводило к тому что можно было из юзерспейса поменять смысл FS, и повысить привилегии.
Дело осложнилось SGX, который вроде называется Secure что-то, а на деле — решето.
SGX выступил ещё одним вектором атаки.
https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/best-practices/guidance-enabling-fsgsbase.html
Но ситуацию спас сотрудник Макрософт (!) Саша Левин, который допилил для Linux необходимые ядру изменения.
http://lkml.iu.edu/hypermail/linux/kernel/2008.0/02467.html
Почитайте ссылки, там очень добротный контент.
Итак:
1. В третьем кольце защиты нельзя сделать MOV GS, 42
2. На это полагалось ядро Линукса.
3. В Ivy Bridge появились четыре инструкции, позволяющие модифицировать FS и GS даже из третьего кольца.
4. На эту возможность ядро Линукса не было рассчитано.
5. Но эти действия можно запретить битом в CR4.
Всё правильно понял, ничего не наврал?
Но упустил самое вкусное, на десерт:
> The SGX-LKL project is designed to run existing unmodified Linux binaries inside of Intel SGX enclaves.
https://github.com/lsds/sgx-lkl/issues/528
во времена микроядер была такое мысль
А вот в ARM всё хуже. PL0 для юзермода, PL1 для ядра, PL2 для гипервизора. В ARMv8 добавили ещё один, аналог SMM. А вот промежуточных уровней у ARM нету.
Приложение само запускает часть кода в анклаве, доступа к данным которого нет больше ни у кого (может кроме NSA в ring -2 и -3).
Особенно пиздец в этом всём, что технология со словом «Secure» в названии активно используется для повышения привилегий.
Вдвойне пиздецово, то что SGX позволяет скрывать чем занимается процесс и данные даже от администраторов. Что идеально для запуска и сокрытия вредоносного кода от сканеров.
Нашёл реальный пример, как на Винде были схожие проблемы
Intended to protect sensitive information from snooping, SGX allows applications to lock off areas of memory, dubbed enclaves, that cannot be accessed by the operating system nor other processes. The idea is that you run cryptographic or anti-piracy digital rights management code within an enclave so that it cannot be spied upon by even the administrators of the machine.
In the case of CVE-2018-18098, the technology potentially allows an attacker to game SGX to gain admin clearance. The problem lies not within the processor's SGX hardware, though, but in the software layer above it. When enclave code is installed by a normal user on a Windows system, it is possible to hijack the installer, via a process injection attack, to gain admin rights on the box.
А втройне пиздецово что уже так засрали своим «secure» говном, которое по сути anti-secure. Настолько всё усложнили, что очень трудно понять даже описание найденной дырки. А найти в коде и подавно.
К слову, из Вики: «в процессорах Core 11 и 12 поколений поддержка технологии SGX удалена». Поняли, что обосрались. Но процессоры с этой дырой ещё долго будут в ходу.
А пропаганда как обычно представляет всё в другом свете:
«Теперь машины на базе этих чипов не смогут воспроизводить диски Blu-ray в разрешении 4K».
Пользователи скоро сами попросят вставить им Microsoft Pluton ректально.
> Теперь вредоносный код может получить аппаратную защиту от антивирусов...
Так точно.
Кстати не только у Штеуда есть анально огороженная параша для DRM.
У ARM с AMD тоже всё в порядке. В кернелы поновее и поддержку завезли (у меня в /dev пока такого говна нет)
https://www.kernel.org/doc/html/v5.9/staging/tee.html?highlight=platform%20security%2 0processor%20psp
A TEE (Trusted Execution Environment) is a trusted OS running in some secure environment, for example, TrustZone on ARM CPUs, or a separate secure co-processor etc. A TEE driver handles the details needed to communicate with the TEE.
The AMD-TEE driver handles the communication with AMD’s TEE environment. The TEE environment is provided by AMD Secure Processor.
The AMD Secure Processor (formerly called Platform Security Processor or PSP) is a dedicated processor that features ARM TrustZone technology, along with a software-based Trusted Execution Environment (TEE) designed to enable third-party Trusted Applications. This feature is currently enabled only for APUs.
Причём иронично что это копроцессор ARM. 32-bit Cortex-A5.
Every time i see a news item about these trusted systems i can't help asking myself a few things :
- Why it isn't named "Don't trust the owner/user of this device" environment because that reflects what those things do.
- Where can i buy new devices without that environment ?
Обыватели не понимают смысл термина "trusted"...
Он означает совсем не то, что код няшный и пушистый и ему можно доверять.
Он означает код, которому ты вынужден доверять от безысходности. Потому что если этот код скопроментирован -- остальные части системы уже ничего не с этим сделать не смогут.
Т.е. например ты вынужден доверять фирмвари, иначе ничего не загрузится.
Это маркетологический трюк расчитанный именно на то чтоб обыватель неправильно понял.
Потому назвали «trusted», а не «анальный тюбик».
На x86 не так. Там вшиты отдельные копроцессоры со своей закрытой осью.
У Штеуда по последней информации 32 битный Quark под управлением... Minix.
Starting with ME 11, it is based on the Intel Quark x86-based 32-bit CPU and runs the MINIX 3 operating system. The ME state is stored in a partition of the SPI flash, using the Embedded Flash File System (EFFS). Previous versions were based on an ARC core, with the Management Engine running the ThreadX RTOS.
У АМД Cortex-A5 с непонятной прошивкой. Причём без него остальная часть проца работать не будет
> The PSP is an integral part of the boot process, without it the x86 cores would never be activated.
https://en.wikipedia.org/wiki/AMD_Platform_Security_Processor
По веткам травинок карабкалась ловко,
Глядела, как в небе плывут облака…
И вдруг опустилась Большая Рука.
И мирно гулявшую Божью коровку
Засунула в спичечную коробку.
Коровка ужасно сердилась сначала,
Мычала и в стены коробки стучала…
Но тщетно! Забыли о ней в коробке,
Закрыли Коровку в шкафу, в пиджаке.
Ах, как тосковала в коробке бедняжка!
Ей снились лужайка, и клевер, и кашка…
Неужто в неволе остаться навек?!
Коровка решила готовить побег.
Три дня и три ночи рвалась она к цели.
И вот, наконец, вылезает из щели…
Но где же деревья, цветы, облака?
Коровка попала в карман пиджака.
Однако она, не теряя надежды,
Бежит на свободу из душной одежды:
Там солнце, и ветер, и запахи трав…
Но вместо свободы увидела шкаф!
Тоскливо и страшно Божьей коровке.
Опять она в тёмной пустынной коробке.
Вдруг видит: вверху, где вставляется ключ,
Сквозь щёлочку в шкаф пробивается луч!
Скорее на волю! Коровка отважно,
Зажмурясь, штурмует замочную скважину…
И вновь оказалась в глухом коробке
С огромною люстрой на потолке.
Однако Коровка на редкость упряма:
Нашла, где неплотно захлопнута рама…
И вот вылезает она из окна —
Ура! Наконец на свободе она!
И вновь на знакомой лужайке букашка.
Под нею, как прежде, колышется кашка,
Над нею плывут в вышине облака…
Но смотрит на мир осторожно Коровка:
А вдруг это тоже Большая коробка,
Где солнце и небо внутри коробка?!
Да ну? Я сварщица не настоящая, но разве недостаточно будет TPM, Secure Boot и гипервизора? Которые, внезапно, и требуются для win 11.
Ну да, ещё придётся вайтлистить вендоров прошивок, чтобы не забывали Boot Guard включить. Но я думаю это решаемо для майкрософт.
Вообще, забавно, что M$ повёлся на байки интела о "секьюрности" анклавов и вбухал в это кучу ресурсов. А на деле они оказались решетом.
И теперь они пилят всё сами.
32-битная использует FS, а 64-битная — GS (не знаю, зачем они сменили регистр) для указания на TIB — thread information block — структурку, хранящую внутренние переменные ОС, относящиеся к текущему треду.
Кстати, textsynth в одном примере, увидев [_tib], нагенерировал код для получения переменных TIB. Он даже это знает.
Ну так и GCC использует их для адреса thread localов.
> 32-битная использует FS, а 64-битная — GS
А не наоборот? В Линуксовом ABI наоборот.
i386 — GS
x64 — FS
В gcc кстати есть флаг чтобы это отключить.
Но тогда будет перепитух с thread base pointer.
А жаль. Классная же была идея: выделаешь кусочек памяти, и реально железо тебе его защищает.
Мечтай в одну руку, сри в другую.
Что мешало сделать реальный режим без нахлеста?
Гранулярность большая получится, что пиздец неудобно. Нахлёст был компромиссом между экономией памяти и достаточно лёгкой арифметикой указателей: если аллокатор минимизирует оффсет (а нахлёст даёт ему такую свободу), то в 99% случаев очень тяжёлую операцию по инкременту сегмента можно выкинуть и апдейтить только смещение.
- хитровыебанный аллокатор, который никогда не пересекает 64к границы и из-за этого проёбывает память
- push si; push ds; add si, bx; mov ax, ds; adc ax, 0; mov ds, ax; mov ax, [ds:si]; pop ds; pop si на каждом обращении к памяти.
но я говорил о проблеме A20, из за которой у нас мегабайт. Если бы у нас было 2^16 сегментов, то было бы у нас и 4 гига памяти, не?
С гранулёмой можно было бы бороться через huge segments (сравни huge pages), алеж тогда пришлось бы делать description tables (иначе как узнать размер сегмента?) и был бы уже не честный реальный режим
Ну а нахуй это все надо, если у тебя регистры 32-битные? Реалмод такой странный именно из-за 16-битности.
Собственно поэтому на arm'овских контроллерах нет такой ёбли. Там 32-битный flat, хоть памяти и меньше, чем у древних х86.
если зашиться на то, что размер сегмента всегда 4гига, то и похуй.
Конечно, макс размер массива 4 гига кому-то может показаться гомосячеством при наличии 256 гигов оперативки в сервере например, ну так жабаёбы же живут например
Это делается так:
1. Переключаешься в защищённый.
2. Ставишь лимит у всех селекторов по четыре гига.
3. Возвращаешься в реальный.
Теперь ты можешь адресовать четыре гига, используя 32-битные смещения (с помощью префикса ADRSIZE).
Нужно или все обработчики прерываний переписывать под себя, или ограничивать код первым мегабайтом.
Остаётся только включать CLI для кода, расположенного выше первого мегабайта. Но это ужас.
знаешь же как работало хардварное переключение конь текста?
Потому что он бессмысленный... Раз у тебя регистры 32-битные, твой конпелятор к этому готов и тебе явно плевать на совместимость, то что мешает просто остаться в защищённом?
Прерывания можно обратно в реалмод зафорвардить если сам не хочешь обрабатывать.
Ну хотя да, IDT чуть сложнее.
Другой вопрос, считать ли это контроллером.
Впрочем, надо проверять.
хатя...
The segment address inside the descriptor table entry has a length of 24 bits so every byte of the physical memory can be defined as bound of the segment. The limit value inside the descriptor table entry has a length of 16 bits so segment length can be between 1 byte and 2^16 byte. The calculated linear address equals the physical memory address.
говно какое. Как же всякие миниксы, OS/2 и прочие xenix Работали?
В Windows 3.x была такая же проблема.
Либо ограничиваешь массив 64 килобайтами, либо городишь костыли для переключения сегментов.
В 1979-м году Intel хотел как лучше: отдельный сегмент для кода, отдельный для данных, нельзя случайно "выполнить данные", всё логично, удобно, и правильно.
И уже через пять лет буквально начались анальные костыли ради массива более 64K
От начата DS: ты мог отступить максимум на 64 кило. А дальше нужно либо подкручивать базу селектора, либо создавать новый селектор с базой повыше.
Адресации scale-index-base, как на 386, где индекс можно умножать на scale, тогда ещё не было.
Линус изучал MMU, и решил сделать OS для PC со страницами (в 286 не было страниц, хотя и были защищенные сегменты), а миниксы работали и до этого
https://vetusware.com/download/Minix%20for%20286%202.0.4/?id=9903
https://www.chipdip.ru/product0/8008545452
Клон 8086 в корпусе DIP40.
Слабо под него плату развести?
В айфонах baseband processor на x86 -> https://lcq2.github.io/x86_iphone/
https://ru.wikipedia.org/wiki/Intel_Management_Engine
> Starting with ME 11, it is based on the Intel Quark x86-based 32-bit CPU and runs the MINIX 3 operating system.
Т.е. там отдельный 32-битный x86-совместимый процессор под это говно выделен
блядь) зачем? зачем?
IME это вроде та хрень, через котору Йоханна Рутковска (тян хакер существует не только в аниме!) поломала интел>?
а еще из за IME сервера вроде по десять минут грузятся
Есть ли у Йоханны Рутковски хуй? Есть. Есть хоть и со знанием средневекового этнографического языка. Она живет с дочерью и фантастическими партнерами на Соловках. Она смотрит свои лучи в массивных рашифровках викинго�йвоградского сонара, чтобы оправдать величавую книжку. В последние годы Йоханна напрямую убеждала мира руководить войсками души, делая их более смелыми.
Рецензенты разного рода могут быть на то ли бессовестными или неприличными. Одна любимая хитросплетение математической школы стилистики в нашей реальности в основном предлагается именно британским писателям, самим себе часто удобно предпочитаемые альтернативы отчасти утешительны, но многим это исполнение воздуха не нравится.
А потом то flat намного проще, чем реалмодные грабли. Да и работает обычно быстрее.
Но real mode у тебя из коробки, а для flat нужно чото там в CR* регистры загружать, *DT всякие.
Десять инструкций буквально... Ну и таблички, да.
В лонг вот сложнее из-за пейджинга.
Это по сложности почти как свой cygwin написать или ещё какую-нибудь прослойку.
Нужно реализовать:
1. Несколько функций INT 31h (не так много).
2. Переходники для прерываний DOS и BIOS.
И вот с реализацией переходников проблема, когда передаёшь данные не по значению, а по указателю. Нужно держать буфер в «реалмодной» памяти, чтобы DOS/BIOS его увидел.
Получишь... свой Линукс.
Как же оно petuzh.efi грузит?
Х.з., от настроения прошивки зависит. Флешки без GPT они вполне так грузят.
Но зачем в 2021 пердолиться с MBR?
Да не зачем, но я переодически вижу питузов, которые ставят на современный (вот почти уровня адлер лейк) комп винду без уефи. хуй знает зачем
2.1.2
не
нельзя
у интела так точно
https://www.japheth.de/HX.html
Тогда и х86 не чистый фон-нейман, если посмотреть на раздельный кеш данных и инструкций.
Походу это разделение уже устарело.
https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/caches-and-self-modifying-code
И физически все ядра сейчас работают по-гарвардски, просто иногда добавляют роутинг с шины кода до оперативки.
Или есть реальный пример выжившего фон-неймана?
Таким образом они не работают как установились. Но всё же постоянно выполняются.
А дальше за L1 кешами всё это смешивается в кучу и уже становится похоже на фон-неймана. Плюс интел ещё когерентность между этими кешами поддерживает, чтобы усилить иллюзию (ARM -- нет).
Хер знает, короче. Устарела вся эта классификация. Чуваки всё-таки про свои конкретные изобретения рассуждали, а не про то что через десятки лет наворотят.
в 86 у тебя два адресных пространства: ненунжное(IO) и обычное(MEM).
MEM на код и данные не разделяется, так что это как-бы гарвард.
Правда, у тебя есть инструкции для работы с кешем, а значит абстракция уже протекла.
>Устарела
Ну да, наверное это как с CISC/RISC, сейчас уже сложно сказать.
зы: dram controller нам том же die, что и ядро, так что физически снаружи проца никакой разницы между кодом и даннымитоже нет: дорожки тянутся к dram
не было бы глупых проблем типа "win32 не видит 4 гига памети"
Но возможно I/O инструкции чем-то плохи и тормозят, а поменять их уже нельзя. Как минимум там всё плохо с режимами адресации.
Самое смешное, что уже в 95 году х86 умел в PAE. Так что проблема тут далеко не в проце. Прыщи, к примеру, видели.
1. far-указатели были 48-битными (16 бит селектора + 32 бита смещения).
2. Линейные адреса были 36-битными (с учётом PAE).
Не просто ведь на будущее интел эту фичу пилил.
рендерили поди на SGI каких нить
А потом пришёл АМД и всё перевернул.
З.Ы. Блин, так то до сих пор продаются говноуты с 2 гигами.
Да нет, на серверах таки настало. Я вживую видел 2003-й с PAE.
Как бы намекает нам сайт HP.
Такой perfect...
Это тн "F6 driver". При установке XP жмешь F6, и суаваеш дискету.
Никогда не видел, чтоб AHCI нельзя было переключить в IDE
Ваще 32битная семерка станет на 2 гига, но работать на нем всё равно хуёво
Кошечка говорит: "MMIO"
Ядерному или прикладному? Прикладному то по-дефолту сейчас никто не даёт код патчить...
А адресное пространство вон у arm cortex m0 тоже общее (решили не экономить на спичках). Тем не менее, роутинга от шины кода до оперативки у него нет и указатели на данные в оперативке не пашут как указатели на код. Т.е. это почти труъ гарвард (был бы труъ, если бы флешка с кодом не читалась с шины данных).
а прикладник не может пометить страницу как W, насрать туда, и потом пометить X?
как же жыты работают? через трап-лины?
Какой фон-нейман )))
Если посмотреть на развитие их конпелятора, то они последние годы реально лечат именно то, через что их ломают.
Просто они пошли немного по другому пути -- убить RCE как класс, даже если код написан бухим долбоёбом и спроектирован по наивным канонам 80-х.
Просто долбоёб часто сам все портит при наличии specially crafted packet, как мы знаем, а хакер всё равно гаджет найдет.
Тут вся TCB, вся в система сгнила, всё менять надо.
При работающих CFG и CET ему не особо приятно будет это делать... По сути, прыгнуть можно только в начало функции. А вернуться только туда, откуда функцию вызвали.
Но CET слишком сложный, конечно. Боюсь, что там тоже какие-нибудь баги найдутся и интел его отправит на кладбище не взлетевших технологий.
А как же автоуничтежние локального фрейма при выходе из функици?
mov rbp, rsp
...
mov rsp, rbp
pop rbp
Придётся во втором стеке городить контроль за фрейм-поинтером.
Ну классическое:
Шта? Ты про ret с циферкой, который в паскалевском конвеншене юзался? Я другой "автоматики", завязанной на ret не припомню. Всю жизнь вручную вилкой чистили через mov bp, sp или add esp, 42.
То есть полюбасу придется подвинуть указатель на стек, либо как-то явно из него всё повыкидывать.
про FramePointer там ужо выше все написали, но он же опционален
Соглашусь, впрочем, что слово "автоматический" тут плохо подходит, потому что "ret" в случайном месте приведет к прыгу в локальную переменную
Если фреймпоинтера нет, стек сначала очищают вручную с помощью add esp, 42 и pop'ов сохранённых туда регистров. Если включен стек протектор, после этого проверяется канарейка. И только после этого происходит ret. Да, в этот момент под rsp уже как раз адрес возврата.
Если мы уберём адрес возврата на другой стек... то все остальные механики, описанные выше, ничего не заметят. Вообще ничего. Потому что при нормальной работе кода всё сбалансировано.
> "ret" в случайном месте
Ну откуда он там взялся? Какая-нибудь бага конпелятора, который забыл высрать эпилог функции?
Если мы унесем адрес возврата в другой стек, то я смогу сделать "ret" не сделав ни add esp, 42, ни pop.
Таким образом вызвавшая меня функция может получить стек с моими переменными
Это бага конпелятора имеется в виду? Или нарушение DEP? Мимопролетающая космическая частица, превратившая mov в ret? Или ты сам на асме такую хуйню написал?
Я не понимаю суть проблемы, честно.
не, ну можно конечно перенести это на вызывающую сторону: пусть запоминает SP, а после вызова возвращает на место, такую call convention можно принять
Сейчас нельзя случайно забыть вернуть SP на место, и спокойно ретнуться. А так станет можно.
Но может быть проблемы и нет, нужно попробовать, чтобы сказать. Сама идея хранить RET и переменные в разных местах, чтобы писанием в массив на стеке не засрать RET, наверное правильная идея
Если для адресов развратов сделать отдельный стек, то мы сможем не удалять локальные переменные и вернуть их вызывающему коду.
Привет, forth.
1. «Стековые» инструкции не обязаны использовать R13=SP, они могут использовать любой регистр.
2. BL не использует стек, она лишь сохраняет адрес разврата в R14=LR. Вызываемая подпрограмма должна его где-нибудь пересохранить перед вызовами других подпрограмм из себя.
2. Стек развратов
3. Стек потока управления (для компиляции управляющих слов, может быть совмещён со стеком данных)
4. Очередь поиска
5. Стек локалок
6. Область данных фактически тоже стек, ALLOT может двигать указатель в обе стороны.
Просто если нет, то ведь смысла от быстрой очистки стека посредлством MOV нет
В Сишке все-все-все структуры trivially_destructible. Именно поэтому я за «Си».
никогда не забываю close, fclose, petuh_destoroy и free в правильном порядке
Разве что ручной выбор между near и far указателями привернули.
А в остальном сишный стандарт оставляет достаточно UB'ов и свободы, имхо.
Не имеет значения, какими танкерами захватывает это дочернее сооружение которые могут носить на большой скорости огромную толщину составляющей, или их масса не превышает сотни тонн и миллионы килограммов но это дочернее сооружение на скорости между стаи составляющей. Но для таких стаи на них приходится заранее установить прием, при расчете по опыту потери энергии подлежат заметным повышениям, из-за чего это вообще возможно?
Я относительно недавно для себя открыл, и оно окончательно заменило мне визио. Что приятно, оно нативно умеет в svg.