how to sleep ...
-
Hallo,
ich benötige eine Sleep Funktionalität auf einem 32 Bit Windows-System. Da mits dem IRQ0 so nichts wird, wollte ich den Systemtimer des BIOS verwenden, der alle 55 ms hochgezählt wird.
Allerdings scheitere ich daran im Protected Mode an die entsprechende Speicherstelle zu kommen.
Segment sollte 0x0040 sein und Offset 0x006c. Müsste also an lineare Adresse 0x046c ran.
Weiß jemand wie es geht oder hat eine bessere Idee?
; void cdecl sleep(DWORD dwTime) _TEXT SEGMENT _dwTime$ = 4 ; size = 4 _sleep PROC mov ecx, _dwTime$[esp] ; time (ms) to wait mov ax, cx ; ax = low 2 byte of time shr ecx, 16 mov dx, cx ; dx = high 2 byte of time mov cx, SYSTEM_TIMER_COUNT ; cx = 55 div cx ; ax = result mov cx, ax ; store result in cx push ds ;mov ax, 0040h ; BIOS-Data Area ;mov ds, ax ;mov si, 006Ch ; incremented by 1 every 55 ms ;mov ax, ds:[si] ; get time ;add ax, cx ; add sleep time pop ds break: cmp ds:[esi], eax ; sleep time reached? jna break ret _sleep ENDP _TEXT ENDS
Ich bekomm beim Zugriff immer eine schöne Access Violation
__asm { [asm] push fs mov dx, 0x0040 mov fs, dx mov ax, WORD PTR fs:[0x006c] lea edx, BiosSystemTimer mov WORD PTR [edx], ax pop fs[/asm] } cout << BiosSystemTimer << endl;
-
FrEEzE2046 schrieb:
ich benötige eine Sleep Funktionalität auf einem 32 Bit Windows-System... Weiß jemand wie es geht oder hat eine bessere Idee?
1. Die Segmentregister kannst du nicht ändern.
2. mag bezweifeln, dass das BDA in deinen Prozess gemapt wird - Zugriff wirst du so oder so nie bekommen.
3. dafür gibt’s die WinAPI! -> Sleep() (kernel32.dll). Wenn es etwas genauer sein soll: CreateWaitableTimer+SetWaitableTimer+WaitForSingle/MultipleObject[s]
-
Mir steht die WinAPI aber nicht zur Verfügung, sonst hätte ich nicht versucht Sleep nach zu bilden.
Mir ist klar, dass im Protected Mode über die GDT adressiert wird, jedoch gibt's sowas wie den Virtual 8086 Mode in dem auch Real Mode Programme laufen, die mit Sicherheit die Segmente beeinflussen.
-
FrEEzE2046 schrieb:
Mir steht die WinAPI aber nicht zur Verfügung
warum?
FrEEzE2046 schrieb:
jedoch gibt's sowas wie den Virtual 8086 Mode in dem auch Real Mode Programme laufen, die mit Sicherheit die Segmente beeinflussen.
ja, dann must du aber ein DOS-Programm schreiben, dass dann von der ntvdm ausgeführt wird.
-
FrEEzE2046 schrieb:
Mir steht die WinAPI aber nicht zur Verfügung, sonst hätte ich nicht versucht Sleep nach zu bilden.
auf 'nem 32-bit windows system (wie du schreibst), steht dir die winapi *immer* zur verfügung. es sei denn, du bastelst irgendwelchen kernel-code, dann z.b: http://www.osronline.com/DDKx/kmarch/k105_7epe.htm
-
;fricky schrieb:
auf 'nem 32-bit windows system (wie du schreibst), steht dir die winapi *immer* zur verfügung.
Mir steht die WinAPI nicht zur Verfügung. Glaub mir
"32-Bit Windows System" ist im Bezug auf irgendwelche Bibliotheken hier nicht so ernst zu nehmen.Also geht's gar nicht oder wie? Mir ist schon klar, dass der Zugriff auf die IRQ's (sowie allgemein niedrigere Privileglevel) nicht möglich sein wird. Ich dachte jedoch, dass es irgendeine andere Möglichkeit gibt.
Gut, ich kann die Anzahl der Taktzyklen auslesen (rdtsc), aber das bringt mich in Sachen Zeit nicht viel weiter, wenn ich nicht weiß, wie viel Takte pro Sekunde gemacht werden ...
-
FrEEzE2046 schrieb:
Mir steht die WinAPI nicht zur Verfügung. Glaub mir
"32-Bit Windows System" ist im Bezug auf irgendwelche Bibliotheken hier nicht so ernst zu nehmen.da muss mal einer draus schlau werden...
Wie auch immer ... Wenn man weiß, dass die kernel32.dll (und ntdll.dll) in jeden Prozess geladen wird und schon mal etwas vom PEB [Process Environment Block ] gehört hat, ist es möglich ein Programm ohne jegliche lib zu schreiben. Die Api-Funktionen lokalisiert/lädt man dann während der Laufzeit. (geht nur für Win32)
-
FrEEzE2046 schrieb:
Gut, ich kann die Anzahl der Taktzyklen auslesen (rdtsc), aber das bringt mich in Sachen Zeit nicht viel weiter, wenn ich nicht weiß, wie viel Takte pro Sekunde gemacht werden ...
Du kannst ja Unstetigkeiten im TSC analysieren. Jedes mal, wenn ein IRQ ausgelöst wird, solltest du einen größeren Sprung bemerken können. Über einen hinreichend langen Zeitraum solltest du den Timer von anderen Geräten, die ja auch in regelmäßigen Abständen unterbrechen können, unterscheiden können. Der Timer wird soweit ich weiß auf aktuellen Windows-Systemen immer noch in einer festen Frequenz ausgelöst. (Sowas wie 100 Hz oder so, aber das kann man ja entweder nachlesen, oder in einem Testprogramm feststellen.)
Problematisch wird es, wenn sich die CPU runtertaktet, oder dein Prozess den Kern wechselt. Aber über längere Zeiträume sollte man ersteres auch ausgleichen können, und wenn letzteres am TSC erkennbar ist, ist es korrigierbar, und wenn es nicht erkennbar ist, ist es nicht relevant. Das alles setzt natürlich voraus, dass das System im Kalibrierungszeitraum gleichmäßig und repräsentativ ausgelastet ist. (Und der Timer IRQ mit einer festen Frequenz ausgelöst wird.)
-
Sollten 18.222 Hz sein. Ich überleg mir mal was.
-
Der PIT wird vom BIOS aus historischen Gründen auf 18,2 Hz programmiert. Unter meinem Vista ist der Timer für "normale" Sachen (vermutlich der PIT) auf 64 Hz eingestellt, und der HPET kann auf bis zu 1000 Hz programmiert werden. Ein weiterer Timer ist die RTC, die noch langsamer als der PIT IRQs auslösen kann, aber an der hängt normalerweise nicht der Scheduler.
-
FrEEzE2046 schrieb:
;fricky schrieb:
auf 'nem 32-bit windows system (wie du schreibst), steht dir die winapi *immer* zur verfügung.
Mir steht die WinAPI nicht zur Verfügung. Glaub mir
"32-Bit Windows System" ist im Bezug auf irgendwelche Bibliotheken hier nicht so ernst zu nehmen.gut, wenn du das sagst, dann glaube ich dir. ich will auch garnicht wissen, wie du dein windows abgespeckt hast, so dass die winapi nicht mehr verfügbar ist. *fg*
-
Evtl. koennte man dir gezielter Hinweise geben, wenn du dein Problem genauer beschreiben wuerdest...
Wie auch immer - in einem modernen Multitasking-System bist du mit normalen Anwendungen einfach auf die API des Systems angewiesen. Ansonsten bist du in deinen Moeglichkeiten sehr beschraenkt - im Prinzip kannst du so eigentlich gar nichts produktives tun, da du ohne System-API auch gar keine I/O-Moeglichkeiten hast.
Wenn du also aus irgendeinem Grund dein Windows so versteummelt hast oder irgendwelche fiese Hackerware bastelst, so dass du die WinAPI gar nicht benutzen kannst, bleibt dir im Grunde nur direkte Kernel-Calls unter Umgehung der System-Libs zu benutzen.
Hinweise ueber die grundlegenden Kernel-Funktionen koenntest du entweder aus den Kernel-Sourcen oder Disassemblieren der entsprechenden API-Funktionen erhalten...