程序集 x86 - 计算文件中的小写字母

Assembly x86 - counting small letters in a file

我正在做一项作业,但不知何故卡住了。 这是代码的一部分,肯定是错误的。实际上错误的是,当程序应该打印数字时(通过过程 convertNumber,它工作正常!),它没有做任何事情,也没有 returns。就是没反应,必须手动关闭

read:
            mov ah, 3fh                 ; function for reading from file
            mov bx, handle              ; moving file handle to BX
            mov cx, 10000               ; how many bytes will be read
            mov dx, buffer              ; where the string will be saved
            int 21h                     ; system call ready

            mov bytesRead, 0            ; nulling my variable bytesRead, which represents how many bytes have been read
            mov bytesRead, ax           ; now moving the real value from AX

            cmp ax, 0                   ; if it is equal to 0, then there is nothing left to read                                                     
            je closeFile                ; close file

            mov cx, 0                   ; starting position

cycle:
            cmp cx, bytesRead           ; if I need to reload buffer
            jge read

            mov bx, 0                   ; nulling position counter
            mov bx, cx                  ; moving CX to BX -> mov ax, buffer[cx] was an illegal operation, so I did it this way
            mov ax, buffer[bx]          ; getting a character from BX. position from buffer

            cmp ax, 'a'
            jb next                     ; below 'a', skip
            cmp ax, 'z'
            ja next                     ; above 'z', skip
            inc count_task              ; if it passed, it is between 'a' and 'z'
            jmp next                    ; and moving on

next:
            inc cx                      ; increase position counter (always!)
            jmp cycle                   ; and repeat

finally:
            mov ax, count_task          ; move the final count to AX (needed by the procedure convertNumber)
            call convertNumber          ; convert number to its ASCII value (+48)
            ret

error_fopen:
            print fopenErr
            ret

error_fclose:
            print fcloseErr
            ret

closeFile:
            mov ah, 3eh
            mov bx, handle
            int 21h

            jc error_fclose
            jmp finally

convertNumber proc near
    push si

    mov buff, '$'
    lea si, buff
    mov cx, 10

conv:
    mov dx, 0
    div cx                          ; AX is being divided by CX, where value 10 is stored (direct dividing by 10 is not legal)
    add dx, 48                      ; getting ASCII value of the number (from 0 to '0')
    dec si                          ; going backwards
    mov [si], dl
    cmp ax, 0
    jz printNumber                  ; if AX is empty (0), print the number
    jmp conv                        ; else loop 

printNumber:
    mov ah, 9                       ; service to print string
    mov dx, si                      ; position of my string (number)
    int 21h

    pop si

    ret
convertNumber endp      

我希望你能看懂这段代码是怎么回事,如果不明白,我可以解释给你听。如果有任何帮助,我将不胜感激!

下面显示了使用 lodsbloop 的版本,并整理了一些其他内容。我添加了一些额外的内容来打印找到的每个小字母的索引。我没有检查这个愚蠢的错误,因为我没有设置 运行 DOS 中断。

此代码将处理长度超过 65535 字节的文件,但 "convertNumber" 子例程需要更新以打印长整数。

编辑:下面的格式假定 NASM 汇编器(实际使用的汇编器未在问题声明中提及)。

        mov     [count_task], 0
        mov     [count_task+2], 0
        mov     [index], 0
        mov     [index+2], 0
read:
        mov     ah, 3fh                 ; function for reading from file
        mov     bx, [handle]            ; moving file handle to BX
        mov     cx, 10000               ; how many bytes will be read
        mov     dx, buffer              ; where the string will be saved
        int     21h                     ; system call ready
        jc      error_read

        cmp     ax, 0                   ; if it is equal to 0, then there is nothing left to read
        je      finally                 ; print result and close

        ; This code assumes your ds segment register already points to your data

        lea     si, [buffer]
        mov     cx, ax                  ; starting loop counter
        cld                             ; clear direction flag (increment)
cycle:
        lodsb
        cmp     al, 'a'
        jb      next
        cmp     al, 'z'
        ja      next
        add     [count_task], 1
        adc     [count_task+2], 0

        ; Print the current index of the found small letter.
        ; Note it's assumed that convertNumber saves certain registers
        ; according to calling conventions. For example, if it uses "si"
        ; then it should save "si". AX, CX, and DX are fair game.
        ;
        push    cx
        mov     ax, [index]
        mov     dx, [index+2]
        call    convertNumber           ; print the index of the found small letter
        pop     cx
next:
        add     [index], 1              ; increment overall index
        adc     [index+2], 0
        loop    cycle                   ; and repeat

        jmp     read                    ; read another buffer full
finally:
        mov     ah, 3eh
        mov     bx, [handle]
        int     21h
        jc      error_fclose

        mov     ax, [count_task]        ; move the final count to DX:AX (needed by the procedure convertNumber)
        mov     dx, [count_task+2]
        call    convertNumber           ; convert number to its ASCII value (+48)
        ret

error_read:
        print   freadErr
        ret

error_fopen:
        print   fopenErr
        ret

error_fclose:
        print   fcloseErr
        ret