如何将十进制数写入8086 YASM文件中



我有一个任务,我会尽量解释清楚。有一个文件[0;1000]。每行包含6列。

前两列包含stringwith [1;20)字符。字符可以是字母、数字和空白

3-5列包含[-100;100]。第6列包含[-9.99;9.99]小数点后只有两位。

每一节用分号";"隔开。

文件的例子:

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

任务:数一下前两部分中有多少行包含字母"B"one_answers"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

如有任何帮助,不胜感激。

我不知道如何在文件中打印十进制数。我将这个数字以十六进制的形式存储在内存中。我需要把这个数字转换成十进制,然后打印到另一个文件中。

这个问题的解决方案已经在yasmlib中了。asm文件!它包含一个代码procint16tostr,它将把AX中的无符号数转换成DX中地址处的ascii字符串。
它不返回字符串的长度,因此您必须遍历字符串并使用procFPutChar将单个字符发送到文件。或者,最好是循环字符串,用DOS函数40h一次性建立字符串长度和输出(就像你已经做的那样)。

如果你有兴趣知道如何从整数转换到字符串,那么你可以阅读我的Q/A用DOS显示数字。

.WritingToFile:
mov  dx, Buffer
mov  ax, [linecount]
call procUInt16ToStr  ; produces an ASCIIZ string at DX
mov  si, dx
.again:
lodsb
cmp  al, 0
jne  .again
sub  si, dx
lea  cx, [si - 1]     ; -1 because we don't want to send the zero
mov  bx, [writingDescriptor]
mov  ah, 40h          ; DOS.WriteToFile
int  21h              ; -> AX CF

小心这些

.untilEndOfFile:
call procReadLine
.firstColumn:
mov al, [di]

这段代码使用DI而没有初始化寄存器(mov di, line)。

.skipALine:
cmp [readTheLastLine], byte 0
je .untilEndOfFile

检查readTheLastLine变量来得太晚了!您需要在procReadLine过程返回后直接使用:

.untilEndOfFile:
call procReadLine
cmp  byte [readTheLastLine], 0
je   .WritingToFile
mov  di, line
.firstColumn:
mov al, [di]
...
jmp  .untilEndOfFile
.WritingToFile:

您不需要浪费procAddNumber过程来增加linect变量。
inc word [linecount]代替call procAddNumber

另一个答案处理的是你关于写数字的文本表示的问题,而这个答案关注的是对任务要求的基本误解。

任务:计算前两部分中包含字母"B"one_answers"C"的行数

当前程序正在计算既不包含'B'也不包含'C'的行。和问的正好相反。接下来将给出包含'B'或'C'的行数。

.untilEndOfFile:
call procReadLine
cmp  byte [readTheLastLine], 0
je   .WritingToFile
...
jne  .secondColumn
jmp  .untilEndOfFile
.skipALine:
inc  word [linecount]
jmp  .untilEndOfFile
.WritingToFile:

注意,上面仍然不是字面上包含字母'B''C'",它更像是"包含字母'B'"C"。但别担心,一个在编程中非常重要的区别,在日常的语言/写作中可能并不总是被认为那么重要。