程序集 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
我希望你能看懂这段代码是怎么回事,如果不明白,我可以解释给你听。如果有任何帮助,我将不胜感激!
下面显示了使用 lodsb
和 loop
的版本,并整理了一些其他内容。我添加了一些额外的内容来打印找到的每个小字母的索引。我没有检查这个愚蠢的错误,因为我没有设置 运行 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
我正在做一项作业,但不知何故卡住了。 这是代码的一部分,肯定是错误的。实际上错误的是,当程序应该打印数字时(通过过程 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
我希望你能看懂这段代码是怎么回事,如果不明白,我可以解释给你听。如果有任何帮助,我将不胜感激!
下面显示了使用 lodsb
和 loop
的版本,并整理了一些其他内容。我添加了一些额外的内容来打印找到的每个小字母的索引。我没有检查这个愚蠢的错误,因为我没有设置 运行 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