From: Frank Kotler on
carlos wrote:
> Hello, I'm trying to make a little program that do the following:
>
> Check if a key was pressed. If so, return the ascii value of the key.
> Otherwise, returns 0.

Hi again Carlos,

Due to some wind, the power went out, so I took the opportunity to boot
to dos and refresh my memory. Your program does what you say... since no
key has been pressed, it returns zero.

> I made this code, but I'm can't capturing the ascii value of the
> arrows.

.... or any other ascii value, that I can see...

> org 100h
>
> mov ah, 11h
> int 16h
> je pre_quit

Since no key has been pressed, this goes right to "pre_quit" and returns
zero, as described. The rest of it never gets to run. This probably
isn't what you really want to do.

> mov ah,8h
> int 21h
> cmp al,0 ; if not extended key
> jnz quit
> int 21h
> jmp quit

This would work, if it got to run.

> pre_quit:
> mov al,0
> quit:
> mov ah,4ch
> int 21h

Rod gave an example of this using ah=6 instead of 8 - which is not the
problem, I don't think. Steve gave an example with int 16h/0 - int
16h/10h is the same thing, but for "103-key" keyboards, it catches a few
"exotic" keys that int 16h/0 misses. Here's still another example...
using int 21h/7 (same as int 21h/8, but it ignores control-c... so we
can see its code). This prints out a hex value and goes back for more
(hit "ESC" to quit).

Best,
Frank


; nasm -f bin -o wotkey.com wotkey.asm

org 100h

top:
mov ah, 7 ; no echo - change to 1 if you want
int 21h ; get a key

call byte2ha ; show it
or al, al ; if it was 0
jz top ; call again
call newline
cmp al, 1Bh ; was it escape?
jnz top ; no? do more.
ret
;---------------------------

;------------------------
; thanks Ben
; thanks TAD
byte2ha:
push ax
aam 16 ; 2
hex:
xchg ah,al ; 2
cmp al,0Ah ; 2
sbb al,69h ; 2
das ; 1
int 29h
mov al,89h ; 2 (thanks Ruud)
jc short hex ; 2
pop ax
ret
;------------------------

;----------------------
newline:
push ax
mov al, 13
int 29h
mov al, 10
int 29h
pop ax
ret
;-------------------

From: Rod Pemberton on
"Frank Kotler" <fbkotler(a)myfairpoint.net> wrote in message
news:hervvv$jde$2(a)aioe.org...
>
> Rod gave an example of this using ah=6 instead of 8

RBIL doesn't document that 8h returns extended. That may be reason enough
to avoid 8h. But, I rechecked. 8h does return extended, at least for arrow
keys, on this machine.

> - which is not the
> problem, I don't think.

I think the real problem was that he had no keypresses in the keyboard input
buffer and no wait for a keypress... He was missing a loop on ZF for a
wait, or he needed to fill the keyboard buffer.


Rod Pemberton


From: carlos on
Thanks for the help.
I think it's impossible to do what I want with 16-bit assembler.
In the end I did but at c using the Windows API calling to functions
_kbhit and _getch of msvcrt.dll
If anyone thinks that can be done with 16-bit assembler, please show
me how to.

This is c source code:
int main()
{
int c = 0;
if (_kbhit()) //if key was pressed.
{
c = _getch(); //get key
if (c == 0 || c == 0xE0) //if is extended key
{
c = _getch();//get extended key
}
}
return c;//return 0 o value of key.
}

From: Rod Pemberton on
"carlos" <cmontiers(a)gmail.com> wrote in message
news:9a32662f-d83b-46f6-9ebf-2bc788ffcf49(a)d21g2000yqn.googlegroups.com...
> ... with 16-bit assembler.

When you asked for 16-bit assembler, you're asking for an environment that
supports 16-bit x86 cpu mode. These are real-mode DOS, v86 mode emulated
DOS environments like a Windows "console" application (or dosbox) or DOS
running under Linux's DOSEMU, DOSBox application, or your own 16-bit
bootloader or a 16-bit operating system, etc. If you used a DOS compiler,
e.g., DJGPP, you could see what BIOS and DOS function calls are used.

> If anyone thinks [example C code] can be done with 16-bit assembler,
> please show me how to.

We already showed you that.

*Where* are you trying to use the 16-bit code? By "where", I mean what OS,
what cpu mode, what environment? You can only use it in 16-bit mode, on
x86, in an environment that supports 16-bit x86 cpu mode.

You can't be asking for 16-bit code that works with an existing modern OS
like Windows 7, Vista, XP or Linux. These OSes limit or prohibit use of
16-bit code, like BIOS calls, and don't support DOS calls. Supposedly, x86
64-bit mode doesn't support 16-bit code natively, so a 64-bit OS might not
have support for 16-bit mode.

