News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Buffered Input.[solved]

Started by hungerTom, January 21, 2009, 07:17:49 PM

Previous topic - Next topic

hungerTom

For my current assignment, I need to write a small app, which uses int21 0Ah function, for buffered input.
The Program should take the input, check if it is a valid filename (with optional path+wildcards) and if so display some information (access times etc. to that file).

Now in case you may not remember (which is of course highly unlikely...) I'm the guy 'stuck' with having to write 16bit dos apps, when my system is a 64bit linux type of beast. I was having 'compatibility' problems when using Dosbox seemingly due to a different implementation within dosbox for certain functions.
Since last posting here, I've since switched to using DosEmu, configured to load a 'real' MS-DOS 6.22 for me. Its slow, but up until now its gotten me through.

Now back to my current assignment. I of course had it working (sort of using Dosbox), but it no longer behaved well when using DosEmu (or Win32's cmd-box, which ironically is the 'target-system', as its that what they have installed in their labs at my uni).
So I started to sift through the mess, and finally ended up just rewriting it.
So the first task was to get input, using 0Ah (buffered input). And no matter what I do, it seemingly will not behave.

So my question is: I've searched for this wide and far, I need to see a *working example* of how to use buffered input.
How does my buffer need to be defined? How should I pass the 0Ah function it's offset? And should I be able to 'see' my input when using cv and 'watching' string?

Below is what I've been messing with.The actual functionality within 'find' is of course not present.


.MODEL small
.STACK 100h
.DATA
string  DB  20,20 dup(0)     ; c:\8.3\8.3\8.3\8.3\8.3
.CODE
find   proc
        mov     ah,0Ah             
        ;mov     dx,offset string ; same as below!?
        lea     dx,string
        int     21h
        ret
find   endp
MAIN:
        mov     dx,@data
        mov     ds,dx
        call    find
        mov     ah,4Ch
        int     21h         
END     MAIN
   

sinsi

The buffer's format is

db 20 ;in - maximum length
db ?  ;out - actual length
db ?  ;buffer start

Don't forget that DOS terminates the buffer with 0dh, not 00.
Light travels faster than sound, that's why some people seem bright until you hear them.

FORTRANS

Hi,

   Here is something I put together to answer a question or debug
function 0A calls.  I don't use CV but it works nicely in DEBUG.  You
can zero out the InBuff if that is clearer to you.  I filled it with
numbers and so forth to see it in debug.

HTH,

Steve N.

        PAGE ,132
        TITLE Test DOS Input String
        NAME TESTFN0A

        COMMENT *
2 October 2008, example for MASM Forum question.  (Oops, not for the forum...)
SRN as FORTRANS.

MASM TestFn0A;
LINK TestFn0A;
EXE2BIN TestFn0A.exe TestFn0A.com
*

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CODE    SEGMENT
        ORG     100H ; COM file opening
        ASSUME  CS:CODE,DS:CODE
Start   PROC    FAR

; Initialization
        MOV     AX,CS   ; Save someone from foot shooting if they
        MOV     DS,AX   ; don't EXE2BIN and run the EXE.

; Enter the text
        MOV     DX,OFFSET InBuff; Point to input buffer
        MOV     AH,0AH          ; Input String Function Number
        INT     21H

; Print a message
        MOV     DX,OFFSET Msg1  ; Point to message.
        MOV     AH,9            ; Output String Function Number
        INT     21H

        MOV     DL,InBuff[1]    ; And get the input's length.
        ADD     DL,48           ; Convert to ASCII
        MOV     AH,2            ; Console Output Character Function Number
        INT     21H

        XOR     BH,BH
        MOV     BL,InBuff[1]    ; Get the input's length.
        MOV     InBuff[BX+2],'<' ; Change the carriage return to printable char.

        MOV     DX,OFFSET Msg2
        MOV     AH,9
        INT     21H

        MOV     DX,OFFSET InBuff[2]     ; Point to start of input + debug
        MOV     AH,9            ; Output String Function Number
        INT     21H

        MOV     AX,04C00H ; Exit
        INT     21H

Start   ENDP
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Msg1    DB     13,10,'  The length of the input was $'
Msg2    DB     ' characters,',13,10,'  and the input text looks like: ', 13, 10, '$'
InBuff  DB     9, 0, 13, '23456789$'    ; Input buffer filled with debug stuff.

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CODE    ENDS
        END     Start

hungerTom

Thanks for the replies.
I'm still not 'getting it' though.
I used parts of your example and got it to work, but my understanding is not really clear yet.
Neither has the example translated into working within my app, and I'm still quite certain its down to my incorrect understanding of declaring that input buffer variable.
InBuff  DB     9, 0, 13, '23456789$'    ; Input buffer filled with debug stuff.
Would mean:
Quote9   ;maximum length
0   ;out - actual length
13 ;buffer start
According to your posts. I just don't get that. The '9' is clear, and I assume the '0' gets filled during runtime, but what with the '13'. No matter what I set it to, the example will work. As far as I understand it, this is the third byte, from where on my input should get stored. So why 13 in the example, and why doesn't changing it matter(seemingly) ?
I realise I'm being a dork here, but I've just hit a brick wall which is starting to question my understanding of other things... :(

hungerTom

The questions in my above post are still valid, but I've now cornered where my actual problem lies.
As my InputBuffer will hold a filepath of an obviously unknown length, it is important not to have garbage in it, so it needs to be correctly initialized.

This is what I've currently got, and when outputting it, I get no 'unprintables', but its not clean this way either. I think.
string  DB  50,0,50 dup(' '),'$'

What am I doing wrong.
To make myself more clear. The string would have the CR removed(replaced) and then it would get passed to int21's function 4Eh.
For the function to work, the 'string' would have to be clean, obviously.

MichaelW

The first byte of the buffer must specify the maximum number of characters, including the carriage return, to be copied to the buffer. This allows the function to avoid writing past the end of the buffer. The second byte receives the actual number of characters that the function copied to the buffer, not including the carriage return. The actual buffer starts at the third byte. The function will read characters, echo them to standard output, and copy them to the buffer until a carriage return is read. If the number of characters reaches one less than the maximum, the function will send a beep character to standard output and ignore any further characters, other than a carriage return. As zooba pointed out, the buffer will be terminated with a carriage return. As I see you already realized, if you structure your buffer like this:

buff db 20, 0, 21 dup('$')

Then you can use the Display String function (AH = 9) to display the contents of the buffer on return:

    mov ah, 9
    mov dx, OFFSET buff+2
    int 21h


And to prevent it from displaying over the top of the echoed input, you can define a carriage return / line feed string like this:

crlf   db 13, 10, '$'

And display it before you display the contents of the buffer.

I'm not sure what you mean by "clean".  From the third byte to the carriage return the buffer will contain what the user entered, less any characters that were ignored. So you replace the carriage return with a zero byte and pass the address of the third byte of the buffer, and any remaining problems are bad input.

eschew obfuscation

FORTRANS

Hi,

   Sorry for the confusion, the example posted was for
my use and experimentation.

QuoteAccording to your posts. I just don't get that. The '9' is clear, and I assume the '0' gets filled during runtime, but what with the '13'. No matter what I set it to, the example will work. As far as I understand it, this is the third byte, from where on my input should get stored. So why 13 in the example, and why doesn't changing it matter(seemingly) ?

   The buffer is overwritten with the input, its initial contents
do not matter in that respect.  The 13 is the carriage return
that would occur it there was no additional text entered, and
was for debugging the rest of the code.  For a time I just had
the numbers 1 through 9, and that may have been clearer.


QuoteWhat am I doing wrong.
To make myself more clear. The string would have the CR removed(replaced) and then it would get passed to int21's function 4Eh.
For the function to work, the 'string' would have to be clean, obviously.

   Yes, 4Eh is "Find First File" and requires an ASCIIZ string.
Use the actual length byte (the second byte in the input buffer)
to locate the carriage return, and replace it with a zero.  See
in my example were I "Change the carriage return to printable
char." for something close.

HTH,

Steve N.

hungerTom

Ok, after looking long and hard at what you wrote, an playing with the code some more, I finally got it working.

With 'clean' I meant that I wanted my input buffer to *only* contain what the input function gives it. No stray printables  or worse non-printables, because obviously the 4Eh function would not produce the desired results.

This:
buff db 20, 0, 21 dup('$')
saved me, the ' $ ', to be more precise  :lol

Thanks alot for all your help!   :bg