用单词替换数字并使用汇编器 8086 写入文件

问题描述 投票:0回答:1

我正在编写一个程序,将数字转换为单词,并将所有其他字符不变地写入输出文件。但由于某种原因,输出缓冲区会相互覆盖字符。

例如。输入文件如下所示:

0a

输出文件应如下所示:

nulisa

它看起来像这样:

aulis

这是我到目前为止所拥有的:

.model small         
.stack 100h            

.data
    msgHelp        DB "Usage: program.exe <input_file> <output_file>$"    
    msgFileError   DB "Error: File not found or cannot be opened.$"    
    input db 200 dup (0)           
    output  db 200 dup (0)          
    skBuf   db 20 dup (?)  
    raBuf   db 200 dup (?) 
    words db "nulis", 0, "vienas", 0, "du", 0, "trys", 0, "keturi", 0, "penki", 0, "sesi", 0, "septyni", 0, "astuoni", 0, "devyni", 0
    wordOffsets dw 0, 6, 13, 16, 21, 28, 34, 39, 47, 55
    dFail   dw ?     
    rFail   dw ?     
    raBufPos dw 0    

.code

start:
    MOV ax, @data          
    MOV ds, ax         
    MOV di, offset raBuf    

    MOV bx, 82h             
    MOV si, offset input    

    cmp byte ptr es:[80h], 0 
    je help                  
    cmp es:[82h], '?/'       
    jne check_param          
    cmp byte ptr es:[84h], 13
    je help
    jmp check_param 

help:
    mov ah, 9              
    mov dx, offset msgHelp 
    int 21h                
    jmp programEnd       

check_param:
    cmp byte ptr es:[bx], 13 
    je next_filename         
    cmp byte ptr es:[bx], 32 
    je next_filename
    mov dl, byte ptr es:[bx] 
    mov [si], dl             
    inc bx                   
    inc si                   
    jmp check_param          

next_filename:
    inc bx 

    mov si, offset output    

output_filename_loop:
    cmp byte ptr es:[bx], 13 
    je found                

    mov dl, byte ptr es:[bx]
    mov [si], dl             
    inc bx                    
    inc si                    
    jmp output_filename_loop 

found:
    MOV ah, 3Dh              
    MOV al, 00      
    MOV dx, offset input
    INT 21h 
    JC file_error       
    MOV dFail, ax           

    MOV ah, 3Ch   
    MOV cx, 0               
    MOV dx, offset output      
    INT 21h                   
    JC file_error 
    MOV rFail, ax           

read:
    MOV bx, dFail
    CALL ReadBuf            
    CMP ax, 0               
    JE closeInput

    MOV cx, ax              
    MOV si, offset skBuf    

processLoop:
    MOV dl, [si]   
    CMP dl, '0'
    JB notDigit  
    CMP dl, '9'   
    JA notDigit 

    PUSH cx                  
    PUSH si
    PUSH di
    CALL ConvertDigitToWord  
    POP di                   
    POP si
    POP cx
    JMP skip 

notDigit:
    MOV [di], dl            
    INC di  
    INC raBufPos            

skip:
    INC si                  
    DEC cx                  
    JNZ processLoop         

writeOutput:
    MOV cx, raBufPos        
    MOV bx, rFail           
    MOV dx, offset raBuf    
    CALL WriteBuf
    MOV di, offset raBuf    
    MOV raBufPos, 0         
    JMP read                

file_error:
    MOV ah, 09h  
    MOV dx, offset msgFileError
    INT 21h
    jmp programEnd

closeOutput:
    MOV ah, 3Eh     
    MOV bx, rFail   
    INT 21h     
    JC file_error   

closeInput:
    MOV ah, 3Eh      
    MOV bx, dFail   
    INT 21h        

programEnd:
    MOV ah, 4Ch 
    MOV al, 0    
    INT 21h 

ConvertDigitToWord PROC
    SUB dl, '0'              
    MOV cl, dl

    MOV si, offset wordOffsets  
    MOV bx, cx 
    SHL bx, 1                
    ADD si, bx               
    MOV ax, [si]             
    ADD ax, offset words     
    MOV si, ax               

copyWord:
    MOV al, [si]             
    CMP al, 0  
    JE doneCopy              
    MOV [di], al             
    INC di                   
    INC si                   
    INC raBufPos             
    JMP copyWord    

doneCopy:
    RET  
ConvertDigitToWord ENDP

ReadBuf PROC
    MOV ah, 3Fh   
    MOV bx, dFail            
    MOV cx, 20               
    MOV dx, offset skBuf     
    INT 21h  
    RET       
ReadBuf ENDP

WriteBuf PROC
    MOV ah, 40h    
    MOV bx, rFail            
    MOV cx, raBufPos         
    MOV dx, offset raBuf     
    INT 21h  
    RET   
WriteBuf ENDP

END start
assembly x86 dosbox
1个回答
1
投票
PUSH cx                  
PUSH si
PUSH di
CALL ConvertDigitToWord  
POP di                   
POP si
POP cx

DI 寄存器目前仅是ConvertDigitToWord 程序的输入。但对于您的程序来说,它也应该是此过程的“输出”。通过删除 PUSH di

POP di
指令快速解决该问题。
想要更好吗?然后避免冗余。

DI 和

raBufPos

都扮演着类似的角色。您不需要那个 raBufPos 变量。 只需像您在 mov di, offset raBuf
中所做的那样设置 DI,并且在需要输出长度的地方可以将

MOV cx, raBufPos
替换为
lea cx, [di - raBuf]
。如果您的汇编器不接受这一点,则将其写为
mov cx, di
sub cx, offset raBuf
ps。请编辑您的帖子并将整个程序放在三个反引号字符之间。

© www.soinside.com 2019 - 2024. All rights reserved.