2009-05-15 25 views
7

Ho un vecchio codice scritto in C per 16 bit usando Borland C++ che passa da stack multipli, usando longjmps. Crea un nuovo stack eseguendo un malloc e quindi impostando i registri SS e SP sul segmento e l'offset, rispettivamente, dell'indirizzo dell'area malloc'd, utilizzando Assembler in linea. Mi piacerebbe convertirlo in Win32, e sembra che le due istruzioni dovrebbero essere sostituite da una singola impostazione ESP. Le due istruzioni erano circondate da una coppia CLI/STI, ma in Win32 queste forniscono "istruzioni privilegiate", quindi le ho tagliate per ora. Sono un vero innocente quando si tratta di Windows, quindi sono rimasto piuttosto sorpreso dal fatto che il mio primo test abbia funzionato! Quindi, la mia domanda piuttosto vaga è quella di chiedere agli esperti qui se quello che sto facendo è un) troppo pericoloso per continuare, o b) funzionerà se aggiungo del codice, prendo certe precauzioni, ecc.? Se quest'ultimo, cosa dovrebbe essere aggiunto, e dove posso scoprirlo? Devo preoccuparmi di altri registri, come SS, EBX, ecc.? Sto usando l'ottimizzazione no ... Grazie per i suggerimenti che mi possono dare le persone.Commutazione di stack in C++

+1

Wow, questa è una domanda molto interessante! Non sono esattamente un professionista di C++ a 16 bit, quindi mi chiedo perché scambiate gli stack? –

+1

Dato che è un vecchio codice a 16 bit, direi che si tratta di una sorta di implementazione di fibra homebrew. Conosco un paio di videogiochi per console che hanno fatto qualcosa del genere perché i thread offerti dal sistema erano molto pesanti. – Charlie

+0

Sì, come un certo numero di eccellenti risposte individuate, è (era) un'implementazione di fibra homebrew - la mia prima implementazione di programmazione basata sul flusso su un PC. La versione a 16 bit è stata effettivamente utilizzata per il lavoro di produzione in una grande azienda statunitense. Non mi sono reso conto che Win32 ha un'implementazione di fibre - leggerò l'articolo citato da Greg Hewgill. Grazie a tutti voi! –

risposta

9

La rimozione di CLI/STI funziona ancora a causa delle differenze nell'ambiente operativo.

Su DOS a 16 bit, potrebbe verificarsi un interrupt e questo interrupt inizialmente sarebbe in esecuzione sullo stesso stack. Se ti sei interrotto nel bel mezzo dell'operazione, l'interrupt potrebbe bloccarsi perché hai aggiornato solo ss e non sp.

Su Windows e qualsiasi altro ambiente moderno, ogni thread in modalità utente ottiene il proprio stack. Se il tuo thread viene interrotto per qualsiasi motivo, lo stack e il contesto vengono preservati in modo sicuro - non devi preoccuparti di qualcos'altro che sta girando sul tuo thread e sul tuo stack. cli/sti in questo caso proteggerebbe contro qualcosa che sei già protetto dal sistema operativo.

Come ha detto Greg, il modo sicuro e supportato per scambiare pile come questa su Windows è CreateFiber/SwitchToFiber. Questo ha l'effetto collaterale di cambiare l'intero contesto, quindi non è come cambiare lo stack.

Questo solleva davvero la domanda su cosa vuoi fare. Un sacco di volte, cambiare stack è quello di ottenere dallo stack limitato, che era 64k su DOS a 16 bit. Su Windows, hai uno stack da 1 MB e puoi allocarlo ancora più grande. Perché stai cercando di cambiare stack?

+0

Questa è stata la mia prima implementazione della programmazione basata sul flusso su un PC. Non mi sono reso conto che Win32 ha un'implementazione di fibre, ma potrebbe essere un grosso problema convertire il mio codice in Fibre: certamente leggerò l'articolo citato da Greg Hewgill. Grazie a tutti voi! –

5

Il modo più sicuro per eseguire questa operazione consiste nel trasferire il codice nelle strutture multiprogrammazione Win32 ufficiali, ad esempio thread o fibre. Fibers forniscono un paradigma multistrato molto leggero che sembra adatto alla tua applicazione.

L'articolo Why does Win32 even have fibers? è anche una lettura interessante.

+0

Uno dei post di questo articolo dice "cambierà la base dello stack, ma non aggiornerà il limite dello stack, o non cambierà l'elenco di gestori di eccezioni, o dimenticherà di scambiare lo stato di FP". Supponendo che le fibre prendano cura di queste cose per me, posso fare longjmps tra le fibre? Se volessi prendermi cura di loro personalmente, quanto sono complessi e dove posso scoprirli? Grazie. –

+1

Nella mia risposta sono già collegato alla documentazione MSDN sulle fibre. C'è una funzione completa di riferimento lì, che dovrebbe rispondere alla maggior parte delle tue domande. Nota che non penso che dovresti provare a "longjmp tra fibre", ma invece usare le funzioni ufficiali come SwitchToFiber. –

+0

Grazie, Greg. La documentazione sembrava un po 'offuscata, ma inizierò a scavare dentro. –

0

Ho fatto questo in modalità utente, e sembra non avere problemi. Non hai bisogno di cli/sti, queste istruzioni si limitano a prevenire interruzioni a quel punto nel codice, che non dovrebbe essere necessario per le informazioni limitate che ci hai comunicato.

0

Dai un'occhiata a Mtasker di Bert Hubert. Fa un semplice multitasking cooperativo, potrebbe essere facile per te usarlo per effettuare il porting del tuo codice.

0

Non dimenticare che gli stack di salto filtreranno qualsiasi argomento o variabile residente nello stack.