首页 文章

8086 ASM:Turbodebugger打开文本文件,正常执行没有

提问于
浏览
0

我正在研究ASM任务的这个小问题 . 当我使用TD时,它就像一个魅力......由于我对大会很新,我真的找不到问题所在 .

我需要在屏幕上打印.txt文件中每个ASCII代码有多少个字符(多少个,多少个b,依此类推) . 我首先使用int 21h / 3dh打开文件来创建一个句柄,然后缓冲一些字节,处理它们,并缓冲下一部分,直到到达文件末尾 . 正如我所说,当我使用TurboDebugger运行它时,它运行得很好 . 但是,当我执行它只是形成命令行时,它甚至不创建文件句柄 . 它在3dh中断后设置CF,这意味着错误 .

我真的认为我没有做我需要做的事情,我很感激你的帮助 . 谢谢!顺便说一下,我正在使用TASM进行编译 . 我不认为发布我的代码会有所帮助,但如果你不这么认为我会很乐意修改帖子 .

这是整个代码,对于西班牙语的评论感到抱歉

NLCR       macro
           mov dl, 0dh      ;Caracter a imprimir a dl
           mov ah, 02h      ;Preparo la impresion de un caracter
           int 21h          ;Ejecuto
           mov dl, 0ah      ;Caracter a imprimir a dl
           mov ah, 02h      ;Preparo la impresion de un caracter
           int 21h          ;Ejecuto
           endm 

 SData Segment para 'Data'
            msgerrorab  db  "Error al abrir el archivo.$"
            msgerrorca  db  "Error al cargar el archivo.$"
            msgnombre   db  "Ingrese el nombre del archivo a abrir: $"
            msgnoexiste db  "Error: el archivo no existe.$"
            msgimprimir db  "=========  Caracter  ==========  Cantidad  =======",10,13,"$"
            msglinea1   db "===           $"
            caracter    db  0
            msglinea2   db  "   ==========     $"
            cuantos     dw  0
            msglinea3   db  "==========",10,13,"$"
            msgtecla    db  "Presione una tecla para mostrar mas...$"
            noarchivo   db  "$$"
            nombre      db  20 Dup(?)
            buffer      db  4096 Dup(4)
            handle      dw  0
            caracteres  dw  255 Dup(0)
            cantidad    dw  0
            eof         db  0
            bytesinv    db  10 dup("$")
            bytes       db  10 dup("$") 
            contador    db  0 

 SData EndS 

 pila segment stack 'stack'
  dw 256 dup (?) 
pila ends 

 CSeg Segment para public 'Code'
  Begin:
       Assume CS:CSeg, DS:SData,SS:pila 

 LeeChar Proc                  ;Procedure para leer un caracter y guardarlo. Lo salva en AL
          xor ax,ax             ;Limpia el ax para guardar el resultado
          mov ah, 08h           ;Prepara el servicio para leer un caracter
          int 21h               ;Lo ejecuta
          ret                   ;Retorna
  LeeChar endP 

 ImpChar Proc                  ;Similar, pero imprime un caracter
          xor ax,ax             ;Limpia el ax para guardar el resultado
          mov ah,02h            ;Prepara el servicio para imprimir un caracter
          int 21h               ;Lo ejecuta
          ret                   ;Retorna
  ImpChar endP 

 ImpStr Proc                 ;Similar, pero imprime un caracter
          xor ax,ax             ;Limpia el ax para guardar el resultado
          mov ah,09h            ;Prepara el servicio para imprimir un caracter
          int 21h               ;Lo ejecuta
          ret                   ;Retorna
ImpStr endP 

 ImpNum     Proc                 ;el numero en ax, el bx en 000A, dx en 0, y el di en 0.
