2015-11-24 8 views
2

Я пытаюсь сделать программу TASM, которая может взять строку из файла, проверьте, имеет ли она более 5 символов, проверьте, является ли это палиндром, а затем выводит, является ли это палиндром. Моя программа до сих пор может сказать, когда нужно вывести справки, прочитать файл и вывести ответ. Мои проблемы двоякие:TASM последняя буква и длина строки

1) Как вы указываете на последнюю букву строки в TASM? Моя проверка палиндрома работает, сравнивая первую и последнюю буквы, проверяя, совпадают ли они, если они затем переместились на 1 и вниз на 1, проверьте эти 2 и т. Д. Если какие-либо два не совпадают, это не палиндром.

2) Как вы проверяете, чтобы линия, о которой идет речь, составляет как минимум 6 букв/цифр?

Для справки, вот код до сих пор:

.model small 
.stack 100H 
.data 

about  db 'Programa iesko palindromu nuskaitytoje eiluteje arba faile.',13,10,9,'2uzdasm.exe [/?] destinationFile [ - | sourceFile1 [sourceFile2] [...] ]',13,10,13,10,9,'/? - pagalba',13,10,'$' 

err_source  db 'Source failo nepavyko atidaryti skaitymui',13,10,'$' 
err_destination  db 'Destination failo nepavyko atidaryti rasymui',13,10,'$' 

sourceF  db 12 dup (0) 
sourceFHandle dw ? 

destF  db 12 dup (0) 
destFHandle  dw ? 

buffer  db 2000 dup (?) 
simbolis db ? 

palindromas db 'Tai yra palindromas',13,10,'$' 
nepalindromas db 'Tai nera palindromas',13,10,'$' 

.code 

START: 
mov ax, @data 
mov es, ax 

mov si, 81h 

call space_skip 

    mov al, byte ptr ds:[si] ; nuskaityt simboli 
    cmp al, 13   ; ner parametru, tai tada 
    jne _1 
    jmp help   ; pagalba 

_1: 

    ;; ar /? yra 
    mov ax, word ptr ds:[si] 
    cmp ax, 3F2Fh   ; jei nuskaityta "/?" - 3F = '?'; 2F = '/' 
    jne _2 
    jmp help     ; rastas "/?", vadinasi reikia isvesti pagalba 


_2: 

    ;; destination failo pavadinimas 
    lea di, destF 
    call read_filename  ; perkelti is parametro i eilute 
    cmp byte ptr es:[destF], '$' ; jei nieko nenuskaite 
    jne _3 
    jmp help 

_3: 

    ;; source failo pavadinimas 
    lea di, sourceF 
    call read_filename  ; perkelti is parametro i eilute 

    push ds 
    push si 

    mov ax, @data 
    mov ds, ax 

    ;; rasymui 
    mov dx, offset destF ; ikelti i dx destF - failo pavadinima 
    mov ah, 3ch   ; isvalo/sukuria faila - komandos kodas 
    mov cx, 0   ; normal - no attributes 
    int 21h   ; INT 21h/AH= 3Ch - create or truncate file. 
       ; Jei nebus isvalytas - tai perrasines senaji, 
       ; t.y. jei pries tai buves failas ilgesnis - like simboliai isliks. 
    jnc _4   ; CF set on error AX = error code. 
    jmp err_dest 

_4: 
    mov ah, 3dh   ; atidaro faila - komandos kodas 
    mov al, 1   ; rasymui 
    int 21h   ; INT 21h/AH= 3Dh - open existing file. 
    jnc _5   ; CF set on error AX = error code. 
    jmp err_dest 

_5: 
    mov destFHandle, ax  ; issaugom handle 

    jmp startConverting 

readSourceFile: 
    pop si 
    pop ds 

    ;; source failo pavadinimas 
    lea di, sourceF 
    call read_filename  ; perkelti is parametro i eilute 

    push ds 
    push si 

    mov ax, @data 
    mov ds, ax 

    cmp byte ptr ds:[sourceF], '$' ; jei nieko nenuskaite 
    jne startConverting 
    jmp closeF 

