我在DOSBox中启动的ASM代码遇到了一个奇怪的问题。我写了以下代码:
section .text
global start
start:
; Getting command line arguments
xor si, si
xor ax, ax
mov byte [st], 0
mov al, [ds:80h] ; Getting arguments' string length
mov si, ax ; Storing in index register
mov byte [ds:81h+si], 0 ; Adding string termination symbol
; Opening file
mov dx, 82h ; Filename address
mov al, 0 ; Read-only mode
mov ah, 3Dh ; Calling 3Dh interrupt
int 21h
jc exit
mov bx, ax
; Calculating number of lines
mov cx, 0 ; Zeroing counter
calclp: lea dx, [buf] ; Getting buffer address
mov ah, 3Fh ; Calling read
push cx ; Storing counter
mov cx, 40 ; Reading 40 bytes
int 21h ; Calling interrupt
cmp ax, 0 ; If ax = 0, no symbols were read -> EOF, exiting
je findlast
add dx, ax
mov bp, dx
mov byte [ds:bp], 0 ; Putting zero at the end of the string
pop cx ; Restoring cx
xor si, si ; Zeroing index
lea bp, [buf] ; Getting buffer address
calcchlp: mov dl, [bp+si] ; Getting char from buffer
inc si
cmp dl, 0 ; If zero - end of buffer
je calclp ; Reading another 40 bytes
cmp dl, 0Ah ; If newline - incrementing counter
jne calcchlp ; If not - continuing loop
inc cx
jmp calcchlp
findlast: pop cx
lea bp, [ln] ; Saving the result
mov [bp], cx
lea bp, [lastb] ; Zeroing lastb
mov word [bp], 0
mov word [bp+2], 0
sub cx, 0Fh
cmp cx, 0 ; If number of lines =< 15, the first and the last 15 lines are the same
jle clear ; In that case, simply exiting, leaving lastb = 0
mov ah, 42h ; Resetting file pointer to the start of the file
mov al, 0h
mov cx, 0
mov dx, 0
int 21h
flcalclp: lea dx, [buf] ; Getting buffer address
mov ah, 3Fh ; Calling read
push cx ; Storing line counter
mov cx, 40 ; Reading 40 bytes
int 21h ; Calling interrupt
cmp ax, 0 ; If ax = 0, no symbols were read -> EOF, though we should not reach EOF here
je exit ; In that case, it's error - exiting
add dx, ax
mov bp, dx
mov byte [ds:bp], 0 ; Putting zero at the end of the string
pop cx ; Restoring cx
xor si, si ; Zeroing index
lea bp, [buf] ; Getting buffer address
flchlp: mov dl, [bp+si] ; Getting char from buffer
inc si
cmp dl, 0 ; If zero - end of buffer
je flcalclp ; Reading another 40 bytes
cmp dl, 0Ah ; If newline - decrementing counter
jne flchlp ; If not - continuing loop
dec cx
cmp cx, 0 ; If counter = 0, we reached 15th line from the end
je getlastb ; Jumping to finding actual byte number
jmp flchlp
; Calling seek to find the exact byte number
getlastb: mov ah, 42h ; Seek call
mov al, 1h ; Seeking from the current position
mov cx, 0 ; Offset = 0
mov dx, 0
int 21h
jc exit
lea bp, [lastb] ; DX:AX contains offset from the start, storing it
mov [bp], ax
mov [bp+2], dx
mov ah, 42h ; Resetting file pointer to the start of the file
mov al, 0h
mov cx, 0
mov dx, 0
int 21h
; Clearing the screen
clear: mov al, 03h ; 80x25, 16 colors video mode
mov ah, 0h ; Enabling video mode
int 10h
; Printing 15 lines
mov cx, 15 ; Line counter for 15 lines
printlp: lea dx, [buf] ; Getting buffer address
mov ah, 3Fh ; Read function
push cx ; Saving cx
mov cx, 40 ; Number of bytes to read
int 21h ; Reading into buffer
cmp ax, 0
je keyproc
add dx, ax
mov bp, dx
mov byte [ds:bp], 0 ; Putting zero at the end of the string
pop cx ; Restoring cx
xor si, si ; Zeroing index
lea bp, [buf] ; Getting buffer address
charlp: mov dl, [bp+si] ; Getting char from buffer
cmp dl, 0 ; Checking if symbol is zero
je printlp ; If it is, reading another line
cmp dl, 0Ah ; Checking if symbol is newline
jne printch ; If it's not, jumpt to printing it
dec cx ; Decrementing line counter
cmp cx, 0 ; Checking if counter = 0
je keyproc ; If it is, we printed all the lines, exit loop
printch: mov ah, 02h ; Calling stdout write
int 21h
inc si ; Incrementing index
jmp charlp
keyproc: mov ah, 0 ; Waiting for a key to be pressed
int 16h
cmp al, 20h ; if space, swap state
je swap
cmp al, 71h ; if q, quit
jne keyproc
mov ax, 0 ; exit code 0
jmp exit
swap: cmp byte [st], 0 ; Checking state variable
je toend ; If it's 0, jumping to the last 15 lines, otherwise to the first
tostart: mov byte [st], 1 ; Swapping state
mov ah, 42h ; Calling seek file
mov al, 0 ; From the beginning
mov cx, 0 ; Offset is 0
mov dx, 0
int 21h
jc exit ; If error - exit
jmp clear ; If not - clearing screen and printing text
toend: mov byte [st], 0 ; Swapping state
mov ah, 42h
mov al, 0 ; From the start
lea bp, [lastb]
mov cx, [bp+16] ; Offset was calculated before
mov dx, [bp]
int 21h
jc exit
jmp clear
exit: mov ah, 4Ch
int 21h
section .bss
buf: resb 40 ; Text buffer
st: resb 1 ; State variable
ln: resw 1 ; Number of lines
lastb: resd 1 ; Number of the fist byte of the last 15 lines
基本上,我正在尝试计算某个文件中的行数,然后在显示该文件的前15行和后15行之间快速切换。但是,在执行我的代码时,我的程序似乎与其他程序合并,即代码中的命令后面跟随着一些完全与我的代码无关的其他命令。这是示例:
https://serverfault.com/questions/796674/block-masking-url-from-nginx/
我的代码在左侧,反汇编程序输出在右侧。您可以从sub cx, 0Fh
中看到以下命令,而其他代码以iret
结尾,从而导致无限循环。
我正在使用NASM版本2.12.01,并通过nasm -f bin example.asm -o example.com
为DOS汇编可执行文件。我使用DOSBox 0.74版执行汇编程序。