Лекция 6 - Домашно - Задача 2
Първоначално задачата не ми направи впечатление, тъй като решението изглеждаше сравнително лесно, но после ударих на камък. За да сметна някакъв триъгълник ми трябват операции с плаваща точка, от рода на корени, тригонометрия и т.н. Ядрото (очаквано) не харесва особено операциите с плаваща точка по ред причини, които не са важни в случая, затова и няма кой знае какви библиотеки за тях, поне аз не можах да намеря, а по форумите като цяло се карат на всеки, който пита за fp аритметика и се чудят за какво му е. Тук се сетих за два варианта да заобиколя въпросния проблем:
Самата floating point аритметика може да бъде пусната за x86 архитектури по следния начин:
#include <asm/i387.h>
int some_function(void){
kernel_fpu_begin();
// Do some calculations or whatever...
kernel_fpu_end();
return 0;
}
Програмата ще използва копроцесора за аритметика с плаваща запетая и ще направи каквото трябва. Между другото, имаше и някакъв друг хедър, който емулираше тази аритметика софтуерно, така че и той остава вариант, както и да е. Това означава, обаче, да си пиша сам функцията за корен квадратен, което не е чак такъв проблем. Тригонометрията вероятно ще е голям зор, ако въобще е възможно да се напише без inline assembly в нея. Отново, леко задънена улица, или поне нещо, което предпочитам да избегна.
Вторият вариант е да използвам inline assembly и по подобен начин на горния да си направя сметките с x87 инструкциите, където има и корен квадратен, и тригонометрия. Назад съм с асемблера, но, като цяло, приемлив вариант. Тук, обаче, също удрям на камък, защото не мога да намеря функция, която ще изпринти floating point стойност в proc файл. seq_printf() отказва упорито.
С това се изчерпва моят опит до момента, споделете и вашия, ако искате, разбира се.
Мога да добавя малко лош опит. Продължих да се лигавя с floating point аритметика, въпреки добрата си преценка. Нещата работят, но само донякъде. Освен, че асемблерските инструкции ограничават до използването на определена архитектура, но и както е споменато горе, floating point аритметиката може да доведе до undefined behavior. Описал съм всичко в коментарите на постнатия код, но като цяло наистина се случват някои странни работи. Примерно, когато извикам функцията sqroot върху някой литерал и всичко е наред. Викна ли я обаче върху някакъв друг тип, дори и кастнат към float, всичко приключва и компилаторът хвърля warning за undefined behavior и модулът не се зарежда, или прави segmentation fault-ове и други подобни глупости. За това намерих workaround, като написах функция за преобразуване на int в някаква форма на float. Когато викна sqroot върху някакъв сбор от променливи, се случва нещо подобно и т.н. Като цяло не си заслужава мъките и писането на откровени простотии, затова отивам да си смятам векторите. Поствам кода кат предупреждение за ентусиасти като мен.
Благодаря за кода и информацията. За сведение - в MM Solutions само на няколко човека е разрешено да пишат на асемблер за нуждите на клиентите.
Асемблерът е нещо много хубаво, но поставя някои ограничения. Като, цяло, ако си напред с математиката можеш да пишеш много оптимален код, което е в пъти по-добре от C компилатор с набичена на макс оптимизация в който и да е случай. Уловката идва тогава, когато проектът е голям и трябва да пише повече от един човек и се стигне до разпъване и рисуване по чаршафи, спане на работа и т.н. Не е за общи цели.
А дали няма да е лошо да се направи един курс и за Асемблер?
Какво мислите за идеята?
По принцип цялата идея на операционните системи е да ти отделят хардуера от имплементацията, т.е. един и същи код да работи на различен хардуер. Асемблера, като цяло, е стъпка в обратната посока, т.е. е задраво хардуерно зависим в доста случаи и ограничава нещата. Може да се използва без проблем за устройства без операционна система, примерно на мен ми се е налагало да го ползвам като съм писал за PIC микроконтролери, въпреки че ползвам е силно казано в случая за нивото ми на разбиране. Курс за x86 асемблер, или пък за ARM асемблер би представлявал интерес за мен, въпреки че там се отдалечаваме възможно най-много от софт частта на софтуера. :D
Съгласен!
Но не е ли странно как тези "високотехнологични" n-ядрени процесори, обременени с "революционни" операционни системи и "висококачествен" код се "влачат" така!
А процесорчета на 30 МHz управляват производствени линии!
Но, все пак, масовите съвременни технологии са най-вече за забавление, така - всичко е разбираемо :)
Лека и успех!
За начало - писането на многонишков код никак не е лесно. Още по-трудно е паралелизирането на алгоритмите - дори в някои случаи това е невъзможно. След това алгоритмите трябва да бъдат написано бързо, за да бъдат пуснати на пазара - дори и с цената на някои бъгове. Оптимизацията отнема време, а и не може да стане за всички системи едновременно.
От друга страна не е зле да се знае, че C се нарича още и преносим асемблер. Модерните компилатори в повечето случаи генерират достатъчно оптимален код, така че знанието на асемблер не е наложително. Но е поучително да се разгледа генерираният код :)
Абсолютно е така!!!
Навремето една и съща програма даваше дори различни резултати под различните компилатори (не че сега не се случват такива неща понякога)