Takže, začal jsem dělat svůj list odznovu. Uvidíme jak si povede. Při dalším kouknutí do zdrojáků std::list jsem si všiml že funkce insert() používá místo push_back() funkci emplace_back() (V případě C++11). Výhoda je, že se objekt v tomto případě nekopíruje (jako při použití push_back), ale rovnou vytvoří na místě. To musí být znatelné zrychlení (ačkoli, máme move konstruktory takže to zrychlení taky nemusí být moc velké). Toto by mohlo být vysvětlení proč je v mém listu funkce insert tak pomalá oproti std::list::insert(). ALE, tato výhoda by se neprojevila, pokud by jsme do kontejneru vložili nějaký primitivní datový typ (v mém případě long). Takže, furt nevím čím to je.
Příspěvky odeslané z IP adresy 80.188.252.–
Vnitřně to může používat pro alokaci uzlů jinou metodu využívající poslaný alokátor (mPooly, zóny). Ty to přečteš? Super, si šikovnej..., některé lidi ale z toho kódu akorát začne bolet hlava. No, když už si tady, můžeš mi pomoci objasnit tu rychlost?
Obě dvě implementace (std i moje) používají i pointer na konec chainu, takže operace push back je O(1). A teď ta největší sranda, std::list používá obyčejný implicitní std alocator který opravdu není memory pool, žádný jiný alokátor sem tam nenašel (jeden co tak vypadal byl typedef na standardní alokátor...ehm). Takže oni tam dokonce volají 2x alokátor kdežto já jen jednou. A přesto je to hrozivě pomalí. A ty konstruktory? No, testuji to s datovým typem long, takže konstruktory možná budou drhnout, naštěstí ale ne teď. Teda, je to záhada. Zejtra si s tím zase pohraju (jak vyjde čas) a pak sem šoupnu zdroják. Kouknul by ses pak na něj prosím?
Inu, je to tak. Zatím to dám k ledu. Ale, víš. Dráždí mne to. Třeba teď sem testoval push back operaci, a, byla v mém podání rychlejší než je v std::list. A to je fakt divné, protože funkce insert která vkládá do prázdného listu funguje jako push back operace, akorát mnohokrát opakovaná. Asi je ten nečitelnej STL kód výsledkem magie či co ... ničím jiným to nevysvětlím.
Píšu kernel. To proto nemůžu použít STD list. Inu, máš pravdu, díky cache je vektor určitě rychlejší, jednotlivé uzly listu jsou rozházené všude možně takže je tam plno cache miss, kdežto dynamické pole je pěkně kompaktní. Mne však teď vadí právě to, že nejsem schopen přijít na to, jak to dostat (můj list) na úroveň std::listu bez memory poolů. Nebo je taky možné že používá std::list zóny, naalokuje paměť pro nody najednou a taky ji najednou uvolní (ušetřil by spoustu systémových volání). Při čtení zdrojáků sem narazil na to že uzly mají vlastní alokátor, bohužel se mi nepodařilo najít kde je implementovaný. Proto se ptám, potřeboval bych nasměrovat na řešení. V samotném algoritmu přidání uzlů by neměl (jak jsem uvedl v otázce) být ňáký rychlostní exces ne?
Nazdar, z určitých důvodů nemůžu v jedné aplikaci použít std::list, takže jsem se vrhnul na vytvoření vlastního listu. Problém nastal při testování rychlosti mého výtvoru s std::list. Zezačátku to bylo fajn, několik operací můj list zvládal rychleji než std::list. Pak ale přišel zlom při testování insert() funkce. Konkrétně případu insert funkce kdy se přidávají prvky do prázdného listu. Moje implementace je zhruba o 30% pomalejší. Operace mého listu jsou zhruba takové:
nainstaluj první uzel;
for (opakuj dokud jsou prvky ke vložení)
{
alokuj uzel;
vlož do něj hodnotu prvku [i];
připoj uzel na konec;
}
Operace alokuj uzel sestává z jednoho volání malloc a následného zavolání odpovídajícího konstruktoru nad objektem (new (pointer) T [size]). Toť vše. Zjistil jsem, že právě tato alokace mi tam žere všechen ten čas. Když jsem ji odmazal, a na místo ostatních závislých operací (na ní) přidal nezávislé se stejnou časovou spotřebou, rychlost byla stejná jako u std::list (smutné ...). Takže k jádru mé otázky, zná tady někdo vnitřní realizaci STL listu pro GCC 4.8? Pokoušel sem se číst zdrojáky, ale autor byl zřejmě pán strachu a děsu, takže to má psychika nedokáže vydržet (rozuměj, psalo to prase, aspoň tak se to jeví mému oku). Můj odhad je, že std::list používá memory pool pro uzly. Z toho, co sem si všim tak alokuje uzly a vkládané objekty odděleně. To by mohlo vysvětlovat tu rychlost, ale radši se zeptám.
Opomněl jsem dodat, že místo výkonu praxe by mělo být v Praze.
Dobrý den,
studuji na SPŠE v Úžlabině a tento rok máme povinnou 14 denní praxi (od 19.5.2014 do 30.5.2014) ve které bych rád využil své programovací dovednosti. Ovládám C/C++ (STL+základy QT), Assembly (x86-64 -> MMX,SSE,SSE2,SSE3,SSE4,AVX), HTML, CSS, Javascript (jQuery). Znám GNU toolchain (GCC+AS+LD), QT Creator, code::block, Visual Studio. Linux ovládám na uživatelské úrovni. Anglický jazyk ovládám na úrovni čtení technické dokumentace. V případě zájmu mne prosím kontaktujte zde v komentářích a nebo přímo honza.tomsu[at]seznam.cz. Za případné nabídky předem děkuji.
Používám gcc jež ma implementovane c++11. Verzi ti nepovím, píšu z mobilu. Jo a k tomu nakopnutí do prdele...nevím jakou jinou reakci bys čekal. Asi tě to urazilo, ale mne zas nakrklo že někdo svým přístupem bagatelizuje problém. Bejt to blbé lezení za pole. Nic neřeknu. To skutečně není problém zanalizovat bez pokusu o kompilaci. Todle je ale trochu něco jiného. Jo a vytrvale mi to hází errory, zřejmě způsobené neaktualitou GCC...abych řekl pravdu, je rychlejší si napsat vlastní kontejner než se srat s alokatorama.
Zasláno z mobilního telefonu.
Spoooustu errorů. Není to jen jeden error. Nechci bejt drzej, ale tys to nezkusil spustit? Vono todle není tak lehký aby stačilo radit od stolu no. STL je vnitřně fakt divočina, na první pohled je to prostě správně, a je fuk jestli tam dám bool a nebo string. Ono je to ale prostě blbě ať tam dám cokoli. Zajímavé ale je, že když udělám vektor s vlastním alokátorem který ukládá vektory s implicitním alokátorem, vše je OK. Jakmile se ale pokusím přidat svůj alokátor i vnořeným vektorům, je zle. To je na tom zajímevé. A taky když vytovřím obyčejnej vektor s vlastním alokátorem a použiju na něj konstruktor keterej bere jen objekt alokátoru, nemůžu použít metodu push_back(), prej neexistuje. KDyž však použiju konstruktor vector<>(lenght,Value,Allocator), vše funguje jak má. Todle je prostě hackování STL ...
Tak mám tady zase problém, tentokrát ultra.
Při řešení jednoho projektu potřebuji zjistit výpisy alokace a uvolňování paměti kontejnerama vector. Knihovna STL samozřejmě definuje alokátor který můžeme přepsat a podstrčit ho kontejnerům. Až po taď je vše v pohodě. Vektoru sem podstrčil vlastní alokátor a krásně šlapal ALE. Já ve skutečnosti mám vektory v kterých sou další vektory, a u všech potřebuji mít vlastní alokátor. INU vrhl sem se nato a vznikla skutečně nechutná šablonová SR**KA. Bohužel, furt to na mne křičí errory, které sou však mírně nepochopitelné, jako ostatně celá vnitřní implementace STL....
#include <vector>
#include <iostream>
using namespace std;
template <typename T>
class debugAllocator: public std::allocator<T>
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template<typename _Tp1>
struct rebind
{
typedef debugAllocator<_Tp1> other;
};
pointer allocate(size_type n, const void *hint=0)
{
cout << "Alokuji \t" << sizeof(n) * n << " bajtu na adrese ";
auto temp = std::allocator<T>::allocate(n, hint);
cout << hex << long(temp) << dec << "[" << long(temp) << "]" << endl;
return temp;
}
void deallocate(pointer p, size_type n)
{
cout << "Uvolnuji \t" << sizeof(n)*n << " bajtu na adrese " << hex << long(p) << dec << "[" << long(p) << "]" << endl;
return std::allocator<T>::deallocate(p, n);
}
debugAllocator() throw(): std::allocator<T>()
{}
debugAllocator(const debugAllocator &a) throw(): std::allocator<T>(a) { }
~debugAllocator() throw() { }
};
int main()
{
vector<vector<bool,debugAllocator<bool>>,debugAllocator<vector<bool,debugAllocator<bool>>>>
vect(0,vector<bool,debugAllocator<bool>>(),debugAllocator<vector<bool,debugAllocator<bool>>>());
return 0;
}
Ano, vytvoří rovnici lineárně závislou, ale ... sakra jak to říci, to je prostě ten problém. Prostě to nejde ! Tak si zkus ručně ňákej obvod propočítat a uvidíš (pokud tam teda najdeš chybu ...).
EDIT: A možnost, že budu hledat všechny možný kombinace smyček v obvodu nepřichází v úvahu (u velkejch obvodů bych to něchtěl vidět ...) ... to má do elegantního řešení daleko .... sem se proto ptal jestli někoho nenapadne jak od sebe odlišit smyčky závislé a nezávislé...
cycle detection mi není k ničemu, opravdu vím jak najít v obvodu (převedeném na graf) smyčku. Ale já chci smyčky nezávislé a né ZÁVISLÉ. Toto je právě ten problém který řeším ... proto jsem přidal link s návodem na smyčkové proudy protože nestačí pouze ovládat programování k vyřešení tohoto problému ale ještě metodu smyčkových proudů ...
Čelím vskutku komplexnímu problému. Píšu modul do programu, který provádí analýzu el. obvodu pomocí smyčkových proudů (pokud neznáte tak -> http://user.unob.cz/…L/Tema04.htm). Můj problém je najití NEZÁVISLÝCH smyček (závislí mi to hledá furt ...). Už sem vyzkoušel vše co mne napadlo a nyní opravdu netuším. Pro najití smyček používám hledání nejkratší cesty v grafu (můj nejnovější nápad zahrnoval i analýzu uzlů (v obvodu) a podle toho se upravovali délky hran mezi součástkami...ale...hledá to nezávislé smyčky jen někdy -> pokud tomu sedne topologie obvodu). Kdybych měl více času, asi bych se pokusil řešit problém nějak jinak (třeba evolučním algoritmem...a i ten by asi nepomohl). Já ho však nemám, a proto se ptám jestli někoho nenapadá nějaké elegantní řešení problému ...
No, výš vzorce ? Pak není problém (S=a*b,V=a*b*c atp.), toto je skutečně triviální problém takže nebudu psát příklad.
No hele, udělej to jednoduše, prostě ulož do binárního souboru celej objekt. Získej adresu objektu, tu si přetypuj na adresu charu, a pak prostě do souboru nasyp celej objekt jako kdyby to bylo pole charů (ono to skutečně je...). Zpátky objekt vytáhneš opačným postupem.
K čemu knihu proboha ? Osobně, na multithreading jsem knihu opravdu nepotřeboval. Když budeš sdílenou paměť lockovat mutexama, nic vážnýho ti už nehrozí. C++ std knihovna má implementován multiplatformní API pro multithreading, pokud používáš QT, má ho taky (podle mne hezčí).
ach jej, a co takhle převodní funkce v knihovně ? jak je to v std netuším ale v QT je
QString QString::number(num,base)
a
objektQString.toInt(base) ... to double atp. !POZOR! u desetinných čísel vždy musí být číslo v 10 soustavě ...
od sdílené paměti sou tady mutexy, kterejma si ji lockuješ. Rada, nepiš OS když neznáš pořádně funkci procesoru. Nastuduj oficiální dokumentaci k použité architektuře (asi x86 -> Intel má moc hezkou dokumentaci), a až pak něco tvoř, pokud bys tak udělal, bylo by ti to jasné.
Opravdu je ti jedno když přerušíš věc na více instrukcí, MÁŠ uloženej kontext procesu, takže můžeš kdykoli navázat znovu.
Pokud robíš na MP systému a máš aktivováno více jader, nastuduj taky paměťové bariéry (lfence,sfence,mfence) krom atomickejch instrukcí (prefix lock).
místo časovače jde použít třeba určitý počet syscallů, a nebo jeden specifický (něco jako yeld).
ewww, trošku děsivý, já fakt hledám něco naprosto minimalistickýho -> GraphViz je kanón na vrabce . Já primárně potřebuju to najití nejkratší cesty. Prostě něco jako BGL akorát s pěknou dokumentací, minimem blbostí kolem a hezkým kódem (to znamená žádné zběsilé používání typedef jako u BGL kde je to nutnost). Prostě něco jako QT akorát pro grafy.
Achjo ... scheduler skočením na požadovanou adresu (místa v úloze kde byla utnuta) sám skončí, za dejme tomu 25 ms vyvolá APIC interrupt (náš scheduler) a vše se opakuje znova.
Uprostřed instrukce ho prostě neutneš ... furt nechápu tvou otázku, dycky budeš muset tupě skočit na adresu v paměti. Jinak kontrolu asi nebudeš mít takovou jak si přeješ (a co ochrana paměti hmm ...) ... kernel není VM.
aha, u x86_32: máš task switching mechanismus (koukni do dokumentace). u x86_64 musíš všechno udělat ručně, ale TSS je potřeba furt (pro switch stacku při interruptu == každá úroveň privilegovanosti vyžaduje jinej stack). Při přepnutí kontextu musíš uložit obsah registrů stávající úlohy, nahrát obsahy registrů nové úlohy, vložit novou kořenovou tabulku pro Paging do CR3, nahrát novej TSS do TR a pak skočit na přerušenou adresu. Pro vyvolávání handleru scheduleru použij timer (využij APIC jádra).
Eh ? přesně nechápu otázku, ale možná se ptáš na interrupty. U x86 se koukni na téma IDT.
Hoj,
hledám dobře zdokumentovanou, přehlednou, a velmi rychle naučitelnou knihovnu pro práci s grafy (hledám nejkratší cestu z bodu A do bodu B, potřebuji výpis všech uzlů cesty, nikoli jen číslo vzdálenosti). Když jsem se kouknul na to, co nabízí Boost, tak jsem se zhrozil. Tak strašnou dokumentaci jsem ještě neviděl. Navíc kód (napsaný uživatelem BGL) vypadá jak od schizofrenického prasete (část je procedurálně, část OOP a různě se to mísí, přičemž autor knihovny se s OOP teda nesral). Takže knihovny krom BOOSTu. Díky.
Java je pomalí neštěstí, pokud neděláš něco na android a nebo pro enterprise prostředí (tam je java bomba), je chyba javu použít. Jedná se skutečně o nechutně nevýkonej jazyk (jako ostatně všechny jazyky pracující na principu bajtkódu a následné JIT kompilace při běhu - nic se nevyrovná nativní binárce).
V tom že C++ neumíš není problém, neřešíš problém jazyka ale API ... jazyk není nic těžkého. Nastuduj winAPI a nebo MFC. Přesně tydle problémi vznikaj když začneš programovat něco, na co nemáš nastudovaný potřebný API.
Je to tak, děkuji za ochotu mi osvětlit tento problém.
Ať se snažím vzpomenout sebeurputněji, nemůžu si vzpomenout že by mi C++ (G++) něco takového v minulosti provedlo. Fakt mám pocit že tyto optimalizace přišli nedávno (rok zpět?). Na druhou stranu chápu výhodu tohoto řešení (vzhledem k tomu že staticky alokovaná pole jsou uložena na stacku).
Takže to mám chápat tak, že u staticky alokovanejch polí kompilátor dělá optimalizaci v přístupu (2D pole je int * 2DArr ačkoli logika (a kniha) říká int ** 2DArr) a proto to prostě nepasuje ... fajn. Já mám prostě v podvědomí uloženo že to dřív fungovalo i s klasickym zápisem ... asi ne když říkáš.
Nazdar,
střetl jsem se s něčím co opravdu nechápu. Problematiku polí jsem už dávno překonal a pro usnadnění jsem začal používat kontejnery. Ale co čert nechtěl, musím se hrabat v jednom ze svých starších kódů kde ještě pole používám. No, a to je ten problém. Oni ty kódy totiž nefungují (ale předtím fungovali ... aspoň myslím, já už teď fakt nevím nic jistě). Problém popíšu přímo ve zdrojáku:
int foo(int ** bar, int width, int height)
{
int result=0;
for (int i=0;i<width;++i)
{
for (int y=0;y<height;++y)
{
result += bar[i][y];
}
}
return result;
}
int main()
{
using namespace std;
int arr[3][3] =
{
{41,47,85},
{96,78,14},
{32,14,58}
};
/*Kompiler křičí že se nejedná o kompatibilní datové typy, ale co kecá OMG...arr JE 2D pole a to je skutečně pointer na pointer*/
cout << foo(arr,3,3) << endl;
/*Zde už kompiler nekřičí...ALE...program leze do paměti kam nemá a linux mi vyhodí SIGSEGV*/
cout << foo((int**)arr,3,3) << endl;
return 0;
}
Jakmile 2D pole dynamicky alokuju (přímo do ** ), žádné problémy nemám. Je to snad tím že C++ začalo brát staticky alokované pole jinak?? Dřív to nebylo ne? Jsem opravdu zmaten tímto problémem.
Vyřešeno
Použij asociativní kontejner, v kterým si zaznamenáš, kolikrát se jaké číslo vyskytlo. Pak vypiš šest s největším výskytem. Toť vše.
Zapoměl bych ...
.macro power base , exp
push bx
mov ax , \base
mov bl , \exp
call __power
pop bx
.endm
.globl __power
__power:
cmp bl , 0
jne pw1
mov ax , 1
jmp pw10
pw1:
cmp bl , 1
jne pw2
jmp pw10
pw2:
dec bl
mov bh , 0
mov cx , ax
pw0:
mul cl
inc bh
cmp bh , bl
jne pw0
pw10:
ret
[x86 real mode <BIOS interrupts>, GAS ASM, linker LD, emulátor BOCHS]
Nazdar,
čelím tentokrát již poměrně konkrétnímu problému... Napsal sem rutinu na načítání čísel, ale jaksi nefunguje. Když zadám 100, vrátí mi 110. Když zadám 200 nebo 250 vždy mi vrátí 210 a tak dále (u tisíce mám overflow v pomocném registru takže se nadají zadávat čísla větší jak 1000). Už sem s tím peru celkem dost hodin, a ne a ne najít kde je zakopanej pes. Pokud by se někomu povedlo najít chybu, byl bych zkutečně rád...
.globl __readNumber
__readNumber:
readChar
cmp al , 'x' /* ještě sem nevyřešil enter, takže pro ukončení zadávání používám x (enter mi dělá bordel...) */
jne rn0
mov ax , 0
mov bl , 0
jmp rn10
rn0:
sub al , 0x30
push ax
call __readNumber
mov cx , ax
power 10 , bl
inc bl
mov dx , ax
pop ax
mul dl /* zde se projeví overflow u čtyř ciferného čísla ... */
add ax , cx
rn10:
ret
Rutiny na kterých je závislá funkce s chybou (načtení znaku) :
.macro readChar
mov ah , 0
int 0x16
printChar al
.endm
.macro printChar char
push ax
setCharColor 0xf
mov al , \char
mov ah , 0xe
int 0x10
pop ax
.endm
.macro setCharColor color
push ax
push bx
push cx
mov bl , \color
call __setCharColor
pop cx
pop bx
pop ax
.endm
.globl __setCharColor
__setCharColor:
mov ah , 0x9
mov al , ' '
mov bh , 0
mov cx , 1
int 0x10
ret
Hoj,
má někdo z Vás zkušenosti s emulátorem bochs? Mám totiž jeden problém a spíš než jako má chyba to vypadá jako bug. Mám napsané rutiny na výpis čísel a řetězců plus managment odřádkování. Zde je ale právě ten problém. Ve chvíli kdy dojdou volné řádky na obrazovce, zavolám interrupt BIOSU pro posunutí všech řádku o jeden nahoru a posunu kurzor na začátek posledního řádku řádku. No, a jakmile vypíšu další řetězec, jeho první znak tam prostě není (prázdné místo), řetězec je zobrazen až od druhého znaku. Testoval jsem zdali si něčím nepřepisuji řetězec ale, bohužel nepřepisuji ... další zajímavá věc je že když použije stejný postup s posunutém všech řádků o jeden nahoru ještě předtím než mi dojdou řádky, nemám při vypisování dalších řetězců problémy (zobrazí se celí). Žádné registry si omylem nepřepisuji, takže chyba nemohla vzniknout takto (opravdu velmi hojně používám stack ...). Pokud bude někdo zaujat problémem či se s ním sám setkal, budu rád za pomoc. Zdroják sem nevkládám protože už je poněkud delší, v případe zájmu ho zašlu na mail (stačí ho jen tak hodit do komentářů -> ten mail ...).
Nazdar,
zase mám problém ... vytvořil jsem si funkci na výpis čísla (celého). Bohužel, někde sem v ní udělal chybu neb obvykle vypisuje kraviny (místo 950 třeba 900 a tak). Kontroloval jsem ji několikrát ale chybu sem v ní nenašel ...
.macro printDigit dig
push ax
mov al , \dig
mov ah , 0xe
add al , 0x30
int 0x10
pop ax
.endm
.macro printNumber num
push ax
mov ax , \num
call __printNumber
pop ax
.endm
.globl __printNumber
__printNumber:
push bx
mov bx , 10
div bx
cmp al , 9
jle p0
jmp p1
p0:
printDigit al
jmp p2
p1:
push ax
movzx ax , al
call __printNumber
pop ax
p2:
cmp ah , 9
jle p3
jmp p4
p3:
printDigit ah
jmp p5
p4:
push ax
movzx ax , ah
call __printNumber
pop ax
p5:
pop bx
ret
Budu rád za případné rady.
to Z:
Chlape, si idiot, fakt miluju takový chytrolíny kteří dělaj borce a přitom vědí sami hovno. Tvoje první rada byla naprosto zbytečná (neřešila můj problém -> ani se k němu neblížila). Krom registru DS žádný jiný zatím nepotřebuji (stack přijde na řadu později a paměť dereferencuju zkrz DS:SI). K tvému doporučení "A když do toho SI chceš dát offset, tak tam dej offset" musím pouze dodat, děkuju za radu to by mě nenapadlo !ironie!.
Asi sem málo popisoval svůj problém (jinak si neumím vysvětlit tvoji ignoranci). Sice je pravda že na úplným začátku sem vypustil používání segmentů no, ale mít blbý kecy a ani si nepřečíst další příspěvky (a zjistit jak se vyvíjí situace) krom prvního je stupidní.
Tady to máš ještě jednou:
Když do registru SI dám přímo offset číslem napevno (mov si, 0x17), vypíše mi to požadovaný řetězec.
Ve chvíli když tam strčím label řetězce (mov si,WORD PTR ds:0x17), tak to začne taky něco vypisovat, ale z úplně jiné adresy.
A teď k řešení které hledám...ASM mi zřejmě 0x17 vezme jako absolutní adresu, a část (a nebo celou) strčí do DS při přiřazení do SI (a tím pádem to vede asi někam do IVT...). Proto teď hledám metodu, jak ASM říct aby ke každé adrese přičetl 0x7c00 (a rozdělení adresy dopadlo validně), a nebo vypnul to "vylepšení" a nastavil vkládání přímo čísel. Toť vše.
Ale je to asi marný, těžko mi může pomoci někdo, kdo (podle mne, třeba nemám pravdu xD) není schopen můj kód spustit, či si ho aspoň přečíst (jinak si neumím vysvětlit ty tvoje "rady")...
Pokud ti vadí útočná forma mého komentu, tak věz že je to tvoje chyba, prostě si mě nasral tím svým navážením v minulém příspěvku...
to Z : ujišťuji tě že tady problém není ...
Problém je zde :
mov si,WORD PTR ds:0x17
A já potřebuju aby mi tam GAS dal jen
mov si, 0x17
Poté všechno bude šlapat jak hodinky, DS segment je už inicializován na 0x7c0 (*16=0x7c00 == začátek paměti s bootloaderem + offset 0x17 a sem nazačátku přaného řetězce...). V dissasemblovaný binárce se jde přesvědčit že skutečně začíná řetězec na 0x17.
Dostal sem se zase dál, už je to v podle mne validním stavu, ale GAS ASM mi hází klacky pod nohy. Dole přikládám kód a disassemblovanou binárku.
// <------------------------------------->
.intel_syntax noprefix
.code16
// <------------------------------------->
.macro initDSSegment num
mov ax , \num
mov ds , ax
.endm
.macro printStr strAdr , lenght
mov cx , \lenght
mov si , \strAdr
printStrLoop:
mov al , byte ptr [si]
mov ah , 0xe
int 0x10
inc si
loop printStrLoop
.endm
.globl entryPoint
entryPoint:
initDSSegment 0x7c0
printStr welcomeString , 27
endls: jmp endls
// <------------------------------------->
welcomeString: .string "Hello world from low level!"
// <------------------------------------->
// <------------------------------------->
.org 510
.byte 0x55
.byte 0xaa
.att_syntax noprefix
// <------------------------------------->
a zde je disassemblovaná binárka
0: b8 c0 07 mov ax,0x7c0
3: 8e d8 mov ds,ax
5: b9 1b 00 mov cx,0x1b
8: 8b 36 17 00 mov si,WORD PTR ds:0x17 // Offset 0x17 je validní, jedná se skutečně o začátek řetězce. Vrásky mi však dělá to, co sakra dělá ten blbej assembler s WORD PTR ds:0x17. Mám pocit že dělá nějaký mnou nechtěný nadstandard ...
c: 8a 04 mov al,BYTE PTR [si]
e: b4 0e mov ah,0xe
10: cd 10 int 0x10
12: 46 inc si
13: e2 f7 loop 0xc
15: eb fe jmp 0x15 // ZDE je Konec ...
17: 48 dec ax
18: 65 gs
19: 6c ins BYTE PTR es:[di],dx
1a: 6c ins BYTE PTR es:[di],dx
1b: 6f outs dx,WORD PTR ds:[si]
1c: 20 77 6f and BYTE PTR [bx+0x6f],dh
1f: 72 6c jb 0x8d
21: 64 20 66 72 and BYTE PTR fs:[bp+0x72],ah
25: 6f outs dx,WORD PTR ds:[si]
26: 6d ins WORD PTR es:[di],dx
27: 20 6c 6f and BYTE PTR [si+0x6f],ch
2a: 77 20 ja 0x4c
2c: 6c ins BYTE PTR es:[di],dx
2d: 65 gs
2e: 76 65 jbe 0x95
30: 6c ins BYTE PTR es:[di],dx
31: 21 00 and WORD PTR [bx+si],ax
...
1fb: 00 00 add BYTE PTR [bx+si],al
1fd: 00 55 aa add BYTE PTR [di-0x56],dl
Hoj,
díky za odpověď, máš pravdu, ňák sem se vysral na princip segment:offset. Už sem to napravil ALE ... vyzbrojen informacema sem se hrdině vrhl do implementace ale ... zase hovno. Použil sem ze zoufalství nechutný hackování, v hex editoru sem si našel offset začátku mého řetězce a k této hodnotě sem poté přičet 0x7c00 (adresa na kterou se nahraje bootloader). Výsledné číslo sem poté upravil na segment DS=1 (odečetl jsem od něj 16). Ale zase hovno, vypsalo mi to pár posledních písmen řetězce (to byl úspěch! xD). Tak sem tedy od toho podle citu pár bajtů odečet a dostal se k vypsání mé věty. Bohužel tento přístup opravdu nejde v praxi použít a ani nejsem schopen logicky vysvětlit kde se vzalo mnou vypočítané číslo. Dole přikládám aktuální zdroják a otázka zůstává stejná. Jak ten blbej ASM donutit zobrazit můj řetězec bez tohodle hackování s hex editorem.
// <------------------------------------->
.intel_syntax noprefix
.code16
// <------------------------------------->
.macro initDSSegment num
mov ax , \num
mov ds , ax
.endm
.macro printStr strAdr , lenght
mov cx , \lenght
mov si , 31750 /* zde je ta prokletá adresa ... */
printStrLoop:
mov al , byte ptr [si]
mov ah , 0xe
int 0x10
inc si
loop printStrLoop
.endm
.globl entryPoint
entryPoint:
initDSSegment 1
printStr welcomeString , 27
endls: jmp endls
// <------------------------------------->
welcomeString: .string "Hello world from low level!"
// <------------------------------------->
// <------------------------------------->
.org 510
.byte 0x55
.byte 0xaa
.att_syntax noprefix
// <------------------------------------->
SECTIONS
{
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
<MIMO téma, ale mohl bys vysvětlit co to je ta videostránka, nikde sem pořádně neviděl vysvětlení>
Hoj,
mám takový problém, mám bootloader jež má vypisovat řetězec, ale on ho ňák nevypisuje a opravdu netuším čím to je.
{
x86 real mode [16 bit]
GNU binutils [AS , LD]
emulováno pomocí BOCHS
}
// <------------------------------------->
.intel_syntax noprefix
.code16
// <------------------------------------->
.macro printStr strAdr , lenght
mov cx , \lenght
mov si , \strAdr
printStrLoop:
mov al , byte ptr [si] // tady bude zakopanej pes ...
mov ah , 0xe
int 0x10
inc si
loop printStrLoop
.endm
.globl entryPoint
entryPoint:
printStr welcomeString , 26
endls:
nop
jmp endls
welcomeString: .string "Hello world from low level!"
// <------------------------------------->
.org 510
.byte 0x55
.byte 0xaa
.att_syntax noprefix
// <------------------------------------->
linker skript (jo já vím, je blbě, ale aspoň to už nevyhazuje takovej jeden divnej error ... )
SECTIONS
{
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
VS a nejlepší? Nemyslím. Prostě si s code blockem musíš stáhnout mingw (pro gcc) a při spuštění ho vybrat jako kompiler. Nic těžkého. Nic ti nekompiluje neb nemá čím...
Zasláno z mobilního telefonu.
Nazdar,
mám procesor Intel Pentium G860 který podle dokumentace podporuje MMX technologii. Když sem to však testoval pomocí CPUID instrukce, vypadla na mne 0 (prej nepodporuje). Zkusil sem zkusmo hodit nějakou MMX instrukci do kódu a vše šlapalo. Zajímalo by mne zdali je to bug a nebo má chyba.
#include <stdio.h>
#include <stdlib.h>
#define EAX 1
#define EBX 2
#define ECX 3
#define EDX 4
int CPUinf(int leaf,int bitIndex,int registerToMine);
int main()
{
printf("%d",CPUinf(1,23,EDX));
printf("\n");
return 0;
}
a samotný ASM kód funkce :
// CPUinf
.globl CPUinf
CPUinf:
push r8
mov eax , edi
mov r8d , 1
cpuid
cmp rdx , 1
je A
cmp rdx , 2
je B
cmp rdx , 3
je C
cmp rdx , 4
je D
A:
bt eax , esi
jmp end
B:
bt ebx , esi
jmp end
C:
bt ecx , esi
jmp end
D:
bt edx , esi
jmp end
end:
cmovc eax , r8d
mov r8d , 0
cmovnc eax , r8d
pop r8
ret
// end
BTW -> kompilujte to s 64 bit GCC, jinak neručím za funkčnost (z důvodu volací konvence).
Nazdar,
moh by mi někdo vysvětlit proč proboha není rychlejší specializovaná instrukce X86 procesoru (movs) na přesunutí řetězce bajtů než její opis pomocí cyklu a prostého přesunutí jednotlivých prvků pomocí instrukce mov? Opravdu to nechápu ... Když je to specializovaná instrukce, tak snad by měla bejt rychlejší ne ... Asi ne. Dole zmiňuji kód na kterém jsem měřil rychlost.
#include <iostream>
int main()
{
using namespace std;
int one[5] = {10,20,30,40,50};
int two[5] = {0};
for (register int i=0;i<1000000000;++i)
{
/*for (register int i=0;i<5;++i)
{
two[i] = one[i];
}*/
asm(
".intel_syntax noprefix;"
"mov rsi , %0;"
"mov rdi , %1;"
"mov rcx , 5;"
"rep movsd;"
".att_syntax noprefix;"
:
: "r"(one), "r"(two)
: "rcx","rsi","rdi"
);
}
for (int i=0;i<5;++i)
cout << one[i] << " ,";
cout << endl;
for (int i=0;i<5;++i)
cout << two[i] << " ,";
return 0;
}
// ASM -> 8,722 s
// Cyklus ->10,399 s
// Cyklus s register counterem --> 5,022 s !!! WHY !!!
Zde je kód v ASM funkce main s cyklem :
0x4009c0 push rbp
0x4009c1 mov rbp,rsp
0x4009c4 push r12
0x4009c6 push rbx
0x4009c7 sub rsp,0x40
0x4009cb mov DWORD PTR [rbp-0x30],0xa
0x4009d2 mov DWORD PTR [rbp-0x2c],0x14
0x4009d9 mov DWORD PTR [rbp-0x28],0x1e
0x4009e0 mov DWORD PTR [rbp-0x24],0x28
0x4009e7 mov DWORD PTR [rbp-0x20],0x32
0x4009ee mov QWORD PTR [rbp-0x50],0x0
0x4009f6 mov QWORD PTR [rbp-0x48],0x0
0x4009fe mov DWORD PTR [rbp-0x40],0x0
0x400a05 mov r12d,0x0
0x400a0b jmp 0x400a2e <main()+110>
0x400a0d mov ebx,0x0
0x400a12 jmp 0x400a25 <main()+101>
0x400a14 movsxd rax,ebx
0x400a17 mov edx,DWORD PTR [rbp+rax*4-0x30]
0x400a1b movsxd rax,ebx
0x400a1e mov DWORD PTR [rbp+rax*4-0x50],edx
0x400a22 add ebx,0x1
0x400a25 cmp ebx,0x4
0x400a28 jle 0x400a14 <main()+84>
0x400a2a add r12d,0x1
0x400a2e cmp r12d,0x3b9ac9ff
0x400a35 jle 0x400a0d <main()+77>
0x400a37 mov DWORD PTR [rbp-0x14],0x0
0x400a3e jmp 0x400a66 <main()+166>
0x400a40 mov eax,DWORD PTR [rbp-0x14]
0x400a43 cdqe
0x400a45 mov eax,DWORD PTR [rbp+rax*4-0x30]
0x400a49 mov esi,eax
0x400a4b mov edi,0x601080
0x400a50 call 0x400820 <_ZNSolsEi@plt>
0x400a55 mov esi,0x400bb1
0x400a5a mov rdi,rax
0x400a5d call 0x400880 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x400a62 add DWORD PTR [rbp-0x14],0x1
0x400a66 cmp DWORD PTR [rbp-0x14],0x4
0x400a6a jle 0x400a40 <main()+128>
0x400a6c mov esi,0x4008a0
0x400a71 mov edi,0x601080
0x400a76 call 0x400890 <_ZNSolsEPFRSoS_E@plt>
0x400a7b mov DWORD PTR [rbp-0x18],0x0
0x400a82 jmp 0x400aaa <main()+234>
0x400a84 mov eax,DWORD PTR [rbp-0x18]
0x400a87 cdqe
0x400a89 mov eax,DWORD PTR [rbp+rax*4-0x50]
0x400a8d mov esi,eax
0x400a8f mov edi,0x601080
0x400a94 call 0x400820 <_ZNSolsEi@plt>
0x400a99 mov esi,0x400bb1
0x400a9e mov rdi,rax
0x400aa1 call 0x400880 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x400aa6 add DWORD PTR [rbp-0x18],0x1
0x400aaa cmp DWORD PTR [rbp-0x18],0x4
0x400aae jle 0x400a84 <main()+196>
0x400ab0 mov eax,0x0
0x400ab5 jmp 0x400abf <main()+255>
0x400ab7 mov rdi,rax
0x400aba call 0x4008c0 <_Unwind_Resume@plt>
0x400abf add rsp,0x40
0x400ac3 pop rbx
0x400ac4 pop r12
0x400ac6 pop rbp
0x400ac7 ret
Zde je ASM kód funkce main s mnou vložením řešením pomocí specializované instrukce :
0x4009c0 push rbp
0x4009c1 mov rbp,rsp
0x4009c4 push rbx
0x4009c5 sub rsp,0x48
0x4009c9 mov DWORD PTR [rbp-0x30],0xa
0x4009d0 mov DWORD PTR [rbp-0x2c],0x14
0x4009d7 mov DWORD PTR [rbp-0x28],0x1e
0x4009de mov DWORD PTR [rbp-0x24],0x28
0x4009e5 mov DWORD PTR [rbp-0x20],0x32
0x4009ec mov QWORD PTR [rbp-0x50],0x0
0x4009f4 mov QWORD PTR [rbp-0x48],0x0
0x4009fc mov DWORD PTR [rbp-0x40],0x0
0x400a03 mov ebx,0x0
0x400a08 jmp 0x400a24 <main()+100>
0x400a0a lea rax,[rbp-0x30]
0x400a0e lea rdx,[rbp-0x50]
0x400a12 mov rsi,rax
0x400a15 mov rdi,rdx
0x400a18 mov rcx,0x5
0x400a1f rep movs DWORD PTR es:[rdi],DWORD PTR ds:[rsi]
0x400a21 add ebx,0x1
0x400a24 cmp ebx,0x3b9ac9ff
0x400a2a jle 0x400a0a <main()+74>
0x400a2c mov DWORD PTR [rbp-0x14],0x0
0x400a33 jmp 0x400a5b <main()+155>
0x400a35 mov eax,DWORD PTR [rbp-0x14]
0x400a38 cdqe
0x400a3a mov eax,DWORD PTR [rbp+rax*4-0x30]
0x400a3e mov esi,eax
0x400a40 mov edi,0x601080
0x400a45 call 0x400820 <_ZNSolsEi@plt>
0x400a4a mov esi,0x400ba1
0x400a4f mov rdi,rax
0x400a52 call 0x400880 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x400a57 add DWORD PTR [rbp-0x14],0x1
0x400a5b cmp DWORD PTR [rbp-0x14],0x4
0x400a5f jle 0x400a35 <main()+117>
0x400a61 mov esi,0x4008a0
0x400a66 mov edi,0x601080
0x400a6b call 0x400890 <_ZNSolsEPFRSoS_E@plt>
0x400a70 mov DWORD PTR [rbp-0x18],0x0
0x400a77 jmp 0x400a9f <main()+223>
0x400a79 mov eax,DWORD PTR [rbp-0x18]
0x400a7c cdqe
0x400a7e mov eax,DWORD PTR [rbp+rax*4-0x50]
0x400a82 mov esi,eax
0x400a84 mov edi,0x601080
0x400a89 call 0x400820 <_ZNSolsEi@plt>
0x400a8e mov esi,0x400ba1
0x400a93 mov rdi,rax
0x400a96 call 0x400880 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x400a9b add DWORD PTR [rbp-0x18],0x1
0x400a9f cmp DWORD PTR [rbp-0x18],0x4
0x400aa3 jle 0x400a79 <main()+185>
0x400aa5 mov eax,0x0
0x400aaa jmp 0x400ab4 <main()+244>
0x400aac mov rdi,rax
0x400aaf call 0x4008c0 <_Unwind_Resume@plt>
0x400ab4 add rsp,0x48
0x400ab8 pop rbx
0x400ab9 pop rbp
0x400aba ret
Měření efektivity bylo prováděno bez závěrečného vypsání obou polí.
Hej díky, du to implementovat. Sem nevěděl jestli je to neznalostí knihovny a nebo musím hackovat.
Hoj,
mám takovou neurčitou otázku. Pomocí QT knihovny jsem udělal primitivní program na malování. Vše funguje, ale! Když dělám čáru pomalu, je plynulá, jakmile však táhnu rychleji, je přerušovaná jak nestíhá QT zpracovávat zavčasu eventy. A teď k samotné otázce, jak vyřešit tento problém (zkoušel jsem si hrál s event filtrama, ale zajistil jsem pouze zamrznutí celého programu neb sem filtroval i eventy nutné pro chod programu, bohužel, nevím o jaké se jednalo, takže jsem nemohl udělat vyjímku). Nehledě na to že event filtry zřejmě nejsou řešení mého problému. Za radu někoho zkušenějšího jak na to (třeba se s filtrama pletu ...) co se týče QT budu vděčný.
Hoj,
mám takový problém, když chci použít v QT Creatoru (používá GCC) inline assembler který používá instrukci RDRAND (generuje náhodná čísla), program se zkompiluje a spustí ale pro jistotu okamžitě spadne s hláškou "Program neočekávaně spadl" (to sem viděl taky ... fakt miluju tydle hlášky). Když tam skusím nacpat jiné instrukce, vše běží bez problému. BTW -> můj procesor má podporu instrukce RDRAND. Díky za jakékoli nápady čím to může být.
Ser na VB, umíš C++ ? Pokud jo nastuduj knihovnu QT, v tom se daj dělat luxusní GUI multiplatfomní aplikace. Ptáš se jak udělat hru ? Odpověď nedostaneš. Napřed nastuduj technologie jež budeš pro hru potřebovat a poté již pude samotná realizace sama. Ser na ty sračky co tě učej ve škole, jdi vlastní cestou (stejně učej nepoužitelně - neučej technologie ale spíš ukazují příklady).
Hoj,
asi to patří do sekce ASM ale tam to není moc aktivní, takže se zeptám radši tady protože to souvisí s GCC. Když pošlu GCC (přesněji linkeru ld) pomocí přepínače -e nový entry point. Hází mi výsledný program SIGSEGV (segmentation fault). Nevím čím to je, ani google nepomohl. Kód zde nepřikládám, neb to není třeba. Prostě sem místo funkce main nastavil jako entry point svoji funkci (myMain).
díky za odpověď, kód knihovny jsem sem nechtěl strkat. Ptal jsem se proto že jsem přemýšlel jakým způsobem rozsekali ty obrázky. Teď už je mi to víceméně jasné. Stejný obrázek v tuně divů se skrytým přeteklým obsahem, jen pokaždé jinak umístěný.
Hoj,
peru se s inline ASM v G++, vyhodil mi tendle roztomilej error /*Stack smashing detected */ a já nemůžu zjistit kde že to lezu mimo paměť. Za pomoc budu opravdu rád neb opravdu netuším jak chybu vyřešit. /*kde je sem našel ale je mi to k hovnu*/
#include <iostream>
#include <string>
#include <cstdlib>
int main()
{
using namespace std;
int var0[2] = {4,8};
int var1[2] = {25,89};
int var2[2] = {0};
asm(
".intel_syntax noprefix;"
"mov rdx,[%0];"
"add rdx,[%1];"
"mov [%2], rdx;"
"mov rdx,[%0+1*4];"
"add rdx,[%1+1*4];"
"mov [%2+1*4],rdx;" // Tady je zakopanej pes ale nevím proč ...
".att_syntax noprefix;"
: /* no output */
: "a" (var0), "b" (var1), "c"(var2)
: "rdx"
);
cout << var2[0] << " a " << var2[1] << endl;
return 0;
}
Hoj,
na netu jsem našel knihovnu skitter.js která dělá opravdu pěkné animace s obrázky. Nepřišel jsem však na to jak to dělá. Pokud vím tak DOM nenabízí žádné API k manipulaci s obrázky. Používá snad tato knihovna canvas (tam už jde přistupovat k hodnotám jednotlivých pixelů)? Použití canvasu se mi však nezdá neb není ještě 100% kompatibilita se všemi prohlížeči (možná - nevím jistě tak mne neberte za slovo).
Hoj,
mám tady další problém. Protože mé dovednosti angličtiny jsou vcelku žalostné, nepovedl se mi pochopit princip knihovny <future>. Byl by někdo tak hodný a vysvětlil mi základní princip? To by mělo stačit, myslím že jakmile budu vědět rámcově o co go, dokážu to už přelouskat.
Hoj,
nečelím v tuto chvíli ani tak problému jako spíš nejasnosti. Mám dvě vlákna které provádějí operace nad stejnou globální proměnnou. Globální proměnná je atomického datového typu. Přesto se moc atomicky nechová. Výsledek tohoto programu je pokaždé jiný, ačkoli by měl být stejný což znamená že se mi tam rvou vlákna. Není mi moc jasné proč, neb přece používám atomický datový typ který by měl být ňák "olockovaný" ne? Je dost možné že my něco uniklo, přece jenom někdy anglické věty hádám takže se radši ptám.
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
std::atomic<unsigned long> result(0);
void work()
{
using namespace std;
for (int i=0;i < 10000000;++i)
{
if (result.is_lock_free()) /*result není nikdy zamčen ???*/
{
//++result; /*funguje jak má*/
result.store(result.load()+1); /*pokaždé jiný vysledek*/
}
else
{
cout << "Atom result je zamcen!" << endl;
}
}
}
int main()
{
using namespace std;
thread alphaThread(work);
thread betaThread(work);
alphaThread.join();
betaThread.join();
cout << result.load() << endl;
return 0;
}
Hoj,
mám tady zapeklitý dotaz...proč mi níže uvedený kód skončí výjimkou system_error s textem "Operation not permitted". V použití vlákna jsem podle mne neudělal žádnou chybu (stejnou chybu to hází i u příkladu na http://www.cplusplus.com/reference/thread/thread/thread/).
#include <chrono>
#include <iostream>
#include <thread>
void action()
{
using namespace std;
for (int i=0;i<10;++i)
{
cout << "hello" << endl;
this_thread::sleep_for(chrono::seconds(1));
}
}
int main()
{
using namespace std;
thread thr(action);
cout << thread::hardware_concurrency << endl;
thr.join();
return 0;
}
Je to prosté, skus udělat zákeřný virus a pak dobrou 3D hru. Pak porovnej množství času který jsi s každým jednotlivým projektem strávil a odpovíš si sám. Samozřejmě, pro správné porovnání musí být hra stejně dobrá, jako virus zákeřný, jinak nejsi schopen relevantně porovnat složitost. Složitost nemá definované jednotky, takže si musíš vystačit s časem :(.
Já osobně bych bejt tebou nepředbíhal ... aplikace s GUI jsou trošku jiný kafe než konzolový. Napřed si projdi knihu z který se učíš a nauč se základy (třeba co vlastně dělá kompilátor a co je vůbec ten jazyk zač - pak si sám odpovíš na první otázku). Jinak webový aplikace se dělají pomocí HTML + CSS + javascript + PHP, no a nebo pomocí ASP.NET (detaily neznám, nemám vědomosti o platformě .NET). Dále ale existují další cesty k vytvoření webové aplikace ... (ruby on rails framework pro jazyk ruby atp.). Java jde samozřejmě pro web použít taky.
nic tam není špatně ... prostě nastal konflikt jména třídy s něčím jiným stejně pojmenovaným.
namespace chr
{
class Time
{ // trieda Time
private:
int hodiny;
int minuty;
public:
Time(int h = 0, int m = 0) : hodiny(h), minuty(m) {}; // konstruktor
void addminuty(int); //nepoctatná funkcia
void addhodiny(int); //nepoctatná funkcia
Time sum(const Time&) const; // TATO FUMKCIA BY MALA NAVRACAT OJEKT TYPU Time!!!
void show() const; //nepoctatná funkcia
};
Time Time::sum(const Time& t) const // MALA BY VRÁTIŤ OBJEKT TYPU Time
{
Time temp;
temp.hodiny = hodiny + t.hodiny;
temp.minuty = minuty + t.minuty;
temp.hodiny += temp.minuty/60;
temp.minuty %= 60;
return temp;
}
}
Místo time je tam Time takže i kdybys odstranil ten jmenej prostor, mělo by to jít
Prásácky vyřešeno ale de to takto...
class time
{ // trieda time
private:
int hodiny;
int minuty;
public:
time(int h = 0, int m = 0) : hodiny(h), minuty(m) {}; // konstruktor
void addminuty(int); //nepoctatná funkcia
void addhodiny(int); //nepoctatná funkcia
auto sum(const time&) const -> time; // TATO FUMKCIA BY MALA NAVRACAT OJEKT TYPU TIME!!!
void show() const; //nepoctatná funkcia
};
auto time::sum(const time& t) const -> time // MALA BY VRÁTIŤ OBJEKT TYPU TIME
{
time temp;
temp.hodiny = hodiny + t.hodiny;
temp.minuty = minuty + t.minuty;
temp.hodiny += temp.minuty/60;
temp.minuty %= 60;
return temp;
}