Új hozzászólás Aktív témák
-
stepboy
csendes tag
Sziasztok; az elmúlt napokban akadt egy kis problémám, és [ezen] az oldalon találtam rá megoldást. Ha gondoljátok, akkor rakjátok be a többi link közé, hátha másnak is hasznos lehet.
[ Szerkesztve ]
-
stepboy
csendes tag
válasz dobragab #5550 üzenetére
sziasztok,
Ezt a példát nem értem.
int temp = 1;
evil_api_function_call(fp, ptr, &temp);C99-ben tudod lokális változónak is képezni a "címét" egy trükkel. Pontosabban: tudsz compound literal segítségével temp tömböt létrehozni egy elemmel, ami viszont már konvertálódik pointerre.
Tehát azt akarod mondani, hogy lokális változó címét nem lehet paraméterként átadni függvényhíváskor?
-
stepboy
csendes tag
válasz kpisti1990 #5730 üzenetére
hahó;
a switch-el a "state" változó értékét vizsgálod, ezért ha az állapotgépet léptetni akarod, akkor annak kell egy új értéket adni.
valahogy így:{
switch(state)
case ALAP:
...
state = FIZETETT;
break;
case FIZETETT:
...
state = KESZ;
break;
case KESZ:
...
state = ALAP;
break;
}Persze ez csak egy váz. A "state" értéke mindig attól függ, hogy a következő állapotba lépés engedélyezett-e; például az "ALAP" értéknél, csak a megfelelő karakter beolvasása után lehet "FIZETETT" érték, de remélem, hogy a lényeg megvan!
Ha még nem olvastad, akkor hasznos: [Állapotgépek]
Legközelebb használd a "Programkód" formázást, hogy olvasható legyen a kód amit beírsz.
[ Szerkesztve ]
-
stepboy
csendes tag
válasz kpisti1990 #5732 üzenetére
Így már jobban látom a kódod.
Miért van két "getchar()" ?Igen, úgy értettem, hogy csak akkor adhatsz a "state" változónak új értéket, ha a beolvasott karakter megfelelő, valahogy így:
while ( 1 )
{
switch ( state )
{
case ALAP:
{
printf( "szöveg\n" );
char c = getchar();
if ( ( c != 'k' ) || ( c != 't' ) || ( c != 'c' ) )
{
printf( "rossz betű\n" );
}
else if ( c == 'k' )
{
printf( "jó betű 1.\n" );
state = FIZETETT;
}
else if ( c == 't' )
{
printf( "jó betű 2.\n" );
state = FIZETETT;
}
else
{
printf( "jó betű 3.\n" );
state = FIZETETT;
}
break;
}
case FIZETETT:
{
printf( "valami szöveg\n" );
state = KESZ;
break;
}
case KESZ:
{
printf( "megint szöveg\n" );
state = ALAP;
break;
}
}
}Ez nem egy szép kód, de kezdetnek megteszi.
[ Szerkesztve ]
-
stepboy
csendes tag
válasz kpisti1990 #5734 üzenetére
A "while( 1 )" az végtelen ciklust jelent, mindig fut a kód amíg nem lépsz ki a ciklusból (például egy "break"-kel). A return-t el sem éri.
Amire gondolni tudok, hogy ez a ciklus a gépeden natívan fut, ergo nagyon gyors - az egyetlen hely ahol várakozik, az a billentyű lenyomása. Tehát amikor lenyomod a billentyűt, azt gyorsan kiértékeli és végig pörög a statemachine-en végül minden kezdődik elölről; de te még mindig ugyanazt a billentyűt nyomod, ezért úgy tűnik, mintha ismételné magát a program, pedig csak többször lefutott. Ez csak egy tipp, sajnos nem ismerem a stdio-t annyira, hogy megtudjam mondani valóban ez történik a te esetedben is.Úgyhogy, lehet hogy érdemes lenne valami lassítást rakni az állapotgépedbe:
- ALAP: ide nem kell, mert itt várakozik egy billentyű lenyomásra
- FIZETETT: ide valamilyen késleltető függvény, ami érzékelhetően feltartatja a programfutást (~1s kb.), tehát kiírja a szöveget, majd várakozik és utána lép a következő állapotba
- KESZ: itt ezt írod "-végén (ital elvételekor) álljon vissza alap állapotba", ebből nekem úgy tűnik, hogy valamilyen gombbal kell jelezni, hogy elvetted az italt, tehát az is billentyű beolvasás kell, hogy legyen.case FIZETETT:
{
printf( "valami szöveg\n" );
kesleltet_ms( 1000 );
state = KESZ;
break;
}A "kesleltet_ms()" pedig egy nagyon hosszú ciklus, ami a megadott milliszekundumnyi ideig várakozik:
void kesleltet_ms ( int ms )
{
while ( ms )
{
ms--;
for ( int c = 0; c < 65535; c++ )
{
/* ez itt ures */
}
}
}Ez egy nagyon kezdetleges megoldás, a belső "for" ciklust úgy kell tuningolni, hogy nagyjából 1 milliszekundum alatt érjen végig, szóval a c-t addig kell növelni.
Két nagyon fontos dolog:
- fordítás mindenféle optimalizáció nélkül (hogy biztosan benne legyen a lefordított kódban a ciklus és végig is menjen rendesen)
- a típusod olyan legyen, amibe a szám amit vizsgálni akarsz még elfér (tehát ha csak 16bites "int"-ed van, abba értelemszerűen 65535-nél nagyobb szám nem fér bele)Itt egy profibb megoldás: [The delay() Function]
A kilépésre meg azt javasolnám, hogy a while( 1 ) helyett legyen valami ilyesmi:
int bentmarad = 1;
while ( bentmarad )
{
switch ( state )
{
case ALAP:
{
printf( "szöveg\n" );
char c = getchar();
if ( ( c != 'k' ) || ( c != 't' ) || ( c != 'c' ) || ( c != 'q' ) )
{
printf( "rossz billentyű\n" );
}
else if ( c == 'k' )
{
printf( "jó betű 1.\n" );
state = FIZETETT;
}
else if ( c == 't' )
{
printf( "jó betű 2.\n" );
state = FIZETETT;
}
else if ( c == 'q' )
{
printf( "viszlát\n" );
bentmarad = 0;
}
...Tehát egy külön billentyűvel megszakítod az egész ciklust - persze, ha a feladatkiírás ezt nem teszi lehetővé, akkor nem kell belerakni a végleges kódba.
[ Szerkesztve ]
-
stepboy
csendes tag
Rossz úton indultál el; mert a switch szerkezeted csak véges értéket fogad el - a 0-t például hibásnak vesz, pedig azt akarod alapértéknek.
Amire szükséged lesz:
1. szám beolvasás
2. számok összeadása
3. feltétel vizsgálat (igaz, akkor kiír egy üzenetet, ha nem akkor vissza az 1.-es pontra)Ha így nézed, ez egy ciklus. Tehát neked valamilyen ciklusra lesz szükséged. Ciklus: működés
-
stepboy
csendes tag
válasz kpisti1990 #5741 üzenetére
hát windows.h-val csak windows-on működik a kód, de jó nyomon jársz.
-
stepboy
csendes tag
válasz CPT.Pirk #5785 üzenetére
Ha van egy szabad portod, akkor tudnál port billegtetést csinálni és kívülről vizsgálni, hogy valóban annyi idő telik-e el mint amennyire számítasz:
port_fel;
delay();
port_le;ezt megnézni O2-vel, O3-mal meg LTO-val. Ha igen, akkor nem ezzel a függvénnyel lesz baj.
Nem tudom, lehet, hogy hülyeség - esetleg, nem inline-olja a függvényt és cseszi el a regisztereket az O3/LTO build? Sok helyről hívjátok ezt a függvényt? Ha nem, akkor gyorsan meg lehetne nézni azokat a területeket is egy disassemblyvel.
[ Szerkesztve ]
-
stepboy
csendes tag
válasz CPT.Pirk #5787 üzenetére
esetleg, próbáld ki ezt:
http://stackoverflow.com/questions/12114019/g-and-attribute-optimize-not-changing-debugger-behavioritt azt írja, hogy alapból O2-vel fordít, de egy függvényt ezzel az attribute-tal máshogy tud optimalizálni.
#include <iostream>
#include <vector>
int MyNormalFunction();
int MyDebugabbleFunction() __attribute__((optimize(0)));
int MyNormalFunction()
{
int val = 0; // breakpoint here - debugger does NOT stop here
val = 1;
val = 2;
return val;
} // debugger stops here instead
int MyDebugabbleFunction()
{
int val = 0; // breakpoint here - debugger stops here and steps through the next 3 lines as if it were built with only -g
val = 1;
val = 2;
return val;
}
int main()
{
int a = MyNormalFunction();
std::cout << a << std::endl;
int b = MyDebugabbleFunction();
std::cout << b << std::endl;
return 0;
} -
stepboy
csendes tag
válasz CPT.Pirk #5790 üzenetére
Valószínű, hogy máshol van a hiba, ami kihatással van az USB működésére. A projekt többi része működik/meg lehet állapítani, hogy működik?
Viszont a kódot biztosan rossz:
__attribute __((naked))
void delay_loop (unsigned n)
{
__asm volatile ("1: sub r0, #1");
__asm volatile (" bne 1b");
__asm volatile (" bx 1r");
}[Itt találod a GCC Basic Asm leírását]
Van benne néhány fontos megjegyzés:
Do not expect a sequence of asm statements to remain perfectly consecutive after compilation. If certain instructions need to remain consecutive in the output, put them in a single multi-instruction asm statement. Note that GCC’s optimizers can move asm statements relative to other code, including across jumps.vagy ezek:
GCC does not parse basic asm’s AssemblerInstructions, which means there is no way to communicate to the compiler what is happening inside them. GCC has no visibility of symbols in the asm and may discard them as unreferenced. It also does not know about side effects of the assembler code, such as modifications to memory or registers. Unlike some compilers, GCC assumes that no changes to general purpose registers occur. This assumption may change in a future release.For basic asm with non-empty assembler string GCC assumes the assembler block does not change any general purpose registers, but it may read or write any globally accessible variable.
Megnéztem az optimalizációs leírást is, O3-mal jön az inline valóban, de azt ki lehet kapcsolni "noinline" attribute-tal (bár ez egy jó régi GCC: 4.7.4).
Ami a megjegyzéseket illeti, az elsőt nem hiszem, hogy vonatkozik rád a volatile miatt, tehát a sorrend marad. Viszont az inline miatt előfordulhat, hogy nem az van az R0-ban, amire számítasz. Normál esetben a függvényhíváskor az első paraméter valóban oda kell, hogy kerüljön, de ha a függvényt inline-olja a fordító, akkor már nincs garantálva, hogy az R0-án keresztül ad át bármit is, mivel a fordító nem látja, hogy bármi is történik az "n" változóval és azt feltételezi, hogy a regisztereket nem módosítja az assembly kódod.
Azt gondolom, hogyha már mindenképpen beágyazott assembly-t akarsz írni, akkor azt valahogy így kéne csinálni:
void delay_loop (unsigned n)
{
__asm ("1: sub %0, #1 \n\t"
" bne 1b \n\t"
" bx 1r "
:
: "r" (n));
}Mindezt az Extended-Asm leírás alapján (a fenti link következő oldala); itt már jelzed a fordítónak, hogy egy regisztert biztosan használsz és minden egy helyen van, ezért nem változhat meg a sorrend.
Bár a legjobb mindenképpen az lenne, ha az egészet átrakod sima assemblyre és akkor a fordító számára egy függvényhívás lesz a kód, amivel már nem tud trükközni.
[ Szerkesztve ]
-
stepboy
csendes tag
válasz CPT.Pirk #5799 üzenetére
Remélem nem túl nagy a kód, különben elég nagy szívás függvényenként végigmenni.
Hátha ez egy kis segítség lehet: Options That Control Optimization
Új hozzászólás Aktív témák
● olvasd el a téma összefoglalót!
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Melyik tápegységet vegyem?
- Fejhallgató erősítő és DAC topik
- Nothing Phone 2a - semmi nem drága
- Samsung Galaxy S23 és S23+ - ami belül van, az számít igazán
- Milyen videókártyát?
- Energiaital topic
- AMD Radeon™ RX 470 / 480 és RX 570 / 580 / 590
- Synology NAS
- OLED TV topic
- AMD GPU-k jövője - amit tudni vélünk
- További aktív témák...