Почему я получаю неожиданные результаты при получении и отображении символа из строки? - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь получить второй символ строки (например, e в Test). Использование emu8086 для компиляции.

Когда я делаю:

str db 'Test$'
...
mov si, 1       ; get second character of str
mov bl, str[si] ; store the second character

mov ah, 2       ; display the stored character
mov dl, bl
int 21h

Вывод e.

Но когда я это сделаю:

str db 25
    db ?
    db 25 dup (?)
...
mov ah, 0ah         ; accept a string
lea dx, str         ; store input in variable str
int 21h

mov si, 1           ; get second character of str (??)
mov bl, str[si]     ; store the second character

mov ah, 2           ; display the stored character
mov dl, bl
int 21h

Я получаю .

Когда я изменяю часть второго фрагмента "get Второй символ str" на эту:

mov si, 3               ; get second character of str (why is it '3' instead of '1'?)
mov bl, str[si]         ; store the second character

Я получаю e.

Я не понимаю. Хотя это работает в первом фрагменте, почему во втором фрагменте я установил SI в 3 вместо 1, если я пытаюсь сослаться на второй символ строки? Или метод, который я использую, ввел в заблуждение?

1 Ответ

0 голосов
/ 03 сентября 2018

str[si] не является своего рода доступом к типу / массиву, но он преобразуется в операнд памяти команд, например [si+1234], где «1234» смещено, где метка str указывает в памяти.

А во втором примере метка str указывает на байт со значением 25 (максимальная длина буфера), затем str+1 указывает на возвращенный байт входной длины (это значение , которое вы получите на выходе, если вы попробуйте распечатать его как символ), и str+2 указывает на первый символ пользовательского ввода. Таким образом, чтобы получить второй символ, вы должны использовать str+3 адрес памяти.

Память адресуется байтами, поэтому вы должны знать размер всех элементов в байтах или использовать больше меток, например:

str_int_0a:            ; label to the beginning of structure for "0a" DOS service
     db 25
     db ?
str:                   ; label to the beginning of raw input buffer (first char)
     db 25 dup (?)

Затем в коде вы используете правильную метку в зависимости от того, что вы хотите сделать:

...
mov ah, 0ah         ; accept a string
lea dx, str_int_0a  ; store input in memory at address str
int 21h

mov si, 1           ; index of second character of str
mov bl, str[si]     ; load the second character

mov ah, 2           ; display the stored character
mov dl, bl
int 21h
...

Вы должны использовать некоторый отладчик и наблюдать значения в памяти, а также регистры и собранные инструкции, чтобы лучше понять, как они работают внутри ЦП, как сегментная адресация используется для доступа к памяти в реальном режиме 16b x86, и т.д ...

...