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...


Anmelden zum Antworten