> In the end I did but at c using the Windows API calling to functions
> _kbhit and _getch of msvcrt.dll

You can't use DOS and BIOS calls in pure Windows. You can use DOS and BIOS
calls in real-mode DOS or a Windows "console" application (or dosbox). A
Windows "console" is supported in Windows 95, 98, SE, ME, NT, 2K. AFAIK, a
Windows "console" is *not* supported in Windows 7 or Vista. Windows XP
"console" has limited support.

> ... Windows API ... msvcrt.dll

It seems you're using a Windows C compiler which calls Windows C functions.
It's very likely Windows functions are *not* using BIOS or DOS. You might
be able to produce Windows "console" applications with your Windows C
compiler, but these won't use DOS or BIOS calls either. The last version
that supported DOS was MSVC 1.52c. This version hasn't been available for
many years.

> int main()
> {
> int c = 0;
> if (_kbhit()) //if key was pressed.
> {
> c = _getch(); //get key
> if (c == 0 || c == 0xE0) //if is extended key
> {
> c = _getch();//get extended key
> }
> }
> return c;//return 0 o value of key.
> }

DJGPP (a DOS compiler using GCC and custom C library) calls:

bioskey() - int 16h, ah=00h, 01h, 02h, 10h, 11h, or 12h

kbhit() - int 16h, ah=11h - after comparing memory 40:1Ah (pointer to first
character in BIOS keyboard buffer) and 40:1Ch (pointer to first free
character slot in BIOS keyboard buffer)

getch() - int 21h, ax=0700h *or* buffered character - after checking isatty
and line buffering on stdout & stderr and flushing output

You could also look at the OpenWatcom code for the DOS versions of these
functions. OW will also have Windows versions.

> This is c source code:

I understand what the C code you posted is supposed to do. It does what I
expect.

But, I want you to explain to me what this actually does do with your
compiler. Did you run it? Does it immediately exit? Does it ever return a
letter or extended key?

You posted C code to demonstrate the issue. But, it's unlikely I'm using
the same C compiler in the same environment. So, I may be experiencing
different results. E.g., I'm not using a Windows C compiler. Functions
like getch, kbhit, bioskey, are non-portable and can be implemented
differently from compiler to compiler.

When I change _kbhit() and _getch() to kbhit() and getch() and compile with
*multiple* DOS compilers, this has the exact same problem as your assembly
code in real mode DOS and Windows "console". There are *NO* keys in the
keyboard buffer. There is *NO* wait for someone to press a key to put a key
in the keyboard buffer. This causes the code to immediately exit because
if(kbhit()) fails (is false). You can wrap the if(_kbhit()) in a while(1)
loop, adding a break statement inside to get it to wait for a keypress.


Rod Pemberton


From: Frank Kotler on
carlos wrote:
> Thanks for the help.
> I think it's impossible to do what I want with 16-bit assembler.

Horsefeathers! As Rod points out, your OS may not support 16-bit code,
but that's not your code's fault. ( http://www.dosbox.com/ may help?)

> In the end I did but at c using the Windows API calling to functions
> _kbhit and _getch of msvcrt.dll

Sure. But that's 32-bit code (or 64-bit code, perhaps?). (we can do this
in asm, too, of course!)

> If anyone thinks that can be done with 16-bit assembler, please show
> me how to.

Something like...

org 100h

mov ah, 11h
int 16h
je pre_quit

mov ah,8h
int 21h
cmp al,0 ; if not extended key
jnz quit
int 21h
jmp quit

pre_quit:
mov al,0
quit:
mov ah,4ch
int 21h

Oh, wait! That's your original code! In what way does it not do what you
want?

> This is c source code:
> int main()
> {
> int c = 0;
> if (_kbhit()) //if key was pressed.
> {
> c = _getch(); //get key
> if (c == 0 || c == 0xE0) //if is extended key

Anyone ever actually seen 0xE0 at this level? I don't recall.

> {
> c = _getch();//get extended key
> }
> }
> return c;//return 0 o value of key.
> }

Or, put another way, what does an executable made from this C code do
different from your asm code?

What does (either program) do if you feed it some input - "myprog<some.txt"?

Do you have a convenient way to see the return value in dos? IIRC, we
need to run the thing from a batch file and check "errorlevel". PITA.
(in Linux, we can do "echo $?" to see the exit code from the last
program!) We could arrange to "instrument" your code so you could more
easily see what it's doing, if that would help...

What might be more "useful" is to wrap the first three lines of your
code in a "timer" so we could "return zero if no key is hit within ten
seconds" or something...

Honestly, Carlos, I don't see anything wrong with your original code...
except that it isn't very useful to return zero immediately if^H^H since
no key is hit...

Best,
Frank