You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于LEA指令操作SI寄存器与数据段变量的代码逻辑疑问

8086汇编子串检测代码执行逻辑解析

问题背景

现有一段8086汇编代码,功能是检查用户输入字符串中是否存在子串ktmt。存在几个疑问:

  • main过程中lea si, inputstring是让SI持有inputstring的偏移地址,但经过getstring后,SI的值却等于输入字符数,这是怎么回事?
  • findstringktmt子程序中把SI的值移入CX后,CX为何能表示输入字符串的字符数?
  • 整段代码的完整执行逻辑是怎样的?

完整汇编代码

.model small

.data
    inputstring db 100 dup('?')
    findstring  db 'ktmt'
    result      db 0
    crlf        db 13, 10, '$'      ;回车换行符

.code  

;读取单个字符的子函数
getchar:
    mov ah, 1
    int 21h
    ret
    
;从屏幕读取字符串的子函数
getstring:
    call getchar
    inc si
    mov [inputstring + si], al
    cmp al, '#'
    jne getstring
    ret

;检查输入字符串中是否存在'ktmt'的子函数
findstringktmt: 
    mov cx, si
    lea si, inputstring + 1
    lea di, findstring
    mov bh, 0
    
    find:
        mov al, [si]
        mov bl, [di]
        cmp bl, al
        je  if_equal
        lea di, findstring - 1
        mov bh, -1
        if_equal:
            inc di
            inc bh
            cmp bh, 4
            je  found
        inc si
        loop find
    
    ret
    found:
        mov [result], 1
    ret
    
;输出结果到屏幕的子函数
printresult:
    mov ah, 9
    lea dx, crlf
    int 21h
    mov dl, [result]
    add dx, 48
    mov ah, 2
    int 21h
    ret
    
main proc
    mov ax, @data
    mov ds, ax
    lea si, inputstring
    call getstring
    call findstringktmt
    call printresult
    int 20h
main endp
end main

逐阶段执行逻辑解析

1. 程序初始化与字符串输入阶段

  • 初始化:main过程中mov ax, @data; mov ds, ax把数据段的段地址加载到DS寄存器,确保后续访问.data段的变量时地址正确。lea si, inputstring将inputstring在数据段的偏移地址(通常为0x0000)加载到SI。
  • 字符串输入(getstring):
    • 每次调用getchar,通过int 21h AH=1读取用户输入的字符(字符存在AL中,同时自动回显到屏幕)。
    • 执行inc si:SI从初始的偏移地址开始,每输入一个字符就自增1。比如输入第一个字符后,SI从0x0000变成0x0001;输入第二个字符后变成0x0002,以此类推。
    • mov [inputstring + si], al:把输入的字符存储到inputstring对应的偏移位置(比如SI=0x0001时,存储到inputstring+1的位置)。
    • 检查输入字符是否为#,如果不是就循环继续读取;输入#时停止,此时SI的数值恰好等于输入的总字符数(包括#)。

2. 子串检测阶段(findstringktmt)

  • 初始化检测参数:
    • mov cx, si:把SI中存储的输入字符总数赋值给CX,作为后续loop指令的循环次数(遍历所有输入字符)。
    • lea si, inputstring + 1:让SI指向输入字符串的第一个有效字符(因为inputstring的初始位置存的是默认值?,第一个输入字符存在inputstring+1的位置)。
    • lea di, findstring:让DI指向待匹配子串ktmt的第一个字符。
    • mov bh, 0:用BH寄存器记录当前匹配成功的子串字符数,初始为0。
  • 遍历匹配逻辑:
    • 进入find循环,每次取出SI指向的输入字符(AL)和DI指向的子串字符(BL)进行比较:
      • 如果字符相等,直接进入if_equal;如果不相等,把DI重置到findstring - 1(后续inc di会回到子串起始位置),同时把BH设为-1(后续inc bh会回到0,重置匹配计数)。
      • if_equal中:DI自增指向下一个待匹配的子串字符,BH自增1(匹配计数+1)。
      • 检查BH是否等于4:因为子串ktmt共4个字符,等于4说明完全匹配,跳转到found标签,把result设为1(表示找到子串)。
    • SI自增指向下一个输入字符,执行loop find:CX自减1,若CX不为0则继续循环。
  • 循环结束:如果遍历完所有字符都没匹配成功,直接执行ret返回,result保持初始值0。

3. 结果输出阶段(printresult)

  • 先通过int 21h AH=9输出回车换行符(crlf)。
  • 把result的值(0或1)加上48,转换成ASCII字符(0→'0',1→'1'),然后通过int 21h AH=2输出到屏幕,展示检测结果。

关键疑问解答

  • 为何SI的值等于输入字符数?:因为getstring中SI从inputstring的偏移地址(通常为0)开始,每输入一个字符就自增1,输入结束时SI的数值刚好等于输入的总字符数,这是这段代码的特殊逻辑设计,并非SI寄存器本身的属性。
  • 教材说SI持有实际地址?:这里的“实际地址”指的是逻辑地址——段地址存在DS寄存器中,SI是偏移地址,两者结合可计算出物理地址。而SI的数值恰好等于字符数,是代码执行后的结果,和它作为偏移地址的功能不冲突。

内容的提问来源于stack exchange,提问作者Dương Nguyễn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:36:10