Domanda:
Scopo di OR EAX, 0xFFFFFFFF
user3097712
2014-06-14 00:03:42 UTC
view on stackexchange narkive permalink

Ho letto la catena di montaggio

  OR EAX, 0xFFFFFFFF  

e nel registro EAX il programma ha memorizzato una stringa. Ho problemi a capire come possiamo fare un confronto con una stringa e un valore del genere. Dopo aver eseguito tale istruzione, EAX ha il valore 0xFFFFFFFF .

Qualcuno può dirmi quale scopo ha quell'operazione? È una riga che compare spesso in un codice assembly? (ad esempio la riga XOR EAX, EAX che è un modo efficiente per creare EAX = 0 ? È qualcosa del genere?)

avrebbe potuto essere fatto per influenzare i flag. Le istruzioni per lo spostamento dei dati generalmente non influiscono sui flag
Tre risposte:
Peter Andersson
2014-06-14 00:36:11 UTC
view on stackexchange narkive permalink

Penso che per capire perché il compilatore fa questo, studia il seguente disassemblaggio:

  B8 FF FF FF FF mov eax, 0FFFFFFFFh83 C8 FF o eax, 0FFFFFFFFh  

Ciò che il compilatore sta cercando di ottenere è probabilmente di impostare il registro eax su -1 usando il minor numero di byte possibile per essere adatto alla cache. OR ha anche circa il doppio della velocità effettiva dell'istruzione MOV a patto che non ti dispiaccia rovinare i flag.

Questa è probabilmente una variabile inizializzata a -1.

È abbastanza comune usare -1 per indicare un errore o qualche altro valore riservato speciale se 0 è considerato un valore valido nell'intervallo. Sto speculando ovviamente.
Poiché le stringhe menzionate dall'OP, è anche possibile che sia coinvolto `strcmp` o i suoi fratelli, e -1 potrebbe essere un normale valore restituito in quel caso. Ma sono d'accordo, è impossibile dare una risposta non speculativa a "* perché *" senza vedere quale input genera questo risultato e come quel risultato viene utilizzato più avanti nel codice.
@DCoder molto vero. Potrebbe essere un valore restituito completamente normale da una funzione di confronto con -1 (<0) come minore, 0 come uguale e 1 (> 0) come maggiore, il che non sarebbe raro.
@user3097712 `-1` è espresso come` 0xFFFFFFFF` (tutti i bit impostati) in un modo a 2 complementi.
* "OR ha anche circa il doppio della velocità effettiva dell'istruzione MOV fintanto che non ti dispiace rovinare i flag." * Beh, no, non è vero. Per quanto riguarda la CPU, `o eax, -1` dipende dal valore precedente del registro` eax`, che allunga la catena di dipendenze del codice e diminuirà significativamente le prestazioni rispetto a se avessi usato un `mov`. * C'è * una riduzione della dimensione del codice, come hai dimostrato, ma c'è una riduzione della velocità molto significativa. Non vale quasi mai i 2 byte. (Sì, i chip * potrebbero * plausibilmente un caso speciale di un OR con tutti i bit impostati, ma non lo fanno.)
@PeterAndersson dovresti davvero aggiungere quella nota di glglgl nella risposta. Ad esempio, FORTH usa -1 per riferirsi a true. Mi aiuta pensare a questa ottimizzazione come un modo rapido per impostare tutti i bit su 1.
Ian Cook
2014-06-17 00:19:12 UTC
view on stackexchange narkive permalink

Mi spiace, non posso postarlo come commento ma un paio di test rapidi (e non esaustivi) mostrano quanto segue:

  • gcc (4.6.3) usa o invece di mov durante l'ottimizzazione per le dimensioni ( / Os )
  • msvc (13) utilizza o invece di mov qualunque sia l'impostazione di ottimizzazione (inclusa disabilitata)
  • clang (3.0) usa mov qualunque sia l'impostazione di ottimizzazione

Il comportamento di gcc, in particolare, supporta la risposta di Peter Andersson.

Grazie! Non avevo pensato di usare "/ Os" con gcc, ma ovviamente ha perfettamente senso.
Risultati sorprendenti: [MSVC CL19 emette "or" con "/ O2" ma "mov" con "/ Os". ICC 17 e Clang 4.0 usano `xor eax, eax, dec eax` durante l'ottimizzazione per le dimensioni] (https://godbolt.org/g/H1rDWO)
@LưuVĩnhPhúc La sorpresa è perché `/ Os` (come suo cugino,` / Ot`) deve essere combinato con `/ Og` per abilitare l'ottimizzazione in MSVC. Altrimenti, viene completamente ignorato. :-) E il tuo esempio non è un banco di prova particolarmente valido. In circostanze normali, quando è necessario -1 in un registro all'interno di un blocco di codice più grande, "/ O1" farà sì che MSVC emetta un "OR", mentre "/ O2" farà sì che MSVC emetta un "MOV". Posso solo presumere che usi sempre "OR" qui perché non è preoccupato per alcun tipo di dipendenza dei dati da "EAX" che rallenta le prestazioni, considerando il relativo overhead di una chiamata di funzione.
Edward
2014-06-14 00:08:56 UTC
view on stackexchange narkive permalink

Ciò risulterà sempre nell'impostare il registro EAX uguale a 0xFFFFFFFF e avrà anche l'effetto collaterale di impostare i flag in modo appropriato (ovvero N = 1, Z = 0, ecc.). Non è un idioma comune.

Qual è il flag `N` (sono previsti Carry, Overflow, Zero, ecc., Ma cosa rappresenta N)?
"... non è un linguaggio comune" - in realtà è abbastanza comune, specialmente nei vecchi software. L'istruzione "OR" è più piccola dell'istruzione "MOV". Una macchina con 640K o 1MB o memoria necessitava del risparmio (sì, risale a tanto). E "XOR" era (ed è tuttora) usato per azzerare un registro per lo stesso motivo.
@jww: Spiacenti, lavoro con molti processori diversi. Intendevo SF (sign flag) che è come lo chiama Intel; altri produttori lo chiamano N per negativo. Potrebbe essere utile all'OP se potessi specificare i compilatori che generano quella sequenza. Nessuno di quelli che ho a portata di mano lo fa.
@jww: grazie per la tua spiegazione. Non sapevo il fatto che OR fosse più piccolo di MOV. Adesso lo so. Grazie! Da questo intervento ho imparato molto.


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...