hexadec:                        ;Con esto se pasa "a decimal", es decir convierte los caracteres a numeros para ser impresos.
           div bx               ;Divido por 10 y consigo en DL el numero de mas a la derecha
           add dx, 30h          ;Sumo 48 para pasarlo a caracter. EL MODULO QUEDA EN DX
           mov bytesinv[di], dl ;Lo guardo en el vector
           xor dx,dx            ;Limpio para volverlo a hacer
           inc di               ;Aumento el indice del vector
           cmp ax,0             ;Si ya no queda nada
           je resfinal          ;Brinco al resultado final
           jmp hexadec          ;Si todavia queda, hago el proceso de division de nuevo 

 resfinal:                       ;Inversion de los caracteres
           xor si,si
           mov al, bytesinv[di-1] ;Estas dos lineas vuelcan el vector en otro, pero en el orden que corresponde
           mov bytes[si],al     ;Pasa al nuevo vector los caracteres
           dec di               ;Decrementa para mover el indice
           inc si               ;Aumento el indice del vector
           cmp di,0             ;Si ya no queda nada
           jne resfinal
           lea dx, bytes
           xor ax,ax
           mov ah,09h
           int 21h
           ret
ImpNum     endP
;;;;;;;;;;;;;;;;;;;;;;; 
;Comienzo del programa;
;;;;;;;;;;;;;;;;;;;;;;; 

 inicio:   mov ax,SData          ;Con estas dos lineas, pasamos la direccion del segmento SData y lo pasamos al ds
          mov ds,ax
          mov ax,pila
          mov ss,ax 

 leernombre:
          xor di,di
          xor ax,ax             ;Limpio AX
          xor dx,dx             ;Limpio DX
          lea dx, msgnombre     ;Cargo el offset del mensaje que pide el nombre
          mov ah,09h            ;Preparo el servicio de impresion
          int 21h               ;Ejecuto
          xor ax,ax             ;Limpio AX
          xor dx,dx             ;Limpio DX
          lea dx, noarchivo     ;Carga el offset de donde voy a guardar el nombre del archivo
          mov ah,0ah            ;Preparo el servicio de entrada buffereada
          int 21h               ;Ejecuto
          nlcr                  ;New line carriage return
          xor ah,ah             ;Limpio AH
          mov al, noarchivo[1]  ;En narchivo[1] esta la cantidad de caracteres que mide el nombre de archivo
          mov di,ax             ;Lo paso al DI para usarlo como indice
          mov noarchivo[di+2],0 ;La posicion di+2 del nombre contiene el Enter, o 0ah. Lo convierto en 0.
          mov ah,3dh            ;Preparo el servicio de creacion de handle para abrir el archivo
          mov al,0              ;En modo de solo lectura
          lea dx, nombre        ;Cargo el offset del nombre en DX, sin los bytes que sobran antes
          int 21h               ;Ejecuto. El handle queda en AX
          jc  errorabrir
          mov handle,ax         ;Lo paso a su variable correspondiente
          jmp cargarbuffer
errorabrir:
          lea dx, msgerrorab        ;Cargo el offset del mensaje que pide el nombre
          mov ah,09h                ;Preparo el servicio de impresion
          int 21h 
          jmp final
errorcarga:
          lea dx, msgerrorca        ;Cargo el offset del mensaje que pide el nombre
          mov ah,09h                ;Preparo el servicio de impresion
          int 21h 
          jmp final
cargarbuffer:
          xor ax,ax             ;Limpio AX
          xor bx,bx
          lea dx, buffer        ;Cargo el offset del buffer de texto
          mov ah,3fh            ;Preparo el servicio para mover el contenido del archivo
          mov bx,handle         ;Uso el handle que me genero la int 21/3dh
          mov cx,10         ;Voy a guardar 4096 caracteres a la vez
          int 21h
          jc errorcarga 

       mov cantidad,ax       ;Cargo la cantidad de caracteres leidos
      cmp cantidad,4096     ;Si es menor a lo que le dije que cargara, llego al end of file
      jl  endoffile         ;
      xor si,si
      xor ax,ax
      mov bx,handle
      mov ah,3eh
      int 21h
      jmp procesarbuffer
 

 endoffile:
          mov eof,1
          jmp procesarbuffer 

 procesarbuffer:
          xor bx,bx
          xor ax,ax
          xor di,di
          xor dx,dx
          mov bl,2
          mov al,buffer[si]
          mul bl
          mov di,ax
          inc caracteres[di]
          inc si
          cmp si,cantidad
          jne procesarbuffer
          cmp eof,1
          je  imprimir
          jmp cargarbuffer
        
