#assembly #dos #x86-16 #tasm
#сборка #dos #x86-16 #tasm
Вопрос:
У меня возникли проблемы со сравнением двух значений в 64-разрядной версии Windows 10 TASM. Я пытаюсь отобразить последние N строк файла (я не включил весь код, но предполагаю, что обработка файла правильная, я могу предоставить полный код, если необходимо), поэтому я создал процедуру (READN), которая считывает N из входных данных.
N DW 3
LINES DW 0
READN PROC NEAR
MOV AX, @DATA
MOV DS, AX
MOV DI, N
MOV AH, 1
INT 21H
MOV N, AX
XOR AX, AX
MOV AX, N
MOV DX, AX
MOV AH, 2
INT 21H
RET
READN ENDP
Затем я подсчитываю количество строк в данном файле в процедуре COUNTLINES, увеличивая СТРОКИ каждый раз, когда появляется ‘ n’ или
COUNTLINES PROC NEAR
MOV AH,3FH ;read from file function
MOV BX,HANDLE ;load file handle
LEA DX,FBUFF ;set up pointer to data buffer
MOV CX,1 ;read one byte
INT 21H ;DOS call
CMP AX,0 ;were 0 bytes read?
JZ EOFF ;yes, end of file found
MOV DL,FBUFF ;no, load file character
CMP DL,1AH ;is it Control-Z <EOF>?
JZ EOFF ;jump if yes
CMP DL,0AH ;is it n ?
JZ INCR ;jump if yes
JMP COUNTLINES ;and repeat
MOV AH,9 ;display string function
INT 21H ;DOS call
STC ;set error flag
EOFF: inc DS:[LINES]
XOR AX, AX
MOV AX, LINES
ADD AX, '0'
SUB AX, N
MOV N, AX
MOV LINES, 0
MOV AX, N
MOV DX, AX
MOV AH, 2
INT 21H
CALL CLOSEFILE
CALL OPENFILE
RET
INCR: INC DS:[LINES]
JMP COUNTLINES
COUNTLINES ENDP
И, наконец, проблема, с которой я сталкиваюсь, заключается в процедуре DISPLAYLINES, где я снова увеличиваю СТРОКИ с нуля, но на этот раз, когда СТРОК становится меньше N, я начинаю распечатывать строки. Проблема в том, что мое сравнение (в части INCREM: ) работает не так, как я ожидал, и когда я пытаюсь сравнить N и СТРОКИ (сначала я переношу СТРОКИ в AX), программа просто никогда не переходит к нужной функции, хотя значения в какой-то момент должны быть равны. Если бы вы могли попытаться выяснить, почему это происходит, или, возможно, даже предоставить исправление, я был бы очень благодарен.
DISPLAYLINES PROC NEAR
MOV AH,3FH ;read from file function
MOV BX,HANDLE ;load file handle
LEA DX,FBUFF ;set up pointer to data buffer
MOV CX,1 ;read one byte
INT 21H ;DOS call
CMP AX,0 ;were 0 bytes read?
JZ EOF ;yes, end of file found
MOV DL,FBUFF ;no, load file character
CMP DL,1AH ;is it Control-Z <EOF>?
JZ EOF ;jump if yes
CMP DL,0AH ;is it n ?
JZ INCREM ;jump if yes
JMP DISPLAYLINES ;and repeat
EOF: RET
INCREM: INC DS:[LINES]
MOV AX, LINES
CMP AX, N
JZ PRINT
JMP DISPLAYLINES
PRINT: MOV AH,3FH ;read from file function
MOV BX,HANDLE ;load file handle
LEA DX,FBUFF ;set up pointer to data buffer
MOV CX,1 ;read one byte
INT 21H ;DOS call
CMP AX,0 ;were 0 bytes read?
JZ EOF ;yes, end of file found
MOV DL,FBUFF ;no, load file character
CMP DL,1AH ;is it Control-Z <EOF>?
JZ EOF ;jump if yes
MOV AH,2 ;display character function
INT 21H ;DOS call
JMP PRINT ;and repeat
DISPLAYLINES ENDP
Комментарии:
1. Открыт ли файл? Чтение выполнено успешно?
INCREM
Действительно вызывается?2. да, да, и я не понимаю третий вопрос
3. В этом коде-спагетти много ошибок. Ваша проблема в основном основана на
MOV N, AX
inREADN
.Int 21/AH=01h
возвращает результирующий символ ASCII вAL
и случайное значение вAH
. Итак, поместитеxor ah,ah
прямо передMOV N, AX
. Возможно, сегодня вечером я смогу написать полный ответ.4. @rkhb это действительно спагетти-код: DD Я очень новичок в сборке, так что потерпите меня, пожалуйста. Я обязательно попробую ваше предложение.
Ответ №1:
readn
MOV AH, 1 INT 21H MOV N, AX
Эта функция DOS возвращает символ! Вместо этого вам нужно значение. Лучше напишите
MOV AH, 1
INT 21H
sub al, '0'
mov ah, 0
MOV N, AX
количество строк
MOV AX, LINES ADD AX, '0' SUB AX, N MOV N, AX
Здесь ADD AX, '0'
было несколько необходимо из-за предыдущей ошибки. Теперь вы можете просто записать
MOV AX, LINES
SUB AX, N
MOV N, AX
строки отображения
Раньше это не удавалось, потому что в коде readn был старший байт 1 в переменной N. Это, в свою очередь, привело к появлению очень большого нового N после приведенного выше вычитания строк подсчета. Вот почему печать так и не произошла!
Внесите оба исправления, и вы увидите, что сбой больше не происходит…
Ответ №2:
Если вы добавите директиву IDEAL в начале вашего исходного файла, а затем замените все команды непосредственными значениями с явно указанными значениями ‘offset’ или в квадратных скобках — вы решите все свои проблемы. Если, конечно, вы используете borland turbo assembler.