Domanda

Da quello che ho letto, sembra che ci siano 9 bandiere diverse. È possibile leggerli / modificarli direttamente? So di poter sapere, ad esempio, se il flag zero è impostato dopo aver eseguito un'istruzione cmp / jmp, ma sto chiedendo se è possibile fare qualcosa del genere

mov eax, flags

o qualcosa del genere.

Inoltre, per la scrittura, è possibile impostarli a mano?

È stato utile?

Soluzione

Alcuni flag possono essere impostati o cancellati direttamente con istruzioni specifiche:

  • CLC , STC e CMC : cancella, imposta e completa la bandiera carry
  • CLI e STI : cancella e imposta il flag di interrupt (che dovrebbe essere fatto atomicamente)
  • CLD e STD : cancella e imposta il flag di direzione

Per leggere e scrivere il segno, zero, carry ausiliario, parità e carry flag, è possibile utilizzare LAHF per caricare gli 8 bit inferiori (quei 5 flag più 3 bit indeterminati) nel registro AH, e puoi usare SAHF per memorizzare quei valori da AH nel registro delle bandiere.

Puoi anche usare l'istruzione PUSHF per spingere i flag nello stack, leggerli e modificarli nello stack, quindi utilizzare il POPF 1 istruzioni per memorizzarli nel registro delle bandiere.

Nota che non puoi impostare i flag VM e RF con POPF: mantengono i loro valori precedenti. Allo stesso modo, è possibile modificare il livello di privilegio I / O solo quando si esegue a livello di privilegio 0 e il flag di interruzione può essere modificato solo quando si esegue a un livello di privilegio almeno il privilegio del livello di privilegio I / O.


Nota 1:

Nota che popf è piuttosto lento nelle CPU moderne; consulta la Guida all'ottimizzazione di Agner Fog e le tabelle di istruzioni. È microcodificato perché in modalità kernel è in grado di modificare il livello di privilegio IF e AC e IO. Subiamo la penalità indipendentemente dalla modalità sulle attuali CPU perché i decodificatori non sono sensibili alla modalità.

Se possibile, usa lahf / sahf invece di pushf / popf per le prestazioni, o salva un singolo flag che ti interessa come setc al , poi aggiungi al, 255 a impostare CF = (AL! = 0) . Oppure setnc al / sub al, 1 o altro. Anche le sequenze per impostare o cancellare SF o OF in base a un registro 0 o 1 sono semplici, con / senza invertire la bandiera.

Altri suggerimenti

Puoi usare le istruzioni pushf e popf che spingeranno le bandiere nello stack, puoi modificarle e poi rimuoverle.

Se hai bisogno solo del byte inferiore del registro flag (che contiene SF, ZF, AF, PF, CF), allora c'è l'istruzione dispari ma conveniente LAHF (ah ah), che carica gli 8 bit inferiori del le bandiere si registrano in AH e la sua controparte SAHF per memorizzare AH in bandiere.

Per lo specifico flag carry, x86 offre CLC, STC e CMC, rispettivamente per cancellare, impostare e integrare il flag carry.

Il modo più semplice è usare pushf / popf .

Se vuoi spostare eflags in eax , usa il codice qui sotto.

pushf                  # push eflags into stack
pop %eax               # pop it into %eax
scroll top