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

如何使用双寄存器寻址?汇编间接寻址代码执行问题排查

你的两个汇编问题解答

嘿,我来帮你拆解这两个汇编相关的问题,一步步给你讲清楚:


1. 如何使用两个寄存器进行寻址?

在32位x86汇编中,双寄存器寻址属于基址+变址寻址模式,它允许你结合两个寄存器的内容计算内存地址,常见的使用形式有两种:

基础形式:基址寄存器 + 变址寄存器

语法可以写成 [基址寄存器 + 变址寄存器] 或者等价的 [基址寄存器][变址寄存器],比如:

mov eax, [ebx + esi]  ; 将EBX与ESI之和指向的内存值加载到EAX
mov [ebp + edi], ecx  ; 将ECX的值存储到EBP与EDI之和指向的内存
  • 默认段前缀规则:如果基址寄存器是EBP/ESP,默认使用SS段;如果是EBX/ESI/EDI这类寄存器,默认使用DS段,你也可以手动指定段前缀,比如mov eax, fs:[ebx+esi]。

带比例因子和位移的扩展形式

你还可以给变址寄存器加上比例因子(支持1/2/4/8,对应字节/字/双字/四字),再搭配固定位移,这种模式常用于访问数组或结构体:

mov eax, [ebx + esi*4 + 0x10]  ; 计算地址 = EBX + ESI*4 + 0x10

比如用基址寄存器存数组首地址,变址寄存器存元素索引,比例因子对应元素的字节大小。


2. 你的汇编代码错误分析与修正

先把你的代码贴出来方便逐一排查:

unique proc
invoke lstrlen, esi
cmp eax, 1
jle quit
mov ebx, 0; previous iterator
mov edx, 0; next iterator
dec eax
mov ecx, eax
inc eax
next:
inc edx
cmp [esi][ebx], [esi][edx]  ; 问题1:非法指令
je skip
cmp inc ebx  ; 问题2:语法错误
cmp ebx, edx
dec ebx
je skip
inc ebx
mov [esi][ebx], [esi][edx]  ; 问题3:非法内存到内存传输
skip:
loop next
mov [esi][edx], '0'  ; 问题4:终止符逻辑错误
quit:
ret
unique endp

核心错误点逐个解析:

  1. cmp [esi][ebx], [esi][edx] 指令非法
    x86汇编中,cmp指令不支持两个内存操作数直接比较,必须至少有一个操作数是寄存器或立即数。你需要先把其中一个内存值读到寄存器里再比较,比如:

    mov al, [esi + ebx]  ; 把第一个字符读到8位寄存器AL
    cmp al, [esi + edx]  ; 再和第二个字符比较
    
  2. cmp inc ebx 语法完全错误
    这行是无效指令,你应该只是想执行inc ebx(递增EBX),直接删掉前面的cmp即可。

  3. mov [esi][ebx], [esi][edx] 指令非法
    x86的mov指令同样不支持直接从内存到内存的传输,必须通过寄存器中转,比如:

    mov al, [esi + edx]  ; 先把源内存值读到AL
    mov [esi + ebx], al  ; 再写入目标内存
    
  4. 终止符设置逻辑错误
    你最后把[esi+edx]设为字符'0',但edx在循环结束后等于原字符串长度,而且正确的字符串终止符是ASCII码0(不是字符'0')。正确的做法是把最后一个有效字符的下一个位置设为终止符,比如用ebx的最终值+1来定位:

    mov byte ptr [esi + ebx + 1], 0
    

修正后的代码示例(实现字符串去重逻辑)

unique proc
    invoke lstrlen, esi
    cmp eax, 1
    jle quit  ; 长度<=1直接返回,无需处理

    mov ebx, 0       ; 指向当前保留的最后一个唯一字符
    mov edx, 1       ; 遍历指针从第二个字符开始
    mov ecx, eax     ; 总长度存到ECX用于循环计数

next:
    mov al, [esi + ebx]
    cmp al, [esi + edx]
    je skip          ; 字符重复,跳过当前遍历字符

    inc ebx          ; 唯一字符计数+1
    mov al, [esi + edx]
    mov [esi + ebx], al  ; 保存新的唯一字符到目标位置

skip:
    inc edx
    dec ecx
    jnz next         ; 循环直到遍历完所有字符

    mov byte ptr [esi + ebx + 1], 0  ; 添加字符串终止符

quit:
    ret
unique endp

内容的提问来源于stack exchange,提问作者alexander.sivak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 17:48:10