startConverting: 
    ;; atidarom 
    cmp byte ptr ds:[sourceF], '$' ; jei nieko nenuskaite 
    jne source_from_file 

    mov sourceFHandle, 0 
    jmp skaitom 

source_from_file: 
    mov dx, offset sourceF ; failo pavadinimas 
    mov ah, 3dh     ; atidaro faila - komandos kodas 
    mov al, 0     ; 0 - reading, 1-writing, 2-abu 
    int 21h   ; INT 21h/AH= 3Dh - open existing file 
    jc err_sourc  ; CF set on error AX = error code. 
    mov sourceFHandle, ax ; issaugojam filehandle 

skaitom: 
    mov bx, sourceFHandle 
    mov dx, offset buffer  ; address of buffer in dx 
    mov cx, 20    ; kiek baitu nuskaitysim 
    mov ah, 3fh    ; function 3Fh - read from file 
    int 21h 

    mov cx, ax    ; bytes actually read 
    cmp ax, 0   ; jei nenuskaite 
    jne _6   ; tai ne pabaiga 

    mov bx, sourceFHandle ; pabaiga skaitomo failo 
    mov ah, 3eh   ; uzdaryti 
    int 21h 
    jmp readSourceFile  ; atidaryti kita skaitoma faila, jei yra 

_6: 
    mov si, offset buffer ; skaitoma is cia 
    mov bx, destFHandle  ; rasoma i cia 

    cmp sourceFHandle, 0 
    jne _7 
    cmp byte ptr ds:[si], 13 
    je closeF 

_7: 
    push cx   ; save big loop CX 

atrenka: 
    lodsb    ; Load byte at address DS:(E)SI into AL 
    push cx   ; pasidedam cx 
    call palloop 
    mov ah, 40h   ; INT 21h/AH= 40h - write to file 
    int 21h 
    pop cx 
    jc help   ; CF set on error; AX = error code. 
    loop atrenka 

    pop cx 
    loop skaitom 

help: 
    mov ax, @data 
    mov ds, ax 

    mov dx, offset about   
    mov ah, 09h 
    int 21h 

    jmp _end 

closeF: 
    ;; uzdaryti dest 
    mov ah, 3eh   ; uzdaryti 
    mov bx, destFHandle 
    int 21h 

_end: 
    mov ax, 4c00h 
    int 21h 

err_sourc: 
    mov ax, @data 
    mov ds, ax 

    mov dx, offset err_source   
    mov ah, 09h 
    int 21h 

    mov dx, offset sourceF 
    int 21h 

    mov ax, 4c01h 
    int 21h 

err_dest: 
    mov ax, @data 
    mov ds, ax 

    mov dx, offset err_destination   
    mov ah, 09h 
    int 21h 

    mov dx, offset destF 
    int 21h 

    mov ax, 4c02h 
    int 21h 

space_skip PROC near 

space_skip_loop: 
    cmp byte ptr ds:[si], ' ' 
    jne space_skip_end 
    inc si 
    jmp space_skip_loop 
    space_skip_end: 
    ret 

    space_skip ENDP 

    read_filename PROC near 

    push ax 
    call space_skip 

read_filename_start: 
    cmp byte ptr ds:[si], 13 ; jei nera parametru 
    je read_filename_end ; tai taip, tai baigtas failo vedimas 
    cmp byte ptr ds:[si], ' ' ; jei tarpas 
    jne read_filename_next ; tai praleisti visus tarpus, ir sokti prie kito parametro 
    read_filename_end: 
    mov al, '$'   ; irasyti '$' gale 
    stosb       ; Store AL at address ES:(E)DI, di = di + 1 
    pop ax 
    ret 
    read_filename_next: 
    lodsb    ; uzkrauna kita simboli 
    stosb       ; Store AL at address ES:(E)DI, di = di + 1 
    jmp read_filename_start 

    read_filename ENDP 

