У меня странная проблема с моим ASM-кодом, запущенным в DOSBox.Я написал следующий код:
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 строк указанного файла.Однако при выполнении моего кода моя программа, кажется, сливается с какой-то другой программой, то есть за командами в моем коде следуют некоторые другие команды, совершенно чуждые моему коду.Вот пример: Мой код находится слева, а вывод дизассемблера - справа.Вы можете видеть, что из sub cx, 0Fh
следующие команды являются чем-то другим, а остальная часть этого кода заканчивается на iret
, что приводит к бесконечному циклу.
Я использую NASM версии 2.12.01 и собираю исполняемые файлы для DOS через nasm -f bin example.asm -o example.com
.Я использую DOSBox версии 0.74 для выполнения собранных программ.