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

时间:2018-09-03 09:50:16

标签: string assembly character x86-16 emu8086

我正在尝试获取字符串的第二个字符(例如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

我得到

当我将第二个片段的“获取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 :(得分:0)

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
...

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