imprimir:
          xor di,di
          xor dx,dx
          xor ax,ax
          xor bx,bx 

      mov di,0
      mov si,0
      lea dx, msgimprimir
      mov ah,09h
      int 21h

linea:    cmp caracteres[di],0
      je  noimprime
      inc contador
      mov ax,si
      mov caracter,al
      lea dx, msglinea1
      mov ah,09h
      int 21h
      mov dl,caracter
      xor ax,ax
      mov ah,02h
      int 21h
      lea dx, msglinea2
      xor ax,ax
      mov ah,09h
      int 21h
      push di
      push si
      mov ax, caracteres[di]
      mov bx,10
      xor dx,dx
      xor di,di
      call ImpNum
      pop si
      pop di
      inc di
      inc di
      inc si
      nlcr
      cmp si,254
      je final
      cmp contador,20
      je  pidetecla
      jmp linea

noimprime:
      inc di
      inc di
      inc si
      cmp si,254
      je final
      jmp linea

pidetecla:
      lea dx, msgtecla
      xor ax,ax
      mov ah,09h
      int 21h          
      xor ax,ax
      mov ah,08h
      int 21h
      nlcr
      jmp linea

final:
       xor ax,ax            ;Limpia el al y prepara el ah para la salida.
       mov ax,4c00h         ;Servicio AH=4c int 21h para salir del programa.
       int 21h              ;Llamada al DOS. Termine el programa.
CSeg EndS                       ;Fin del segmento de código.
End inicio                  ;Fin del programa la etiqueta al final dice en que punto debe comenzar el programa.

EDIT
似乎中断返回的错误代码是5,这意味着Access被拒绝...可能是因为路径文件??该文件位于我'm compiling it on, and it'的F:\ dos \ tasm \ a.txt所在的文件夹中 . 顺便说一句,我正在使用DosBox .

