How to read a character from the keyboard and save

2019-05-21 18:49发布

问题:

I'm creating the file with the 3Ch function and saving character with the 40h function (I read about it here)

I don't understand how to put read character in DS:DX.

Here is my code:

org 100h
bits 16

section .data
    file DB 'file.txt',0

section .bss
    file_handle resw 1

; CREATE FILE
section .text
    mov DX, file 
    mov CX, 0000h
    mov AH, 3Ch
    int 21h

; START INPUT
INPUTSTART:
    mov AH,01h
    int 21h

    ; SAVE INPUT TO FILE
    mov SI, file_handle
    mov BX, [SI]
    mov CX, 0001h
    mov AH, 40h
    int 21h

   jmp INPUTSTART

    mov AH,4Ch
    int 21h

As you see program is intended to work in loop and write as many charcter as user type. Please help with getting file handle for 40h function and putting data in DS:DX.

回答1:

Based on the syntax of the code, I'm guessing you're using NASM and trying to create a .COM program.

.COM programs' code begins at the very beginning of the file and there isn't any division of the file into logical sections either, so you cannot put a data section (e.g. .data or .bss) first and it doesn't make much sense to even define such sections.

So, your code should look like:

org 100h
bits 16

; code begins here
; then goes data

OR

org 100h
bits 16

jmp start
; here goes data
start:
; here goes the rest of code

Next, function 3Ch returns a file handle in AX. You use this handle to perform further operations on the file (e.g. read, write, close). Your code is not stashing this handle away in file_handle, which I'm guessing is defined exactly for that purpose, and it's trashing it by overwriting the value of AX with mov AH,01h. You need to fix this.

At the end of the program you must close the file using function 3Eh. If you don't, the file may end up containing only a portion of the data that has been written to it, the file may become inaccessible until you reboot the PC and you may also lose the ability to open (or create) more files if you have accumulated enough unclosed file handles. So, close the file at the end.

As for saving the character in the file, nothing prevents you from defining a byte variable, say key, storing AL into it and then passing the address of key to function 40h, e.g.:

...
mov AH,01h
int 21h
mov [key], AL

; SAVE INPUT TO FILE
mov BX, [file_handle]
mov DX, key
mov CX, 0001h
mov AH, 40h
int 21h
...
file_handle dw 0
key db 0
...

Also, don't forget to designate some key for breaking out of the infinite loop that you're having in the program right now.



回答2:

Actually you don't put the character in ds:dx, but rather you use ds:dx to refer to the memory address where the character or whatever data is stored, in Intel syntax it would be [ds:dx] (but dx cannot be used for memory addressing).

So, what you need to do: store the value read from keyboard with DOS interrupt 21h / ah = 01h, returned in al to some memory address and then refer to that memory address with ds:dx.

In your code you don't store the file handle at all, and load 0 from the variable file_handle before write to file call, as that's how you have it initialized. And then you try to read file handle from ds:0 (as si equals 0), and that doesn't make sense at all. All you need to do with the file handle is to store it (return value in ax after file creation/truncation) and always load it to relevant register in subsequent int 21h referring to that same file (write to file, read from file, close file, etc.).

So, with the fixes below it should work (didn't test). I also organized the function call parameters to the order used by Ralf Brown's interrupt list to make it easier to understand.

.section data
file db 'file.txt',0
character_read db 0

...

% create file:
    mov ah,3Ch             % create or truncate a file
    mov dx,file            % ds:dx points to ASCIIZ filename
    xor cx,cx              % file attributes.
    int 21h

    mov [file_handle], ax  % file handle must be stored in memory or in a register!

INPUTSTART:
    mov ah,1               % read character from STDIN, with echo.
    int 21h
    mov [character_read], al  % store the ASCII code to memory.

    % unless you want to loop eternally, you can check the ASCII code and exit.

    cmp al,20h             % space.
    je  EXIT

    mov ah,40h             % write to file or device
    mov bx,[file_handle]   % file handle is just a number.
    mov cx,1               % number of bytes to write.
    mov dx,character_read
    int 21h

    jmp INPUTSTART

EXIT:
    % here you can add some clean-up code, if needed.

    mov ah,3Eh             % close file.
    mov bx,[file_handle]   % here you need the file handle again.
    int 21h

    mov ah,4Ch
    int 21h