2015-11-10 4 views
1

Хорошо, все, что я хочу сделать, просто читать по строкам из текста, а затем выводить его.x86 ASM - чтение строки за строкой


Вещи я:

  • Читать одиночный символ, добавьте в строку
  • Поиск LF
  • Выходная строка
  • Делайте сначала до EOF

Проблемы:

  • Не знаю, как считать сх для 40h прерывания в то время как он занят с 3FH (попытался сделать некоторые новые переменные, но в итоге с кучей ошибок)
  • Своего рода нечетным результат - несколько пустых строк и самый последний один

.txt пример

some 
    random 

    text 
.model small 

    .stack 100h 

    .data 
      filename db 255 dup(0) 
      text  db 255 dup(0) 
      char  db ? 
      line  db 255 dup(0)   

      filehandle dw ? 

    .code 
      newline macro ;NEW LINE 
          ; 
      mov dl, 10  ; 
      mov ah, 02h  ;     
      int 21h   ; 
          ; 
      mov dl, 13  ; 
      mov ah, 02h  ;      ; 
      int 21h   ;     
      endm    ;NEW LINE 
    main: 

      mov ax, @data  
      mov ds, ax 

      lea si, filename 
      mov ah, 01h  ;read character 

    char_input: 

      int 21h   

      cmp al, 0dh  ;enter  
      je zero_terminator 

      mov [si], al  
      inc si 

      jmp char_input 

    zero_terminator: 

      mov [si], 0 

    open_file: 

      lea dx, filename   
      mov al, 0   
      mov ah, 3Dh  ;open file 
      int 21h 

      mov filehandle, ax 

      lea si, text 

      newline 

    read_line: 
      mov ah, 3Fh  ;read file 
      mov bx, filehandle 
      lea dx, char   
      mov cx, 1 

      int 21h 

      cmp ax, 0  ;EOF    
      je EO_file 

      mov al, char   

      cmp al, 0ah  ; line feed 
      je LF 

      mov [si], al 
      inc si  

      jmp read_line: 

    EO_file: 

      lea dx, text 
      mov ah, 40h  ;print 
      mov cx, 255 
      mov bx, 1  
      int 21h 

      mov ah, 4ch  
      int 21h 

    LF:  
      lea dx, text 
      mov ah, 40h  ;print 
      mov cx, 255 
      mov bx, 1 

      int 21h 

      inc si 
      jmp read_line 

    end main 
+0

Вы, кажется, читает в текстовый файл один символ вовремя. Если вы просто собираетесь вывести все строки сразу в конце, почему бы не сделать один большой читать? У вас не хватает комментариев в вашем коде, поэтому я не знаю, что должны делать эти системные вызовы DOS. (Так как я, к счастью, никогда не писал код для DOS.) Комментирование номеров системных вызовов с именем syscall было бы хорошим началом. –

+0

Это не полная программа, просто ее начало. Позже мне придется найти строки из пользовательского ввода в каждой строке. – beingas

+0

Можете ли вы дождаться, пока будете читать файл до тех пор, пока не будет введен пользователь? Или, если вам нужно сохранить весь файл в памяти, вы, вероятно, должны иметь место для более чем 255 символов! Возможно, было бы полезно проклинать его на строки во время чтения и хранить массив смещений до начала каждой строки. Или вам просто придется обнаруживать новые строки «на лету» при поиске. Или вы упаковываете строки вместе с '' \ 0'', отделяя их вместо строк новой строки? Я не понял, как разработана ваша программа. –

ответ

3

Это означало, чтобы ты, не решить все ошибки в коде:

Вы имеете :

zero_terminator: 
     mov [si], 0 

Идея состоит в перемещении 0 байт в положение, на которое указывает SI. TASM не понимает, что вы хотите переместить один байт [SI], так что должно быть сказано явно, что это то, что вы собираетесь:

 mov byte ptr [si], 0 

У вас есть опечатка на этой линии с двоеточием на конец:

 jmp read_line: 

Оно должно быть:

 jmp read_line 

основная проблема с вашим кодом является то, что при переходе на печать символов прочитать в text, вам необходимо указать количество символов для печати в CX.Вы задаете 255 с кодом, как это:

