我有一个任务,我会尽量解释清楚。有一个文件与[0; 1000]行。每行包含6列。
前两列包含带有[1; 20]个字符。字符可以是 * 字母、数字和空格 *。
3-5列包含范围为 [-100; 100]。第6列包含范围真实的 [-9.99; 9.99],小数点后只有两位数。
每一节I用分号'隔开;'.
文件示例:
helloA;lB;lC;lD;lE;lF
A11;bas morning;0;0;5;1.15
B12; Hello WoRlD;-100;11;78;1.33
B11;table;10;0;55;-2.44
C1;OakWood;0;8;17;3.77
**TASK:**计算前两部分中有多少行包含字母'B'和'C'。并在另一个文件中打印该整数。
我几乎完成了所有的任务,除了一件事。我不知道如何打印文件中的十进制数。我在内存中以 * 十六进制 * 存储该数。我需要将该数转换为 * 十进制 * 并将其打印到另一个文件中。
我在挣扎,因为可能只有1行,但也可能有1000行。所以我需要打印1个字符(如果行的数量在[0; 9]),但它可能是900个好的行,所以然后程序必须打印3个字符。
我的代码
org 100h
%include 'yasmmac.inc'
section .text
startas:
macPutString 'Output file:', crlf, '$'
; Save the writing file's name
mov al, 128
mov dx, writingFile
call procGetStr
macNewLine
; Open reading file
mov dx, readingFile
call procFOpenForReading
jnc .writingFileOpen
macPutString 'Error while opening the writing file!', '$'
exit
; Open the writing file
.writingFileOpen:
mov [readingDescriptor], bx
mov dx, writingFile
call procFCreateOrTruncate
jnc .writingFileSuccessfullyOpened
macPutString 'Error while opening file for writing!', '$'
jmp .writingError
; Sacing writing descriptor
.writingFileSuccessfullyOpened:
mov [writingDescriptor], bx
; Read first line
call procReadLine
; Main loop
.untilEndOfFile:
call procReadLine
; checking the first two columns
;mov al, ';'
; checking first column
.firstColumn:
mov al, [di]
inc di
cmp al, byte 'B'
je .skipALine
cmp al, byte 'b'
je .skipALine
cmp al, byte 'C'
je .skipALine
cmp al, byte 'c'
je .skipALine
cmp al, byte ';'
jne .firstColumn
; checking second column
.secondColumn:
mov al, [di]
inc di
cmp al, byte 'B'
je .skipALine
cmp al, byte 'b'
je .skipALine
cmp al, byte 'C'
je .skipALine
cmp al, byte 'c'
je .skipALine
cmp al, byte ';'
jne .secondColumn
jmp .addNumber ; Adding number because line corresponds to filter.
.addNumber:
call procAddNumber
; If it is not the end of file, jump back to main loop
.skipALine:
cmp [readTheLastLine], byte 0
je .untilEndOfFile
; Writing to file (number, how many good lines)
; **I cant do this part**
mov bx, [writingDescriptor]
mov cx, 2h
mov dx, lineCount
mov ah, 40h
int 21h
; Closing Files
.end:
mov bx, [writingDescriptor]
call procFClose
.writingError:
mov bx, [readingDescriptor]
call procFClose
exit
%include 'yasmlib.asm'
; void procReadLine()
; Read line to buffer 'line'
procReadLine:
push ax
push bx
push cx
push si
mov bx, [readingDescriptor]
mov si, 0
.loop:
call procFGetChar
; End if the end of file or error
cmp ax, 0
je .endOfFile
jc .endOfFile
; Putting symbol to buffer
mov [line+si], cl
inc si
; Check if there is \n?
cmp cl, 0x0A
je .endOfLine
jmp .loop
.endOfFile:
mov [readTheLastLine], byte 1
.endOfLine:
mov [line+si], byte '$'
mov [lineLength], si
pop si
pop cx
pop bx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
procAddNumber:
push si
push ax
push bx
push cx
push dx
;lineCount++
mov ax, [lineCount]
inc ax
mov [lineCount], ax
pop dx
pop cx
pop bx
pop ax
pop si
ret
section .data
readingFile:
db 'input.dat', 00
readingDescriptor:
dw 0000
writingFile:
times 128 db 00
writingDescriptor:
dw 0000
readTheLastLine:
db 00
line:
db 64
times 66 db '$'
lineLength:
dw 0000
lineCount:
dw 0000
GitHub链接到宏:yasmlib.asm/yasmmac.inc
任何帮助都将不胜感激。
2条答案
按热度按时间23c0lvtd1#
我不知道如何打印文件中的十进制数。我将该数作为十六进制存储在内存中。我需要将该数转换为十进制数,然后将其打印到另一个文件中。
该问题的解决方案已在yasmlib.asm文件中!它包含一个代码 * procUInt 16 ToStr *,该代码将AX中的无符号数字转换为DX中地址处的ASCIIZ字符串。
它不返回字符串的长度,所以你必须循环遍历字符串,并使用 procFPutChar 将单个字符发送到文件中。或者,最好循环遍历字符串,建立stringlength,并使用DOS函数40 h一次性输出(就像你已经做的那样)。
如果你有兴趣知道 * 如何 * 将整数转换为字符串,那么你可以阅读我的Q/A Displaying numbers with DOS。
小心这些
此代码使用DI,但未初始化寄存器(
mov di, line
)。检查 readTheLastLine 变量来得太晚了!您需要在 procReadLine 过程返回后直接检查 * readTheLastLine* 变量:
您不需要使用浪费的 procAddNumber 过程来递增 linecount 变量。
只需将
call procAddNumber
替换为inc word [linecount]
即可。au9on6nz2#
而另一个答案是关于你的问题,即写数字的文本表示,这个答案集中在一个基本的误解,即任务是问什么。
TASK:计算前两个部分中包含字母“B”和“C”的行数
您目前的程式正在计算既不包含'B'也不包含'C'的行数。这与所要求的正好相反。Next会给予您计算包含'B'或'C'的行数。
请注意,上面的内容并不是字面上的“包含字母'B'和'C'”,它更像是“包含字母'B'或'C'”。但是不用担心,在编程中非常重要的区别可能并不总是被认为在日常的演讲/写作中那么重要。