为什么我在获取和显示字符串中的字符时会得到意想不到的结果?

Why am I getting unexpected results when getting and displaying a character from a string?

我正在尝试获取字符串的第二个字符(例如 Test 中的 e)。使用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 second character of 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,如果我试图引用细绳?还是我使用的方法被误导了?

str[si]不是某种type/array访问,但它会像[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
...

您应该使用一些调试器并观察内存、寄存器和汇编指令中的值,以更好地了解这些在 CPU 中的工作方式,segment:offset 寻址如何用于访问x86 的 16b 实模式内存等...