Hi there,
I had a look at \masm32\m32lib\wait_key.asm and I wonder for what purpose the crt__kbhit loop is used. The function crt__getch waits for a keystroke already and I see no change with or without the loop.
viele grüße
ralph
that's a good question, Ralph :bg
Warum einfach wenn's auch umständlich geht :bg
I think the kbhit loop was an attempt to limit the CPU utilization while waiting, based on the apparently incorrect (as tested under Windows 2000) assumption that getch would not limit the CPU utilization. Perhaps earlier versions of MSVCRT do not.
If this is the version you are talking about,
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
wait_key proc
invoke FlushConsoleInputBuffer, rv(GetStdHandle,STD_INPUT_HANDLE)
@@:
invoke Sleep, 1
call crt__kbhit
test eax, eax
jz @B
call crt__getch ; recover the character in the keyboard
; buffer and return it in EAX
ret
wait_key endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
Its actually a "Sleep" API loop to ensure the idle loop yields while waiting for a keystroke.
now, if we could only come up with a 16-bit version that wasn't a CPU hog :P
if you let NTVDM wait for a key - no problem
but if you try to do other stuff, there is no way to block execution
In 16-bit code calling the MS-DOS Idle Handler from the wait loop might be worth a try. I seem to recall testing this at some point, under NTVDM I think, but I don't recall what the results were.
Quote from: hutch-- on April 28, 2012, 02:25:36 AM
Its actually a "Sleep" API loop to ensure the idle loop yields while waiting for a keystroke.
What the OP and Michael indicate is that crt__getch does yield even without the loop. And indeed the CPU stays put at 0% while waiting for the keystroke, so we can send the loop into retirement :wink
Quote from: MichaelW on April 28, 2012, 06:05:13 AM
In 16-bit code calling the MS-DOS Idle Handler from the wait loop might be worth a try. I seem
to recall testing this at some point, under NTVDM I think, but I don't recall what the results were.
any idea how to do that ?
i didn't know there was such a thing
Dave if you remember when I was having problems with that text adventure you came up with the idea of using crt__kbhit to check whether a keypress was in the keyboard buffer, if there was then use crt__getch to extract the key value, otherwise carry on with other code before looping back to check crt__kbhit again.
Dave,
To call the Idle Handler you simply issue an Interrupt 28h. The Microsoft MS-DOS Programmer's Reference, version 5, recommends also issuing an MS-DOS Idle Call (Interrupt 2Fh, Function 1680h).
thanks, Michael :U
Neil - yah - that is a valid use of crt__kbhit - we wanted to do something else if the keyboard was idle
but - we need something similar for 16-bit programs
it's really easy to write a CPU hog in 16-bit
For 16 bit programs this is what I used :-
PUSH ES ;Save segment.
SUB AX,AX ;Get bottom
MOV ES,AX ;of memory.
MOV AL,ES:[041A] ;Get head pointer.
MOV AH,ES:[041C] ;Get tail pointer.
POP ES ;Restore segment.
CMP AH,AL ;Are they equal ?
JNE GETKEY ;No, get keyboard input.
Do other code then Loop again
again: mov ah,1
int 16h
jnz gotkey
int 28h
jmp again
gotkey:
For running DOS in a VM I setup a new int 28h
int28: sti
hlt
jmp old28
CPU usage afterward is 0 instead of one core.
Running this code under NTVDM, only the MS-DOS Idle Call (Interrupt 2Fh, Function 1680h) drops the NTVDM CPU usage to 0. The other attempts left the usage at 99%.
.model small
.386
.stack
.data
.code
.startup
@@:
;hlt
;int 28h
mov ax, 1680h
int 2Fh
jmp @B
.exit
end
yah - did some reading
you have to install your own INT 28h handler - something like sinsi did - it is initially just an IRET
the multiplex interrupt might be the way to go - provided the OS is recent enough to support it
Quote from: dedndave on April 29, 2012, 06:24:00 PM
yah - did some reading
you have to install your own INT 28h handler - something like sinsi did - it is initially just an IRET
the multiplex interrupt might be the way to go - provided the OS is recent enough to support it
Hi,
Int 28H and Int 2FH were introduced in MS-DOS 2.0 to support
the PRINT command. That was to allow PRINT to operate in the
background. To limit CPU usage in some of my code I use something
similar to what sinsi posted. I just put a HLT in the test for a key
loop. That was done to reduce power usage on the HP 200LX
palmtop.
Regards,
Steve N.
Running on a P3, HLT in a loop had no apprent effect under NTVDM.
yah - that's what i was afraid of :P
NTVDM probably ignores HLT instructions altogether
Hi,
Well a quick test of HLT shows no effect with a Win2k NTVDM
or an OS/2 VDM on my P-III. Using the graphical CPU meters
of each. Got a way to measure CPU usage under plain DOS?
With the MS-DOS 5.0 on the 200LX I used an amp meter.
But I can't find what the actual numbers were anymore...
Regards,
Steve N.
Illuminate me here, with a non-re-entrant OS like MS-DOS, what is the point of looking for a wait instruction/sequence/interrupt when only one task is running ? Surely you just shove a test in the polling loop for something like a keystroke or mouse event (if I vagely remember int 33h correctly) and let the processor ping its heart out ?
From the Intel docs
QuoteThe HLT instruction is a privileged instruction. When the processor is running in
protected or virtual-8086 mode, the privilege level of a program or procedure must
be 0 to execute the HLT instruction.
Makes sense I suppose. You don't want a DOS program to halt everything, especially in a single CPU case...
as i remember, it didn't actually halt anything under DOS, either - lol
the first hardware interrupt that came along caused execution to continue
when you issued a HLT instruction on a 4004 or 8008, the world stopped spinning :P
>the first hardware interrupt that came along caused execution to continue
That's the point. This is how you nowadays stop a core that's not needed.
The BSP will send an interrupt to the AP when needed and off it goes.
Quote from: hutch-- on April 30, 2012, 01:19:07 PM
Illuminate me here, with a non-re-entrant OS like MS-DOS, what is the point of looking for a wait instruction/sequence/interrupt when only one task is running ? Surely you just shove a test in the polling loop for something like a keystroke or mouse event (if I vagely remember int 33h correctly) and let the processor ping its heart out ?
Hi,
Well in this case, the HP 200LX is a palmtop that can be running
on 2 AA batteries. So reducing CPU usage prolongs the time between
chargings.
Thanks for the Intel quote sinsi. Makes some sense. Though the
PM OS should process the exception. But it could possibly wait before
returning to the RM/V86 program. Seems that these don't.
Regards,
Steve N.
>Though the PM OS should process the exception.
"Processes it" as in "ignores it" I guess. It does throw an exception.
For those running heavily overclocked Pentiums under DOS, it might be useful to keep the CPU from frying, while waiting at maximum speed :toothy
Come to think of it, when I used to routinely run DOS apps I sometimes had problems with the NTVDM CPU usage being so high that everything else slowed to a crawl. Periodic calls to the MS-DOS Idle Call function could have solved this problem, and done right, with no perceptible effect on the speed of the DOS app.