1 回答

  • 2

    我发现了一些错误并修复了它们 . 有关更改和注释,请参阅包含 ;;;; 的行 . 我现在在这里工作了 . 你能试试吗?

    NLCR macro
            mov dl, 0dh             ;Caracter a imprimir a dl
            mov ah, 02h             ;Preparo la impresion de un caracter
            int 21h                 ;Ejecuto
            mov dl, 0ah             ;Caracter a imprimir a dl
            mov ah, 02h             ;Preparo la impresion de un caracter
            int 21h                 ;Ejecuto
    endm
    
    SData Segment para 'Data'
    
    msgerrorab      db "Error al abrir el archivo.$"
    msgerrorca      db "Error al cargar el archivo.$"
    msgnombre       db "Ingrese el nombre del archivo a abrir: $"
    msgnoexiste     db "Error: el archivo no existe.$"
    msgimprimir     db "=========  Caracter  ==========  Cantidad  =======",10,13,"$"
    msglinea1       db "===           $"
    caracter        db 0
    msglinea2       db "   ==========     $"
    cuantos         dw 0
    msglinea3       db "==========",10,13,"$"
    msgtecla        db "Presione una tecla para mostrar mas...$"
    noarchivo       db buffer - nombre - 1, 0 ;;;; "$$"
    ;;;; You must initialize the input buffer for function 2 (the max len, at least)
    nombre          db 20 Dup(?)
    buffer          db 4096 Dup(4)
    handle          dw 0
    caracteres      dw 256 Dup(0) ;;;; 255 Dup(0)
    ;;;; You have 256 possible chars, not 255, with 255 you can overflow into "cantidad"
    cantidad        dw 0
    eof             db 0
    bytesinv        db 10 dup("$")
    bytes           db 10 dup("$")
    contador        db 0
    
    SData EndS
    
    
    pila segment stack 'stack'
      dw 256 dup (?)
    pila ends
    
    
    CSeg Segment para public 'Code'
    Begin:
            Assume CS:CSeg, DS:SData, SS:pila
    
    LeeChar Proc                    ;Procedure para leer un caracter y guardarlo. Lo salva en AL
            xor ax, ax              ;Limpia el ax para guardar el resultado
            mov ah, 08h             ;Prepara el servicio para leer un caracter
            int 21h                 ;Lo ejecuta
            ret                     ;Retorna
    LeeChar endP
    
    ImpChar Proc                    ;Similar, pero imprime un caracter
            xor ax, ax              ;Limpia el ax para guardar el resultado
            mov ah, 02h             ;Prepara el servicio para imprimir un caracter
            int 21h                 ;Lo ejecuta
            ret                     ;Retorna
    ImpChar endP
    
    ImpStr Proc                     ;Similar, pero imprime un caracter
            xor ax, ax              ;Limpia el ax para guardar el resultado
            mov ah, 09h             ;Prepara el servicio para imprimir un caracter
            int 21h                 ;Lo ejecuta
            ret                     ;Retorna
    ImpStr endP
    
    ImpNum Proc                     ;el numero en ax, el bx en 000A, dx en 0, y el di en 0.
    hexadec:                        ;Con esto se pasa "a decimal", es decir convierte los caracteres a numeros para ser impresos.
            div bx                  ;Divido por 10 y consigo en DL el numero de mas a la derecha
            add dx, 30h             ;Sumo 48 para pasarlo a caracter. EL MODULO QUEDA EN DX
            mov bytesinv[di], dl    ;Lo guardo en el vector
            xor dx, dx              ;Limpio para volverlo a hacer
            inc di                  ;Aumento el indice del vector
            cmp ax, 0               ;Si ya no queda nada
            je resfinal             ;Brinco al resultado final
            jmp hexadec             ;Si todavia queda, hago el proceso de division de nuevo
    
    resfinal:                       ;Inversion de los caracteres
            xor si, si
    resfinal2: ;;;;
            mov al, bytesinv[di-1]  ;Estas dos lineas vuelcan el vector en otro, pero en el orden que corresponde
            mov bytes[si], al       ;Pasa al nuevo vector los caracteres
            dec di                  ;Decrementa para mover el indice
            inc si                  ;Aumento el indice del vector
            cmp di, 0               ;Si ya no queda nada
            jne resfinal2 ;;;; resfinal
    ;;;; You don't want to be storing all digits at 'bytes[si=0]', overwriting each other
            mov bytes[si], "$"      ;;;;
    ;;;; You must terminate the string with '$' for function 9, you don't want garbage
            lea dx, bytes
            xor ax, ax
            mov ah, 09h
            int 21h
            ret
    ImpNum endP
    
    ;;;;;;;;;;;;;;;;;;;;;;;
    ;Comienzo del programa;
    ;;;;;;;;;;;;;;;;;;;;;;;
    
    inicio:
            mov ax, SData           ;Con estas dos lineas, pasamos la direccion del segmento SData y lo pasamos al ds
            mov ds, ax
    ;;;;        mov ax, pila
    ;;;;        mov ss, ax
    ;;;; .EXEs set up SS:SP for you!
    
    leernombre:
            xor di, di
            xor ax, ax              ;Limpio AX
            xor dx, dx              ;Limpio DX
            lea dx, msgnombre       ;Cargo el offset del mensaje que pide el nombre
            mov ah, 09h             ;Preparo el servicio de impresion
            int 21h                 ;Ejecuto
            xor ax, ax              ;Limpio AX
            xor dx, dx              ;Limpio DX
            lea dx, noarchivo       ;Carga el offset de donde voy a guardar el nombre del archivo
            mov ah, 0ah             ;Preparo el servicio de entrada buffereada
            int 21h                 ;Ejecuto
            nlcr                    ;New line carriage return
            xor ah, ah              ;Limpio AH
            mov al, noarchivo[1]    ;En narchivo[1] esta la cantidad de caracteres que mide el nombre de archivo
            mov di, ax              ;Lo paso al DI para usarlo como indice
            mov noarchivo[di+2],0   ;La posicion di+2 del nombre contiene el Enter, o 0ah. Lo convierto en 0.
            mov ah, 3dh             ;Preparo el servicio de creacion de handle para abrir el archivo
            mov al, 0               ;En modo de solo lectura
            lea dx, nombre          ;Cargo el offset del nombre en DX, sin los bytes que sobran antes
            int 21h                 ;Ejecuto. El handle queda en AX
            jc  errorabrir
            mov handle, ax          ;Lo paso a su variable correspondiente
            jmp cargarbuffer
    
    errorabrir:
            lea dx, msgerrorab      ;Cargo el offset del mensaje que pide el nombre
            mov ah, 09h             ;Preparo el servicio de impresion
            int 21h
            jmp final
    
    errorcarga:
            lea dx, msgerrorca      ;Cargo el offset del mensaje que pide el nombre
            mov ah, 09h             ;Preparo el servicio de impresion
            int 21h
            jmp final
    
    cargarbuffer:
            xor ax, ax              ;Limpio AX
            xor bx, bx
            lea dx, buffer          ;Cargo el offset del buffer de texto
            mov ah, 3fh             ;Preparo el servicio para mover el contenido del archivo
            mov bx, handle          ;Uso el handle que me genero la int 21/3dh
            mov cx, 4096 ;;;; 10              ;Voy a guardar 4096 caracteres a la vez
    ;;;; You wanted 4096 and implemented logic for 4096, so use 4096.
            int 21h
            jc errorcarga
    
            mov cantidad, ax        ;Cargo la cantidad de caracteres leidos
            cmp cantidad, 4096      ;Si es menor a lo que le dije que cargara, llego al end of file
            jl  endoffile           ;
            xor si, si
    ;;;;        xor ax, ax
    ;;;;        mov bx, handle
    ;;;;        mov ah, 3eh
    ;;;;        int 21h
    ;;;; You had the condition for file closing wrong
            jmp procesarbuffer
    
    endoffile:
            xor si, si              ;;;;
            xor ax, ax              ;;;;
            mov bx, handle          ;;;;
            mov ah, 3eh             ;;;;
            int 21h                 ;;;;
    ;;;; You had the condition for file closing wrong
    
            mov eof, 1
    
            cmp cantidad, 0         ;;;;
            je  imprimir            ;;;;
    ;;;; The original code at 'procesarbuffer' wouldn't work with 'cantidad'=0
    
            jmp procesarbuffer
    
    procesarbuffer:
            xor bx, bx
            xor ax, ax
            xor di, di
            xor dx, dx
            mov bl, 2
            mov al, buffer[si]
            mul bl
            mov di, ax
            inc caracteres[di]
            inc si
            cmp si, cantidad
            jne procesarbuffer
            cmp eof, 1
            je  imprimir
            jmp cargarbuffer
    
    imprimir:
            xor di, di
            xor dx, dx
            xor ax, ax
            xor bx, bx
    
            mov di, 0
            mov si, 0
            lea dx, msgimprimir
            mov ah, 09h
            int 21h
    
    linea:        
            cmp caracteres[di], 0
            je  noimprime
            inc contador
            mov ax, si
            mov caracter, al
            lea dx, msglinea1
            mov ah, 09h
            int 21h
            mov dl, caracter
            xor ax, ax
            mov ah, 02h
            int 21h
            lea dx, msglinea2
            xor ax, ax
            mov ah, 09h
            int 21h
            push di
            push si
            mov ax, caracteres[di]
            mov bx, 10
            xor dx, dx
            xor di, di
            call ImpNum
            pop si
            pop di
            inc di
            inc di
            inc si
            nlcr
            cmp si, 254
            je final
            cmp contador, 20
            je  pidetecla
            jmp linea
    
    noimprime:
            inc di
            inc di
            inc si
            cmp si, 254
            je final
            jmp linea
    
    pidetecla:
            mov contador, 0 ;;;;
    ;;;; You want to wait for a key after each 20 lines, not just after the first 20
            lea dx, msgtecla
            xor ax, ax
            mov ah, 09h
            int 21h
            xor ax, ax
            mov ah, 08h
            int 21h
            nlcr
            jmp linea
    
    final:
            xor ax, ax              ;Limpia el al y prepara el ah para la salida.
            mov ax, 4c00h           ;Servicio AH=4c int 21h para salir del programa.
            int 21h                 ;Llamada al DOS. Termine el programa.
    
    CSeg EndS                       ;Fin del segmento de codigo.
    
    End inicio                      ;Fin del programa la etiqueta al final dice en que punto debe comenzar el programa.
    

相关问题