Re: Kernel mode programming in VC++
- From: Joseph M. Newcomer <newcomer@xxxxxxxxxxxx>
- Date: Fri, 07 Jul 2006 11:01:33 -0400
Note that the code you show below is obsolete and hopelessly useless. It is based on an
invalid premise that you can reprogram the timer chip. This is not even possible within
the kernel, because the timer chip now belongs to the operating system and you must not
touch it. Therefore, you could not use this code, even if you managed to write a device
driver.
I find it amazing that anything in user space could ever depend on a "delay in
microseconds" because the time required to do anything in user space is completely
unpredictable. What happens if your thread were to be preempted or hit time-slice-end in
the middle of this code? You'd have a delay measured in hundreds of milliseconds!
In fact, the entire concept is so completely flawed I find it hard to believe that it
could have made sense in any program other than a program running on a dedicated MS-DOS
machine that had no other I/O happening at the time. Note that a single keystroke in the
middle of this would change the loop behavior.
The whole concept of delays-in-microseconds barely makes sense in Windows; it can be done
in an ISR and almost-but-not-quite works (you could use KeStallExecutionProcessor in a
little root-enum driver, but since it takes an unpredictable number of microseconds to get
into the driver, and the thread can be preempted or time-slice-end while
KeStallExecutionProcessor is running, the whole concept seems pointless. In addition, any
interrupt coming in will change the timing even if you force the thread to dispatch level
during the timing). Between any two instructions in your code, you can be subject to
hundreds of milliseconds of delay, so worrying about microseconds seems to be several
orders of magnitude off from the expected error in any timing. If your program critically
depends upon accurate delays in microseconds, you cannot use Windows, Unix, Linux or Mac
OS X; you need to move your code to a separate processor running an embedded real-time
operating system. Note that it is IMPOSSIBLE to prevent other interrupts from happening,
and it is only barely possible to have a device driver defeat the scheduler, and it can do
this only while in the driver, and for a period not exceeding 25us. Therefore, you have
to put a LOT more smarts into your driver; it has to initiate the operation on the device,
delay for microseconds, and then do the next thing. What you are asking for should be
considered to be effectively impossible in a Windows environment. Of course, you can
continue to program in MS-DOS, but your code won't have a big audience.
joe
On Fri, 7 Jul 2006 12:24:38 +0530, "Arun" <arunkumar.v2@xxxxxxxxxxxx> wrote:
Hello again!Joseph M. Newcomer [MVP]
Thank you for the precious input...
Let me explain the problem.
In my Win32 application, I need to induce a delay in microsecond. I knew
that it is pretty impossible in Windows 'coz of its multi-tasking nature.
While searching some other forum I came to know the only way of doing this
in Windows is to hook into the OS itself.
I picked an assembly routine from the forum, which the author claims as a
microsecond variant of ::sleep()
The intel-compatible code is...
syntax - CALL Pause(uSecs%)
;where uSecs% is the number of microseconds to pause
;Note: Maximum acceptable value is 27,500 microseconds.
; Checking is performed on entry.
.Model Medium,BASIC
.Code
Pause Proc, uSecs:Ptr
push si
mov si,uSecs ;get the address for uSecs%
lodsw ;put the number of microseconds into AX
cmp ax,27500 ;exit if value out of range
ja exit
mov bx,25 ;calculate number of timer
mul bx ; cycles equivalent to the
mov bx,21 ; specified number of
div bx ; microseconds
mov bx,ax ;transfer result to BX
;Disable timer 2.
in al,61h ;clear bit 0 of I/O port 61h
jmp short $+2
and al,0FEh
out 61h,al
jmp short $+2
;Initialize timer 2 for mode 0 operation with word-size initial count.
cli ;disable interrupts
mov al,0B0h ;output control byte
out 43h,al
jmp short $+2
mov al,bl ;send low byte of count
out 42h,al
jmp short $+2 ;tiny delay
mov al,bh ;then the high byte
out 42h,al
jmp short $+2 ;tiny delay
;Reinitialize timer 0 to make sure a time-of-day interrupt doesn't occur.
mov al,36h ;mode 3 with word-size divisor
out 43h,al
jmp short $+2
xor al,al ;set interrupts for every
out 40h,al ; 65,536 cycles
jmp short $+2
out 40h,al
jmp short $+2
sti ;enable interrupts
;Start the countdown by enabling timer 2.
in al,61h ;set bit 0 of I/O port 61h
jmp short $+2
or al,01h
out 61h,al
jmp short $+2
;Loop until the count has reached zero.
readloop:
mov al,80h ;latch timer 2
out 43h,al
jmp short $+2 ;tiny delay
in al,42h ;read count
jmp short $+2 ;tiny delay
mov ah,al
in al,42h
jmp short $+2 ;tiny delay
xchg al,ah
or ax,ax ;loop if count hasn't
jns readloop ; reached zero
Exit:
pop si
Ret ;return to VBASIC
Pause Endp
End
Here, the author claims that this routine can be called from VB. If that is
true, I think that it should also be feasible to call this routine in VC++
using __asm { } block. I didn't try this on VB, but on VC++ it is giving
"Privileged instruction" error.
Is there any way I can call this routine as a Windows application? or
Is there any way I can induce microsecond delay in my Windows application?
It's acceptible for me that to obtain the delay in microsecond the
multi-tasking ability of the Windows needs to be disabled!!! for some
definite interval of time.
Eagerly awaiting for a very positive response :))
Best Regards,
Arun
"Joseph M. Newcomer" <newcomer@xxxxxxxxxxxx> wrote in message
news:hheqa2h8c8cnfovig4gmu2f4086169shk4@xxxxxxxxxx
Forget it. This is not possible. There is no "easy solution" of the kindyou are hoping
for. You will need to write a device driver, which has to be written inpure C, and which
follows complex rules unrelated to what applications do. You will have torewrite your
code to open the device driver.to; a device
Note that you can't "encapsulate the code" as you think you might be able
driver follows a massive number of very specific and critical rules andyou can't just
throw code at it.it calls the
By the way, a device driver does not issue IN and OUT instructions either;
Hal functions READ_PORT_xxx and WRITE_PORT_xxx where xxx is UCHAR, USHORT,or ULONG.
joewrote:
On Thu, 6 Jul 2006 20:34:41 +0530, "Arun" <arunkumar.v2@xxxxxxxxxxxx>
out,
Hello Experts,
I have an asm routine which uses privileged instructions like in,
Usercli, etc., I need to execute this as a Win32 application under VC++.
Since the instructions are privileged, I can't execute the same under
&mode as a normal Win32 application, so I have to execute this routine in
kernel mode.
One solution is to encapsulte the routine as a Device driver for Windows
call the same from the application, but, I am looking out for a easyJoseph M. Newcomer [MVP]
solution. Please help...
Thank you.
Regards,
Arun
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.
- References:
- Kernel mode programming in VC++
- From: Arun
- Re: Kernel mode programming in VC++
- From: Joseph M . Newcomer
- Re: Kernel mode programming in VC++
- From: Arun
- Kernel mode programming in VC++
- Prev by Date: Re: how to call drawitem() function in ower draw Clistbox
- Next by Date: Question about CSocket::Receive()
- Previous by thread: Re: Kernel mode programming in VC++
- Next by thread: Re: HexaDecimal format with Cstring
- Index(es):
Relevant Pages
|