LF: 
     lea dx, text 
     mov ah, 40h  ;print 
     mov cx, 255 

Поскольку SI содержит указатель последнего чтения символов, вы можете вычесть адрес (смещение) от текста от SI, чтобы получить количество символов в буфере. Так что выше, может быть изменен на:

LF: 
     lea dx, text 
     mov ah, 40h  ;print 
     mov cx, si  ;CX = # characters. Move pointer to last char to it 
     sub cx, dx  ;Subtract the offset of text (in DX) from CX 
         ;To get the actual number of chars in the buffer 

После того, как вы распечатать строку вы ИНК SI и вернуться к чтению символов. Так как вы распечатаны линию, вы можете также перезапустить с начала текста буфера путем сброса SI назад к началу с:

 mov si, dx ; start from beginning of buffer (DX=beginning of text buffer) 

или вы можете просто Mov DX который содержит смещение текста уже и установить SI к нему:

Это так же, как вы первоначально установить вещи в начале чтения данных.

EOF код у вас есть имеет аналогичный вопрос, где требуется количество байтов в буфере, чтобы быть помещены в ECX. Так что этот код:

EO_file: 

     lea dx, text 
     mov ah, 40h  ;print 
     mov cx, 255 
     mov bx, 1 
     int 21h 

Может быть изменено на:

LF: 
     lea dx, text 
     mov ah, 40h  ;print 
     mov cx, si  ;CX = # characters. Move pointer to last char to it 
     sub cx, dx  ;Subtract the offset of text (in DX) from CX 
         ;To get the actual number of chars in the buffer 

С учетом всех этих изменений вы получите программу, как:

.model small 
    .stack 100h 

    .data 
      filename db 255 dup(0) 
      text  db 255 dup(0) 
      char  db ? 
      line  db 255 dup(0) 

      filehandle dw ? 

    .code 
      newline macro ;NEW LINE 
          ; 
      mov dl, 10  ; 
      mov ah, 02h  ; 
      int 21h   ; 
          ; 
      mov dl, 13  ; 
      mov ah, 02h  ;      ; 
      int 21h   ; 
      endm    ;NEW LINE 
    main: 

      mov ax, @data 
      mov ds, ax 

      lea si, filename 
      mov ah, 01h  ;read character 

    char_input: 

      int 21h 

      cmp al, 0dh  ;enter 
      je zero_terminator 

      mov [si], al 
      inc si 

      jmp char_input 

    zero_terminator: 

      mov byte ptr [si], 0 

    open_file: 

      lea dx, filename 
      mov al, 0 
      mov ah, 3Dh  ;open file 
      int 21h 

      mov filehandle, ax 

      lea si, text 

      newline 

    read_line: 
      mov ah, 3Fh  ;read file 
      mov bx, filehandle 
      lea dx, char 
      mov cx, 1 

      int 21h 

      cmp ax, 0  ;EOF 
      je EO_file 

      mov al, char 

      cmp al, 0ah  ; line feed 
      je LF 

      mov [si], al 
      inc si 

      jmp read_line 

    EO_file: 

      lea dx, text ;DX=offset(address) of text 
      mov ah, 40h  ;print 
      mov cx, si  ;CX = # characters. Move pointer to last char to it 
      sub cx, dx  ;Subtract the offset of text (in DX) from CX 
          ;To get the actual number of chars in the buffer 
      mov bx, 1 
      int 21h 

      mov ah, 4ch 
      int 21h 

    LF: 
      lea dx, text ;DX=offset(address) of text 
      mov ah, 40h  ;print 
      mov cx, si  ;CX = # characters. Move pointer to last char to it 
      sub cx, dx  ;Subtract the offset of text (in DX) from CX 
          ;To get the actual number of chars in the buffer 
      mov bx, 1 

      int 21h 

      mov si, dx  ;Start from beginning of buffer 
          ;(DX=beginning of text buffer) 
      jmp read_line 

    end main 
+1

Отлично! 'mov si, dx' - это то, что мне действительно нужно! благодаря – beingas

Смежные вопросы