2

我正在使用 3Ch 函数创建文件并使用 40h 函数保存字符(我在这里阅读过)

我不明白如何将读取字符放入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.

4

2 回答 2

2

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

.COM 程序的代码从文件的最开头开始,也没有将文件划分为逻辑部分,因此您不能首先放置数据部分(例如 .data 或 .bss),它不会甚至定义这样的部分也很有意义。

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

org 100h
bits 16

; code begins here
; then goes data

或者

org 100h
bits 16

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

接下来,函数 3Ch 返回一个文件句柄在AX. 您可以使用此句柄对文件执行进一步的操作(例如读取、写入、关闭)。您的代码没有将这个句柄隐藏在 中file_handle,我猜这正是为此目的而定义的,并且它通过覆盖AXwith的值来丢弃它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
...

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

于 2013-02-15T00:06:56.840 回答
2

实际上,您没有将字符放入 中 ds:dx,而是ds:dx用于引用存储字符或任何数据的内存地址,在 Intel 语法中它会是[ds:dx](但dx不能用于内存寻址)。

因此,您需要做的是:使用 DOS 中断21h/存储从键盘读取的值ah = 01h,返回al到某个内存地址,然后使用ds:dx.

在您的代码中,您根本不存储文件句柄,并file_handle在写入文件调用之前从变量中加载 0,因为这就是您初始化它的方式。然后您尝试从ds:0si等于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
于 2013-02-15T00:08:29.167 回答