palloop PROC near 
    mov  al, [si] 
    ;mov  [di], al 
    cmp  al, [di] 
    jne  notpal 
    inc  si 
    dec  di 
    cmp  si, di 
    jl  palloop 
    jmp  ispal 

notpal: 
    lea dx, nepalindromas 
    mov cx, 20 
    ret 

ispal: 
    lea dx, palindromas 
    mov cx, 20 
    ret 

    palloop ENDP 

    end START 

ответ

0

Я думаю,

mov bx, sourceFHandle 
mov dx, offset buffer ; address of buffer in dx 
mov cx, 20    ; kiek baitu nuskaitysim 
mov ah, 3fh    ; function 3Fh - read from file 
int 21h 

будет вам неприятности. Попробуйте создать программу C с fread(buffer,1,20,sourceFHandle), и вы увидите, что организация буфера довольно сложна (что делать с обработанными данными? Overflow?).

Предлагаю прочитать строку и только строку («fgets»). Линия может заканчиваться символом 0x0D (Возврат каретки = CR) или 0x0Ah (Line Feed = LF) или EOF (Конец файла). MS-DOS использует для новой линии, как правило, комбинацию обоих (CRLF). В MS-DOS нет функции для чтения строки до одного из этих разделителей, поэтому вам нужно прочитать символ по символу и сравнить его с условием прерывания. Поскольку дескриптор имеет собственный буфер и ему удается получить блок данных с диска, это не является большой проблемой производительности.

Пример:

... 
read_line PROC 
    lea di, buffer 
    dec di 

    @@0:      ; Read until CR or LF 
    inc di 
    mov ah, 3Fh     ; READ FROM FILE OR DEVICE 
    mov bx, sourceFHandle  ; File handle 
    mov dx, di     ; Buffer for data 
    mov cx, 1     ; Read one character 
    int 21h      ; Call MS-DOS 
    jc @@done     ; Error 
    test ax, ax     ; EOF 
    je @@done 

    mov al, [di]    ; Fetched character 
    cmp al, 0Dh     ; CR? 
    je @@1      ; Yes: break 
    cmp al, 0Ah     ; LF? 
    jne @@0      ; No: loop 

    @@1:      ; Read until NOT CR or LF (skip empty lines) 

    mov ah, 3Fh     ; READ FROM FILE OR DEVICE 
    mov bx, sourceFHandle  ; File handle 
    mov dx, di     ; Buffer for data 
    mov cx, 1     ; Read one character 
    int 21h      ; Call MS-DOS 
    jc @@done     ; Error 
    test ax, ax     ; EOF 
    je @@done 

    mov al, [di]    ; Fetched character 
    cmp al, 0Dh     ; CR? 
    je @@1      ; Yes: loop 
    cmp al, 0Ah     ; LF? 
    je @@1      ; Yes: loop 

    ; Adjust file pointer, so that it points to the beginning of the next line 

    mov ah, 42h     ; LSEEK - SET CURRENT FILE POSITION 
    mov al, 1     ; Move from current file position 
    mov bx, sourceFHandle  ; File handle 
    mov dx, -1     ; Move by CX:DX = -1 bytes 
    mov cx, dx     ; CX:DX = FFFF:FFFF 
    int 21h      ; Call MS-DOS 

    @@done: 
    test ax, ax     ; AX == 0 && DI == &buffer[0] => EOF 
    jne @@2 
    cmp di, OFFSET buffer 
    @@2: 
    mov byte ptr [di], '$' 
    ret       ; DI: pointer to '$'. ZF==1: EOF. 
read_line ENDP 
... 

С DI указывает на $ -Delimiter линии, можно вычислить длину строки путем вычитания смещения буфера (например sub di, OFFSET buffer). Сокращение DI от одного приводит вас к последнему письму.

ОТВЕТ: Легче для посторонних помочь, когда вы программируете более структурированные: больше процедур, меньше прыжков.

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

  • Нет связанных вопросов^_^