Flagregister auslesen



  • Weiß jemand wie man das Flagregister in einer Hochsprache wie C auslesen kann?
    Versuche eigenen Overflowschutz zu machen...



  • --- schrieb:

    Weiß jemand wie man das Flagregister in einer Hochsprache wie C auslesen kann?
    Versuche eigenen Overflowschutz zu machen...

    ist so nicht eingebaut.

    enterder, du nimmst inline-assembler...

    unsigned int plus(unsigned int a,unsigned int b){
       bool overflow;
       unsigned int result;
       __asm mov eax,a;
       __asm add eax,b;
       __asm setc overflow;
       __asm mov result,eax;
       if(overflow) throw Fehler();
       return result;
    }
    

    oder du nimmst mathematische überlegungen...

    unsigned int plus(unsigned int a,unsigned int b){
       int result=a+b;
       if(result<a) throw Fehler();
       return result;
    }
    

    evtl

    if(result<a || result<b) throw Fehler();
    

    , hab ich jetzt nicht genau überlegt.



  • Danke ...

    Hab davon gehört, dass man mit pushf das Register auf den Stack bringt.
    Könnte man nicht so die Flags vom Stack in eine Variable speichern und dann auswerten? Wenn ja, wie?


  • Mod

    es gibt verschiedene möglichkeiten. im übrigen ist zu beachten, dass in einigen wenigen fällen die flags keine verlässliche auskunft über das vorliegen eines überlaufs geben. z.b. imul kann man sowohl für vorzeichenbehaftete als auch vorzeichenlose multiplikation verwenden (was der grund dafür ist, warum mul nur in der umständlichen expandierenden version existiert) - allerdings kann man dann die flags nicht benutzen, um einen vorzeichenlosen überlauf zu erkennen.

    prinzipiell ist eine überprüfung des ergebnisses der sauberste weg, überläufe zu erkennn, dummerweise ist es nicht unbedingt performant, wenn man komplexe ausdrücke hat.

    was du möglicherweise meinst, ist so etwas:

    unsigned getFlags()
    {
        __asm pushf
        __asm pop eax
    }
    

    dummerweise kann das nicht funktionieren, da du keine kontrolle darüber hast, wie der compiler einen gegebenen ausdruck tatsächlich auswertet, ausserdem wird dir auch noch instruktion reordering in die quere kommen.

    volkards inline vorschlag kann man noch minimal optimieren:

    unsigned int plus(unsigned int a,unsigned int b){
       __asm mov eax,a
       __asm add eax,b
       __asm jnc exit_
       throw Fehler();
    exit_:
    }
    

    eine andere möglichkeit ist es, überläufe vorher abzufangen:

    if ( std::numeric_limits<unsigned>::max() - a < b ) throw Fehler(); }
    


  • DANKE



  • camper schrieb:

    [...]z.b. imul kann man sowohl für vorzeichenbehaftete als auch vorzeichenlose multiplikation verwenden (was der grund dafür ist, warum mul nur in der umständlichen expandierenden version existiert)

    😕
    Das ist mir neu. Kannst du das bitte mal etwas genauer erlaeutern?


  • Mod

    wie du sicher weisst, gibt es verschiedene formen von imul mit einem, zwei oder drei operanden (hier nur die varianten mit 32bit operanden):
    imul r/m32
    imul r32, r/m32
    imul r32, imm8/32
    imul r32, r/m32, imm8/32

    nur die variante mit einem operanden hat eine entsprechung mit mul.

    die zwei- und drei-operanden formen führen zwar intern ebenfalls eine vollständige (expandierende) multiplikation aus, es wird aber nur das niederwertige 32bit word gespeichert. einen eventuellen signed überlauf bekommt man dabei durch carry- und overflow-flag mit. tatsächlich ist aber aufgrund der 2er-komplementdarstellung das ergebnis identisch zu dem, dass entstünde, wenn die operanden vorzeichenlos wären. lediglich überläufe kann man hier nicht abfragen. um es deutlich zu sagen: mul und imul unterscheiden sich nur im höherwertigen teil des ergebnisses.

    falls das neu für dich ist... ich hab auch jahre gebraucht, bis mir das klar geworden ist, obwohl es eigentlich auf der hand liegt. sehr praktisch bei adressberechnungen, wenn man mit dem SIB byte allein nicht weiterkommt. häufig genügen ja die unteren 32bit, und man ist dann nicht mehr an edx:eax gebunden und spart sich ständiges hin- und hergeschiebe nur im die register frei zu bekommen.



  • Ahso, thnx. 🙂

    Nur hat das IMHO nicht viel mit vorzeichenloser Multiplikation zu tun...
    Sobald du in der Multiplikation eine "negative Zahl" (also letztes Bit gesetzt) hast, passt das Ergebnis auf jeden Fall (ausgenommen Multiplikation mit 1 😉 ) nicht mehr allein ins niederwertige Word.
    Oder habe ich da jetzt was falsch verstanden?

    Ansonsten hast du recht: Diese vielen verschiedenen Formate von imul sind durchaus praktisch. 😋



  • Nobuo T schrieb:

    Sobald du in der Multiplikation eine "negative Zahl" (also letztes Bit gesetzt) hast, passt das Ergebnis auf jeden Fall (ausgenommen Multiplikation mit 1 😉 ) nicht mehr allein ins niederwertige Word.

    Und was willst du damit sagen?



  • Das war ein Versuch zu verdeutlichen, dass bei Verwendung von imul immer eine vorzeichenbehaftete Multiplikation ausgefuehrt wird und die Ergebnisse (in Gaenze betrachtet) von imul und mul nur so lange vergleichbar sind, wie mit positiven Zahlen multipliziert wird. => Verwendung von imul als mul-Ersatz macht nicht uneingescharaenkt Sinn. Kam mir nicht deutlich genug rueber - wollte ich nur nochmal auf den Punkt bringen... ...whatever...
    Ich seh' schon, das fuehrt nur zu Verwirrung und wird auch zu OT. 🙄


  • Mod

    Nobuo T schrieb:

    Das war ein Versuch zu verdeutlichen, dass bei Verwendung von imul immer eine vorzeichenbehaftete Multiplikation ausgefuehrt wird und die Ergebnisse (in Gaenze betrachtet) von imul und mul nur so lange vergleichbar sind, wie mit positiven Zahlen multipliziert wird. => Verwendung von imul als mul-Ersatz macht nicht uneingescharaenkt Sinn. Kam mir nicht deutlich genug rueber - wollte ich nur nochmal auf den Punkt bringen... ...whatever...
    Ich seh' schon, das fuehrt nur zu Verwirrung und wird auch zu OT. 🙄

    und genau das ist eben nicht der fall. es macht eben keinen unterschied, ob die benutzten zahlen negativ wären oder nicht - das niederwertige wort des ergebnis ist stets dasselbe:
    seien a und b zwei integer mit n bits.
    aua_u sei der wert von a interpretiert als vorzeichenloser integer,
    asa_s der wert von a von interpretiert als vorzeichenbehafteter integer in 2er komplementdarstellung.

    dann ist a_s=a_ua\_s = a\_u wenn das höchswertige bit nicht gesetzt ist, andernfalls gilt a_s=a_u2na\_s = a\_u - 2^n

    anolg seien bub_u und bsb_s definiert.

    das ergebnis einer vorzeichenlosen multiplikation ist dann: (a_ub_u)mod2n(a\_u*b\_u) mod 2^n

    das ergebnis einer vorzeichenbehafteten multiplikation ist je nachdem, welches vorzeichen asa_s und bsb_s haben:

    (a_ub_u)mod2n(a\_u*b\_u) mod 2^n

    ((a\_u-2^n)\*b\_u) mod 2^n = ((a\_u\*b\_u)-2^n*b_u) mod 2^n = ((a\_u\*b\_u) mod 2^n - (2^n\*b\_u) mod 2^n) mod 2^n = (a\_u*b_u) mod 2^n

    (a_u(b_u2n))mod2n=(a_ub_u)mod2n(a\_u*(b\_u-2^n)) mod 2^n = (a\_u*b\_u) mod 2^n

    ((a_u2n)(b_u2n))mod2n=(a_ub_u)mod2n((a\_u-2^n)*(b\_u-2^n)) mod 2^n = (a\_u*b\_u) mod 2^n

    (Anmerkung: im die frage ob -1 mod 2^n nun -1 oder 2^n-1 wäre, brauchen wir uns hier nicht kümmern, dank zweikomplement macht das keinen unterschied)

    und das ist eben genau dasselbe, was bei vorzeichenloser multiplikation herauskommt. Häufig genug ist man ja gar nicht am exakten ergebnis interessiert, sondern nur an den niederwertigen bits des ergbnissen, und dann arbeitet man meist mit vorzeichenlosen zahlen. da halte ich es schon für bedeutsam, dass man in jedem falle bedenkenlos imul einsetzen kann, unabhängig davon, ob die höhstwertigen bits der argumente gesetzt sind oder nicht.


Anmelden zum Antworten