我有一個任務,我會盡量解釋清楚。有一個檔案 [0; 1000] 行。每行包含 6 列。
前兩列包含帶有[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”和“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
任何幫助,將不勝感激。
uj5u.com熱心網友回復:
我不知道如何在檔案中列印十進制數。我將此數字以十六進制形式存盤在記憶體中。我需要將該數字轉換為十進制并將其列印到另一個檔案中。
問題的解決方案已經在 yasmlib.asm 檔案中了!它包含一個代碼procUInt16ToStr,它將 AX 中的無符號數字轉換為 DX 中地址處的 ASCIIZ 字串。
它不回傳字串的長度,因此您必須遍歷字串并使用procFPutChar將單個字符發送到檔案。或者,最好回圈字串以建立字串長度并使用 DOS 函式 40h 一次輸出(就像你已經在做的那樣)。
如果您有興趣了解如何從整數轉換為字串,那么您可以閱讀我的 Q/A Displaying numbers with 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]
此代碼在未初始化暫存器 ( mov di, line) 的情況下使用 DI。
.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程序來增加linecount變數。
只需替換call procAddNumber為inc word [linecount].
uj5u.com熱心網友回復:
雖然另一個答案涉及您關于撰寫數字的文本表示的問題,但此答案集中在對任務要求的基本誤解上。
任務:計算前兩個部分中有多少行包含字母“B”和“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'”。但別擔心,在編程中非常重要的區別在日常演講/寫作中可能并不總是被認為那么重要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/533186.html
