MS-DOS Debugger, перейти к следующей ячейке памяти
Я использую DosBox, и у меня есть строка, считанная из буфера с использованием прерывания. Я знаю, где первый символ хранится в памяти, как мне перейти к следующему символу?
0100 mov ah, 0a
0102 mov dx, 111
0105 int 21
0107 mov dl, [113] ;first character here
010b mov ah, 02
010d int 21
010f int 20
0111 db 0f
Вопрос в том, как мне перейти к следующему символу в строке? Если я введу строку "Привет", а затем использовать inc dl
это просто дает мне букву "я" вместо "е".
1 ответ
Вам нужно выбрать регистр, чтобы указать на текущий символ. Как только вы это сделаете, есть инструкции для продвижения вашего указателя, а также инструкции для чтения байта, на который указывает указатель.
Поскольку вы не знаете, сколько символов будет прочитано пользовательской функцией ввода, и вы хотите, чтобы эта функция работала с любым вводимым значением, вам понадобится какой-то цикл, чтобы вы печатали только столько символов, сколько было прочитано, хотя, если вы хотите сделать это проще, вы можете сделать так, чтобы он печатал только первые 3 символа независимо от того, что было напечатано. Я собираюсь предположить, что вы хотите распечатать именно то, что было введено пользователем.
Хороший способ справиться с этим - использовать инструкцию LOOP, которая повторяет (переходит в) тело цикла на счетчик, который был помещен в регистр CX. Поскольку функция пользовательского ввода дает нам количество символов, все, что нам нужно сделать, это прочитать это в нижнюю часть регистра CX (CL) для инициализации цикла. Нам также понадобится указатель для указания на текущий символ. Оказавшись в теле цикла, мы просто прочитаем любой символ по указателю "текущий символ" и затем вызовем функцию печати символов DOS, чтобы вывести его на консоль. Затем мы можем перемещать указатель и LOOP, пока все символы не будут выполнены. Обратите внимание, что каждый раз, когда встречается инструкция LOOP, CX уменьшается до тех пор, пока не достигнет нуля. Как только он становится равным нулю, LOOP больше не прыгает обратно в тело и просто переходит к инструкции, следующей за LOOP.
ПРИМЕЧАНИЕ. Если вы не выводите CRLF после чтения пользовательского ввода, перевод строки не будет выполняться, и новый вывод будет перезаписан в том месте, где ввод был прочитан на консоли. Фактически это будет выглядеть так, будто ничего не произошло.
Вот ваш модифицированный образец:
0100 MOV AH,0A
0102 MOV DX,0123
0105 INT 21 ;input string using buffer at 0123
0107 MOV DX,0120
010A MOV AH,09
010C INT 21 ;output CRLF sequence first
010E MOV SI,0124 ;point SI at byte containing chars read
0111 XOR CX,CX ;CX = 0
0113 MOV CL,[SI] ;CX = chars_read
0115 INC SI ;mov SI to next char to display
0116 MOV DL,[SI] ;DL = character SI is pointing at
0118 MOV AH,02
011A INT 21 ;display character
011C LOOP 0115 ;loop back to INC instruction until no more chars left
011E INT 20 ;exit
0120 DB 0D ;CR
0121 DB 0A ;LF
0122 DB 24 ;"$" DOS string terminator
0123 DB 20 ;buffer start; max characters = 32
0124 DB 00 ; chars read goes here
0125 DB 00 ; input chars are read here