Ну, тогда классно. А то там выше один крендель какие-то тулчейны кастомные пересобирал на ночных сборках раста (не уточнил, правда, сколько тот хелловорлд в итоге компилился по времени), чтобы один файлик скомпилить.
Да: дело в том, что в каждом языке есть набор предкомпилированных библиотек под целевую архитектуру или платформу. Согласен, совсем неясно, как так получилось, что под чрезвычайно популярный 16-битный bare metal из восьмидесятых не оказалось std из коробки. Но мы исправили это упущение, пересобрав стандартную либу под нас. И заметь, мы один раз настроили проект, привязав его к нужной архитектуре, и затем каждый может собрать его одним cargo build: сначала скачается и соберётся сам тулчейн, затем соберётся проект. В одну команду! То есть, сборка любого проекта, независимо от зависимостей и целевых архитектур, независимо от хостовой операционки выглядит примерно так: Код (Text): git clone https://github.com/user/project cd ./project cargo build И более того, мы можем привязаться не просто к каналу stable/beta/nightly, но и к конкретному билду компилятора, чтобы была гарантированная воспроизводимость сборок. Это актуально для nightly, поскольку в нём могут быть ломающие изменения. Насчёт nightly в целом - согласен, писать на нём в продакшн не очень хорошо. Но мы и не пишем в продакшн 16-битные змейки, будем честны) Уточняю: около семи секунд на сборку всего тулчейна на i9-9900k. А все последующие сборки мгновенные. На то они и спецы, их слово закон, фундамент) Но мы уходим от темы: rmn, сказал "А" говори и "Бэ" - жду ссылочки на первоисточники.
В айти мире, как в аптеке, всё имеет суть и вес. Языку, как человеку, имя нужно позарез. Имя вы не зря даёте, я скажу вам наперёд, Как язык вы назовёте, так он обществу зайдёт. Как язык вы назовёте, так он обществу зайдёт. Назовите си плюс-плюсом и скомандуйте вперёд, И язык полюбят люди, опенсорц и Microsoft. А вот «ржавым» назовёте, не уйдёте от беды, Его хейтить будут люди из-за каждой ерунды. Его хейтить будут люди из-за каждой ерунды.
Итак, мы попробовали x32, попробовали x16. В нашем триптихе безумия не хватает x64. Сегодня мы не будем жестить: мы напишем маленькое приложение для UEFI. Итак, UEFI - это фреймворк для разработки приложений и сервисов, которые запускаются до передачи управления загрузчику и, в зависимости от типа приложения, могут работать во время работы операционной системы. UEFI представляет собой стандартизированный интерфейс для работы с файловой системой, сетью, графикой и много чем ещё. В этом он похож на виндовый COM. Спецификацию UEFI можно найти на официальном сайте. Эталонной реализацией является EDKII, он же Tianocore - именно на нём производители железа основывают свои прошивки. Альтернативной реализацией является Project Mu от Microsoft, который, впрочем, тоже основан на EDKII. UEFI предоставляет приложению набор интерфейсов - протоколов. У каждого протокола своя область ответственности: например, отдельный протокол для обработки ввода, отдельный протокол для работы с GPU и т.д. Наборы протоколов объединены по смыслу в отдельные "пакеты" (папки с суффиксом Pkg в корне EDKII). Производитель по желанию реализует дополнительный функционал в отдельных пакетах, но один пакет должен быть всегда - это пакет MDE (Module Development Environment). Все дополнительные модули основываются на MDE, а тот, в свою очередь, реализует базовый функционал: аллокаторы, поддержку многопроцессорности и файловых систем, ввод и подобное. Готовое приложение представляет собой обыкновенный майкрософтовский PE-файл с расширением .efi. Чтобы запустить приложение, достаточно отформатировать флешку в FAT32, положить приложение в /efi/boot/bootx64.efi, затем отключить в BIOS'e SecureBoot (если он включен) и загрузиться с флешки. Для Rust существует несколько биндингов UEFI: uefi-rs, r-efi или efi. Мы будем использовать uefi-rs как самый удобный и распространённый. А что же мы будем писать? А писать мы будем то, о чём вы всегда мечтали, но стеснялись попросить: мы нарисуем портрет Остина Пауэрса! Итак, cargo new austin, let's go! Первым делом подключаем нужные либы: uefi и какой-нибудь декодер jpeg, работающий в no_std - мой выбор пал на zune-jpeg. А для логов возьмём log. Код (Text): [package] name = "austin" version = "0.1.0" edition = "2021" [profile.dev] panic = "abort" [profile.release] panic = "abort" lto = true [dependencies] log = "0.4" uefi = { version = "0.26", features = ["alloc"] } uefi-services = "0.23" zune-jpeg = { version = "0.4", default-features = false } UEFI передаёт в точку входа указатель на таблицу BootServices, в которой есть функции для запроса протоколов и для получения информации об окружении - например, для доступа к файловой системе, с которой мы загрузились. За работу с файловой системой отвечает протокол SimpleFileSystem, за графику - GraphicsOutputProtocol (или GOP, как общепринятое сокращение). А дальше дело за малым: прочитать с диска картинку, раздекодить её в массив BGRA (именно в таком виде фреймбуффер хранит пиксели, игнорируя байт альфа-канала), вписать её в размеры экрана и записать итоговую картинку во фреймбуффер. Код (Rust): #![no_std] #![no_main] #![warn(clippy::pedantic)] extern crate alloc; use alloc::vec::Vec; use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput}; use uefi::{prelude::*, CStr16}; use uefi::proto::media::file::{Directory, File, FileAttribute, FileMode, FileType, RegularFile}; use zune_jpeg::zune_core::colorspace::ColorSpace; use zune_jpeg::zune_core::options::DecoderOptions; use zune_jpeg::JpegDecoder; fn read_file(dir: &mut Directory, path: &CStr16) -> uefi::Result<Vec<u8>> { // Open the file: let fs_entry = dir.open(path, FileMode::Read, FileAttribute::READ_ONLY)?; let FileType::Regular(mut file) = fs_entry.into_type()? else { // Not a file: return uefi::Result::Err(uefi::Error::new(Status::INVALID_PARAMETER, ())); }; // Query the file size: file.set_position(RegularFile::END_OF_FILE)?; let file_size = file.get_position()?; file.set_position(0)?; // Read the whole file: let mut content = alloc::vec![0_u8; file_size as usize]; let read_bytes = file.read(&mut content)?; content.resize(read_bytes, 0_u8); Ok(content) } fn downscale( image: &[BltPixel], original_size: (usize, usize), downscaling_coeff: usize) -> (Vec<BltPixel>, (usize, usize)) { let downscaled_size = ( original_size.0 / downscaling_coeff, // Width original_size.1 / downscaling_coeff // Height ); let mut resized = alloc::vec![]; for scanline in image.chunks(original_size.0).into_iter().step_by(downscaling_coeff) { for chunk in scanline.chunks(downscaling_coeff) { if chunk.len() != downscaling_coeff { break; // The last chunk which will be dropped } let accum = chunk.into_iter().fold( (0_usize, 0_usize, 0_usize), |accum, entry| ( accum.0 + (entry.red as usize), accum.1 + (entry.green as usize), accum.0 + (entry.blue as usize) ) ); // Push the averaged color: resized.push(BltPixel::new( (accum.0 / downscaling_coeff) as u8, (accum.1 / downscaling_coeff) as u8, (accum.2 / downscaling_coeff) as u8 )); } } (resized, downscaled_size) } fn as_image(raw: &[u8]) -> &[BltPixel] { unsafe { core::slice::from_raw_parts(raw.as_ptr().cast(), raw.len()) } } #[entry] fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status { // Initialize UEFI services: uefi_services::init(&mut system_table).expect("Unable to init the `uefi_sevices`"); let bs = system_table.boot_services(); // Read the image: let mut fs = bs.get_image_file_system(image_handle).expect("Unable to get the image file system"); let mut volume = fs.open_volume().expect("Unable to open volume"); let content = read_file(&mut volume, cstr16!("austin.jpg")).expect("Unable to read the file"); // Decode the image: let decoder_options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::BGRA); let mut decoder = JpegDecoder::new_with_options(&content, decoder_options); let image = decoder.decode().expect("Unable to decode the JPEG file"); let (img_width, img_height) = decoder.dimensions().expect("Unable to get the dimensions"); log::info!("Image: {img_width}x{img_height}"); // Query graphics services: let gop_handle = bs.get_handle_for_protocol::<GraphicsOutput>().expect("Unable to query the GOP handle"); let mut gop = bs.open_protocol_exclusive::<GraphicsOutput>(gop_handle).expect("Unable to open the GOP protocol"); let (screen_width, screen_height) = gop.current_mode_info().resolution(); // Resize the image to fit the screen: let ratios = (img_width / screen_width, img_height / screen_height); let max_ratio = usize::max(ratios.0, ratios.1) + 1; let mut resized_image = None; if max_ratio > 1 { resized_image = Some(downscale(as_image(&image), (img_width, img_height), max_ratio)); } // Get an actual image and its size: let (actual_image, (actual_width, actual_height)) = if let Some((ref resized, (width, height))) = resized_image { (resized.as_slice(), (width, height)) } else { (as_image(&image), (img_width, img_height)) }; // Fill the background: const BACKGROUND: BltPixel = BltPixel::new(237, 86, 223); gop.blt(BltOp::VideoFill { color: BACKGROUND, dest: (0, 0), dims: (screen_width, screen_height) }).expect("Unable to fill the screen"); // Blit the image: gop.blt(BltOp::BufferToVideo { buffer: actual_image, src: BltRegion::Full, dest: (screen_width / 2 - actual_width / 2, screen_height / 2 - actual_height / 2), dims: (actual_width, actual_height) }).expect("Unable to BitBlt"); loop { bs.stall(1000 * 1000); } } В Rust есть готовый тулчейн для сборки под UEFI, поэтому нам не надо собирать кастомный и мы можем остаться на stable-ветке. Добавим его: Код (Text): rustup target add x86_64-unknown-uefi Собираем: Код (Text): cargo build --target x86_64-unknown-uefi --release Запустить можно или на настоящем железе, отформатировав флешку в FAT32 и положив получившийся austin.efi в /efi/boot/bootx64.efi, или в QEMU. Мы пойдём вторым путём. Для запуска понадобится OVMF с реализацией EDKII. Скачать OVMF можно здесь. Затем понадобится виртуальный диск, который мы отформатируем в FAT32. Сделаем VHD: Пуск -> Параметры -> Система -> Память -> Дополнительные параметры хранилища -> Диски и тома -> Создать VHD В качестве таблицы разделов выбираем GPT, файловую систему ставим FAT. Букву диска любую - например, X. Теперь кладём наше приложение из /target/x86_64-unknown-uefi/release/austin.efi в /efi/boot/bootx64.efi: Затем берём ваш любимый jpeg с Остином Пауэрсом и кладём его в корень нашего диска - в X:\austin.jpg И делаем батник для запуска Qemu: Код (Text): @start "" "T:\Program Files\Qemu\qemu-system-x86_64w.exe"^ -smp 8^ -display gtk,show-tabs=on,show-menubar=on^ -drive if=pflash,format=raw,readonly=on,file=code.fd^ -drive if=pflash,format=raw,readonly=on,file=vars.fd^ -drive format=raw,file=fat:rw:X:\ code.fd и vars.fd - путь до OVMF, который мы скачали ранее (берём из папки x64). Запускаем батник - и мы счастливы! — Do I make you horny?
угу, пишешь сишный код ржакой, то бишь повторяешь достижение Кая --- Сообщение объединено, 29 янв 2024 --- на сишке писать легче всего, пч сишный бинарь ПОЧТИ ИДЕАЛЬНО интегрируется с отладочными схемами - вот попробуй ржачные бинари ладить.. да, даже на питохе сложней писать, чем на сихи, пч по мере выгребания багов код становится тупо тормознутым/ единственно жаба смогла обойти сиху, пч дико портабельна и её тормозуху на облаках можно компенсировать дешёвым железом
https://wasm.in/threads/godnota-na-rzhaku.34990/page-2#post-441013 вообще, никому не нужны новые яп-ы, пч все они лишь увеличивают фрагментацию кодов и проблемы с совместимостью.. вот на кой чёрт стандартные либы сишки переписывать на новые яп-ы.. в чём профит????????
Наверно они просто не знали, что существует си, а так бы конечно выбрали его. А их не переписывают, их выбрасывают. Кстати, насчёт libc. Как там дела с файлами? Выделяющий память fopen - это ведь чтобы было blazing fast? А fseek + tellg, чтобы узнать размер файла - это в алфавите буква У - удобно. Such amazing лангуаге.
асм/си + пай + жаба == остальное СОМНИИИТЕЛЬНО угу, через несколько десятков летов и со скрипом не совсем просекаю суть Твоего недовольства
UbIvItS, ну, не знаю, может они не знают о существовании кнопок Find Selected и Find Next?? Вот: Двойной щелчёк по указателю или хендлу, требующим особого внимания, затем при помощи Find Selected(Find Next) проверяем корректное наличие/отсутствие всех free, delete, close и пр. Хотя, кажется Rel говорил, что бывает так, что кодер не понимает свой код... Ну тада наверно и правда, остаётся только Rust.
свой код каждый кодер действительно перестаёт понимать по ходу просадки зрения / памяти и способности к долгой концентрации внимания.. но это другая тема. ржака - это чудовищно неудобная штука: корявый компиль с кривыми крейтами + отказ от однопоточного кода и глобальных переменных заставляет писать через Ж.. О.. П.. У..
Смотри какая прикольная штука: https://aliexpress.ru/item/10050061...33.1396186513.1706488619-256390260.1690940710 https://www.hlktech.net/index.php?id=1165 Там есть даташиты на проц и SDK. пс. ну если совсем честно, заказал после поверхностного изучения, буду вникать когда придёт
сложность зависит не столько от яп-а, а от задачи, кою Ты решаешь. питоха же штука очень тормознутая, тч каждый новый чекер в цикле становится новой болью
Марсолёт Ingenuity отлетал своё, но тут вскрывается весьма интересное. Этот марсо–коптер был дополнительной нагрузкой к основной миссии, пробным шаром, и оказывается создатели пошли по пути урезания осетра инопланетных технологий перед дилеммой как вместить в четырёхкилограммовую тушку и батарей и двигателей и камер и средств связи и процессора. Так вот они установили в него не дорогой космический радиационно–проверенный чип за сотни тысяч долларов (например чип RAD750 схемотехнически из 90–х на марсоходе Perseverance стоит четверть миллиона долларов), а банальный Qualcomm Snapdragon 801 из недорогих мобилок. Так вот этот крохотный процессор в сто раз вычислительно мощнее, чем всё, что Jet Propulsion Laboratory отправляла дальше орбиты Земли _вместе взятое_. От всех марсоходов и зондов к другим мирам до пресловутого Джеймса Уэбба. Всё вместе взятое в сто раз меньше биткойнов способно зарабатывать, если бы задались таким упражнением. Подозреваю, конечно, что в какую–нибудь свинцовую коробочку электронику всё–таки положили, но это изумительный факт. Источник (англ.): https://arstechnica.com/space/2024/01/now–that–weve–flown–on–mars–what–comes–next–in–aerial–planetary–exploration/
aa_dav, Ну эти вертолётики весьма требовательны по мощности киберпилота. Старые но крепкие по радиации не хватало вычислительной мощности, либо через чур дорого, вот они воткнули что было, и отработал же. Хотя конечно корпусировать чип надо в вольфрам, от альфа и беты полностью, а гамма уже не так. Остаётся только написать надёжное ПО, типа если 2+2 не четыре, то это исключение как-то надо обработать. И конечно никакого питухона.
aa_dav, есть мнение, что вся ся радость никуда не летала == уж очень забавно, что наиболее бурный прогресс наблюдается в абстрактных темах
один поток забрал и тихо упал. другой тупо ждёт адЪЪЪ инфинитум. ===================== по-хорошему мьютекс всегда надо делать с таймаутом