x86 ASM - 逐行读取
x86 ASM - Read line by line
好吧,我只想逐行读取文本,然后输出。
我做的事情:
- 读取单个字符,添加到字符串
- 搜索 LF
- 输出字符串
- 从头再来,直到 EOF
问题:
- 不知道如何在忙于 3Fh 时计算 40h 中断的 cx(试图创建一些新变量,但最终出现一堆错误)
- 某种奇怪的结果 - 几行空行和最后一行
.txt example
some
random
text
.model small
.stack 100h
.data
filename db 255 dup(0)
text db 255 dup(0)
char db ?
line db 255 dup(0)
filehandle dw ?
.code
newline macro ;NEW LINE
;
mov dl, 10 ;
mov ah, 02h ;
int 21h ;
;
mov dl, 13 ;
mov ah, 02h ; ;
int 21h ;
endm ;NEW LINE
main:
mov ax, @data
mov ds, ax
lea si, filename
mov ah, 01h ;read character
char_input:
int 21h
cmp al, 0dh ;enter
je zero_terminator
mov [si], al
inc si
jmp char_input
zero_terminator:
mov [si], 0
open_file:
lea dx, filename
mov al, 0
mov ah, 3Dh ;open file
int 21h
mov filehandle, ax
lea si, text
newline
read_line:
mov ah, 3Fh ;read file
mov bx, filehandle
lea dx, char
mov cx, 1
int 21h
cmp ax, 0 ;EOF
je EO_file
mov al, char
cmp al, 0ah ; line feed
je LF
mov [si], al
inc si
jmp read_line:
EO_file:
lea dx, text
mov ah, 40h ;print
mov cx, 255
mov bx, 1
int 21h
mov ah, 4ch
int 21h
LF:
lea dx, text
mov ah, 40h ;print
mov cx, 255
mov bx, 1
int 21h
inc si
jmp read_line
end main
这是为了让您继续前进,而不是为了解决您代码中的所有错误:
您有:
zero_terminator:
mov [si], 0
想法是移动一个0字节到SI指向的位置。 TASM 不明白您想将单个字节移动到 [SI],因此应该明确告诉它这就是您的意图:
mov byte ptr [si], 0
你在这行有一个错字,末尾有一个冒号:
jmp read_line:
应该是:
jmp read_line
您的代码的主要问题是,当要打印出读入 text
字符数组的字符时,您需要指定要在 CX[=61 中打印的字符数=]。您使用如下代码指定 255:
LF:
lea dx, text
mov ah, 40h ;print
mov cx, 255
由于SI包含一个指向最后读取字符的指针,可以从text中减去text的地址(偏移量) =]SI 获取缓冲区中的字符数。所以上面的内容可以改成:
LF:
lea dx, text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
一旦你打印出一行你inc SI 和return 来阅读字符。由于您已经打印出该行,您也可以通过将 SI 重置为开头来从 text 缓冲区的开头重新启动:
mov si, dx ; start from beginning of buffer (DX=beginning of text buffer)
或者你可以移动 DX 已经包含 text 的偏移量并设置 SI:
这与您最初在读取数据开始时设置的方式相同。
您的 EOF 代码有一个类似的问题,它需要将缓冲区中的字节数放入 ECX。所以这段代码:
EO_file:
lea dx, text
mov ah, 40h ;print
mov cx, 255
mov bx, 1
int 21h
可改为:
LF:
lea dx, text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
通过所有这些更改,您将获得如下程序:
.model small
.stack 100h
.data
filename db 255 dup(0)
text db 255 dup(0)
char db ?
line db 255 dup(0)
filehandle dw ?
.code
newline macro ;NEW LINE
;
mov dl, 10 ;
mov ah, 02h ;
int 21h ;
;
mov dl, 13 ;
mov ah, 02h ; ;
int 21h ;
endm ;NEW LINE
main:
mov ax, @data
mov ds, ax
lea si, filename
mov ah, 01h ;read character
char_input:
int 21h
cmp al, 0dh ;enter
je zero_terminator
mov [si], al
inc si
jmp char_input
zero_terminator:
mov byte ptr [si], 0
open_file:
lea dx, filename
mov al, 0
mov ah, 3Dh ;open file
int 21h
mov filehandle, ax
lea si, text
newline
read_line:
mov ah, 3Fh ;read file
mov bx, filehandle
lea dx, char
mov cx, 1
int 21h
cmp ax, 0 ;EOF
je EO_file
mov al, char
cmp al, 0ah ; line feed
je LF
mov [si], al
inc si
jmp read_line
EO_file:
lea dx, text ;DX=offset(address) of text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
mov bx, 1
int 21h
mov ah, 4ch
int 21h
LF:
lea dx, text ;DX=offset(address) of text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
mov bx, 1
int 21h
mov si, dx ;Start from beginning of buffer
;(DX=beginning of text buffer)
jmp read_line
end main
好吧,我只想逐行读取文本,然后输出。
我做的事情:
- 读取单个字符,添加到字符串
- 搜索 LF
- 输出字符串
- 从头再来,直到 EOF
问题:
- 不知道如何在忙于 3Fh 时计算 40h 中断的 cx(试图创建一些新变量,但最终出现一堆错误)
- 某种奇怪的结果 - 几行空行和最后一行
.txt example
some random text
.model small
.stack 100h
.data
filename db 255 dup(0)
text db 255 dup(0)
char db ?
line db 255 dup(0)
filehandle dw ?
.code
newline macro ;NEW LINE
;
mov dl, 10 ;
mov ah, 02h ;
int 21h ;
;
mov dl, 13 ;
mov ah, 02h ; ;
int 21h ;
endm ;NEW LINE
main:
mov ax, @data
mov ds, ax
lea si, filename
mov ah, 01h ;read character
char_input:
int 21h
cmp al, 0dh ;enter
je zero_terminator
mov [si], al
inc si
jmp char_input
zero_terminator:
mov [si], 0
open_file:
lea dx, filename
mov al, 0
mov ah, 3Dh ;open file
int 21h
mov filehandle, ax
lea si, text
newline
read_line:
mov ah, 3Fh ;read file
mov bx, filehandle
lea dx, char
mov cx, 1
int 21h
cmp ax, 0 ;EOF
je EO_file
mov al, char
cmp al, 0ah ; line feed
je LF
mov [si], al
inc si
jmp read_line:
EO_file:
lea dx, text
mov ah, 40h ;print
mov cx, 255
mov bx, 1
int 21h
mov ah, 4ch
int 21h
LF:
lea dx, text
mov ah, 40h ;print
mov cx, 255
mov bx, 1
int 21h
inc si
jmp read_line
end main
这是为了让您继续前进,而不是为了解决您代码中的所有错误:
您有:
zero_terminator:
mov [si], 0
想法是移动一个0字节到SI指向的位置。 TASM 不明白您想将单个字节移动到 [SI],因此应该明确告诉它这就是您的意图:
mov byte ptr [si], 0
你在这行有一个错字,末尾有一个冒号:
jmp read_line:
应该是:
jmp read_line
您的代码的主要问题是,当要打印出读入 text
字符数组的字符时,您需要指定要在 CX[=61 中打印的字符数=]。您使用如下代码指定 255:
LF:
lea dx, text
mov ah, 40h ;print
mov cx, 255
由于SI包含一个指向最后读取字符的指针,可以从text中减去text的地址(偏移量) =]SI 获取缓冲区中的字符数。所以上面的内容可以改成:
LF:
lea dx, text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
一旦你打印出一行你inc SI 和return 来阅读字符。由于您已经打印出该行,您也可以通过将 SI 重置为开头来从 text 缓冲区的开头重新启动:
mov si, dx ; start from beginning of buffer (DX=beginning of text buffer)
或者你可以移动 DX 已经包含 text 的偏移量并设置 SI:
这与您最初在读取数据开始时设置的方式相同。
您的 EOF 代码有一个类似的问题,它需要将缓冲区中的字节数放入 ECX。所以这段代码:
EO_file:
lea dx, text
mov ah, 40h ;print
mov cx, 255
mov bx, 1
int 21h
可改为:
LF:
lea dx, text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
通过所有这些更改,您将获得如下程序:
.model small
.stack 100h
.data
filename db 255 dup(0)
text db 255 dup(0)
char db ?
line db 255 dup(0)
filehandle dw ?
.code
newline macro ;NEW LINE
;
mov dl, 10 ;
mov ah, 02h ;
int 21h ;
;
mov dl, 13 ;
mov ah, 02h ; ;
int 21h ;
endm ;NEW LINE
main:
mov ax, @data
mov ds, ax
lea si, filename
mov ah, 01h ;read character
char_input:
int 21h
cmp al, 0dh ;enter
je zero_terminator
mov [si], al
inc si
jmp char_input
zero_terminator:
mov byte ptr [si], 0
open_file:
lea dx, filename
mov al, 0
mov ah, 3Dh ;open file
int 21h
mov filehandle, ax
lea si, text
newline
read_line:
mov ah, 3Fh ;read file
mov bx, filehandle
lea dx, char
mov cx, 1
int 21h
cmp ax, 0 ;EOF
je EO_file
mov al, char
cmp al, 0ah ; line feed
je LF
mov [si], al
inc si
jmp read_line
EO_file:
lea dx, text ;DX=offset(address) of text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
mov bx, 1
int 21h
mov ah, 4ch
int 21h
LF:
lea dx, text ;DX=offset(address) of text
mov ah, 40h ;print
mov cx, si ;CX = # characters. Move pointer to last char to it
sub cx, dx ;Subtract the offset of text (in DX) from CX
;To get the actual number of chars in the buffer
mov bx, 1
int 21h
mov si, dx ;Start from beginning of buffer
;(DX=beginning of text buffer)
jmp read_line
end main