如何从键盘读取字符并将其保存到DOS程序集中的文件?

时间:2013-02-14 23:00:05

标签: assembly input x86 dos

我正在使用3Ch函数创建文件并使用40h函数保存字符(我读过它here

我不明白如何在DS:DX中添加阅读字符。

这是我的代码:

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

正如您所见,程序旨在循环工作并编写与用户类型一样多的字符。请帮助获取40h函数的文件句柄并将数据放入DS:DX

2 个答案:

答案 0 :(得分:2)

基于代码的语法,我猜你正在使用NASM并尝试创建一个.COM程序。

.COM程序的代码从文件的最开始开始,并且文件没有任何划分为逻辑部分,因此您不能先放置数据部分(例如.data或.bss)而且它不会甚至定义这些部分也没有多大意义。

因此,您的代码应如下所示:

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

接下来,函数3Ch返回AX中的文件句柄。您可以使用此句柄对文件执行进一步操作(例如,读取,写入,关闭)。你的代码并没有在file_handle中隐藏这个句柄,我猜测它是为了这个目的而准确定义的,并且通过用AX覆盖mov AH,01h的值来摧毁它。你需要解决这个问题。

在程序结束时,您必须使用功能3Eh关闭文件。如果不这样做,该文件可能最终只包含已写入其中的一部分数据,在重新启动PC之前该文件可能无法访问,您也可能无法打开(或创建)更多文件如果你积累了足够的未闭合文件句柄。所以,最后关闭文件。

至于保存文件中的字符,没有什么可以阻止你定义一个字节变量,比如key,将AL存储到其中,然后将key的地址传递给函数40h ,例如:

...
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
...

另外,不要忘记指定一些键来突破你现在在程序中的无限循环。

答案 1 :(得分:2)

实际上你没有将放在 ds:dx中,而是使用ds:dx引用字符所在的内存地址或者存储的数据,在英特尔语法中它是[ds:dx](但dx不能用于内存寻址)。

那么,你需要做什么:存储从键盘读取的值与DOS中断21h / ah = 01h,在al中返回到某个内存地址,然后引用该内存地址与ds:dx

在您的代码中,您根本不存储文件句柄,并在写入文件调用之前从变量file_handle加载0,因为这是您初始化它的方式。然后你尝试从ds:0读取文件句柄(因为si等于0),这根本没有意义。您需要对文件句柄执行的操作就是存储它(在文件创建/截断后在ax中返回值)并始终将其加载到后续int 21h中引用相同文件的相关寄存器(写入文件,从文件中读取,关闭文件等。)。

所以,通过下面的修复,它应该工作(没有测试)。我还将函数调用参数组织为Ralf Brown中断列表使用的顺序,以便于理解。

.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