18. september 1999 - 21:31Der er
6 kommentarer og 1 løsning
Interrupt
/* - Nedenstående eksempel er kopieret fra TC hjælpen og ændret. Jeg forestillede mig, at man kunne bruge interrupten til at lave et ur, som kørte oppe i hjørnet af skærmen, men den gik ikke. Hverken at lægge koden i selve interrupt-rutinen, eller kalde funktionen ur(). Kan dette ikke lade sig gøre - og hvordan?
- og hvad betyder (...)
- og findes der nogle links til materiale om interrupts? */
Lad os tage det sidste først: (...) betyder at der kommer et "uendeligt" antal parametre - nemlig fordi det er det aktuelle kald til rutinen der bestemmer hvormange parametre der rent faktisk er. Et godt enkesempel på rutine er printf: den tager jo alt fra 1 til (uendelig) mange parametre.
Du har fuldstændig ret i at du ikke kan kalde ur() inde i interrupt-handler rutinen. Interrupts er beregnet til at håndtere "her og nu" afbrydelser, f.eks. at der (igen) er gået 1/60 sek. Det er derfor god latin at interrupt handlere skal være så korte som muligt - og at de aldrig -gentager ALDRIG- må kalde andre dele af dit program. Hvorfor de ikke må det ??? Ja, den primære grund er jo selvfølgelig at rutinen skal kunne nå at afslutte inden den kaldes igen som følge af et nyt interrupt - men timer tick som du bruger i dit ekspempel, altså inden for 1/60 sek. Men mere vigtigt er den logik/kode den genereres når du skrive 'interrupt' foran funktionen, og skriver 'disable()' i starten/'enable()' i slutningen af rutinen. Ordet 'interrupt' for nemlig rutinens entry-kode til som det allerførste, at gemme indholdet at alle CPUens registre. Du skal jo tænke på at interruptet kan komme midt i at du laver noget andet - og maskinen skal jo holde rede på hvor den skal fortsætte. 'disable()' forhindrer i princippet at andre interrupts (herunder også timer tick selv) kommer til førend 'enable()' bliver kaldt. Hvis du derfor skal kalde videre til en anden rutine i samme program, skal den jo i princippet gøre det samme - og det er her det går galt.
Hvis du skal have din ur-funktion til at fungere, skal du derfor lave selv opdateringen af uret selv - ved at skrive direkte til skærmhukommelsen !
Jeg har et eksempel på sådan et ur - skriv igen hvis jeg skal lægge det herud.
Entry-kode er den (maskin-)kode som compileren lægger ind i starten af en funktion, f.eks. til at reservere plads til og initialisere lokale variable, samt at pop'e evt. overførte parametre. Den samme kode laver hvis man bruger ordet 'interrupt' push af alle registre, herunder AX, EP, DS, SS og CS. Tilsvarende indsætter compileren det korrekte antal pop i slutningen af finktionen, sådan at alle registre har samme værdi efter kaldet, som de havde da interrupted blev "fyret" af. (Og programmet afbrudt - deraf navnet interrupt.)
int main(int argc, char* argv[]) { /* Initier egne variable. (Forventer op til 2 params - men ingen er OK. */ if (argc < 2 || (timX = atoi(argv[1])) < 1 || timX > 72) timX = 72; if (argc < 3 || (timY = atoi(argv[2])) < 1 || timY > 24) timY = 24; gettext(timX, timY, timX+8, timY, &curTimStr); curTimStr[4] = curTimStr[10] = ':'; oldtimertick = getvect(TIMERTICK);
/* Flyt timer tick til egen rutine - og start ny DOS skal. Hvis brugeren */ /* skriver 'exit' afsluttes den, og dermed forsvinder også uret. */ setvect(TIMERTICK, timertick);
clrscr(); cprintf("Ur kører i position (X,Y) = (%d,%d)\r\n", timX, timY); cputs("Tryk på en tast for at starte DOS - ESC for at afbryde."); while (!kbhit()); if (getch() != 0x1B) system(getenv("COMSPEC"));
/* Sæt timer tick tilbage til gamle handler - og afslut dette program. */ setvect(TIMERTICK, oldtimertick); return 0; } // MAIN
Man SKAL køre med standard stack frame og UDEN test stack overflow, for at få programmet til at køre. (Og nogle Win95 versioner kløjs i det under alle omstændigheder.)
Tak skal du have. Jeg må nok vente med at kigge nærmere på det til jeg kommer hjem til min compiler:-)
Jeg ved ikke hvad AX, EP osv er, ej heller hvad 'standard stack frame' og 'test stack overflow' er, men det er måske ligeså godt, at jeg selv får læst/lært lidt om de ting, fremfor at blive ved med at stille nye spørgsmål hver eneste gang jeg får et svar!
Så derfor: Hvor/hvordan finder jeg ud af lidt mere (grundigt/grundlæggende) om interrupts?
soepro >> nu har jeg bakset en hel del med dit lille program. Jo, det kan godt køre, men jeg skal da vist ikke prøve på andet end at trykke ESC. Hvis jeg trykker andet, eller ændrer bare en smule i programmet omkring "while(!kbhit());" så går computeren ned.
Du fatter slet ikke hvor mange gange jeg har genstartet min computer. Jeg fandt hurtigt ud af, at det kunne betale sig at starte med en startdiskette, så jeg ikke hver gang skulle vente på at windows startede.
Ud over det, så lader det til at programmet ikke er særlig glad for getch(), kan det være rigtigt?
Og som det sidste. Jeg lavede en lille løkke, som indeholdt en cscanf(). Programmet registrerede kun cirka hvert andet eller tredje tastetryk.
Det duer jo ikke rigtig at det er vældigt smart at lave et ur på den måde, hvis interrupten stort set kører hele tiden!!!
bjarke >> Som jeg skrev, så duer mit prøve program (som stammer fra dengang, jeg kun kørte DOS) ikke med alle Win95 versioner - hvorfor ved jeg ikke.
Mht. while (!kbhit()) løkken, er den jo faktisk helt unødvendig - fjern den. Mht. kaldet til system, har jeg også konstateret at der ikke går godt - men igen jeg ved ikke hvorfor.
Nå, anyway, det virker (selv om jeg egentlig ikke kan bruge det i praksis), så du får pointene. Du fortjener også lidt point med din generelt temmelig grundige besvarelse af spørgsmål:-)
Vær's'go, 30 points!
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.