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

如何在NASM中实现strncmp?计数跳转异常问题排查

问题分析与修复

你的my_strncmp函数中cmp rdx, rcx无法触发跳转的核心原因是rdx寄存器被后续指令意外修改,同时还有几处逻辑和拼写错误,以下是具体问题和修复方案:

核心问题点

  • rdx寄存器被覆盖:你用mov dh, byte [rdi]和mov dl, byte [rsi]存储字符,但dh/dl是rdx寄存器的高8位/低8位,这会直接改写传入的第三个参数(最大比较长度),导致cmp rdx, rcx的比较完全失效。
  • 标签拼写错误:.retrun_2少写了一个t,应该是.return_2,错误的标签会导致跳转异常。
  • 循环逻辑顺序不合理:当前逻辑在递增计数后才比较字符,且字符结束判断的时机不对,同时不符合strncmp的标准行为。
  • 返回值不符合规范:标准strncmp返回的是第一个不同字符的差值(str1[i] - str2[i]),而非固定的1/-1。

修复后的汇编代码

section .text

global my_strncmp

my_strncmp:
    mov rcx, 0          ; 初始化计数器
.next:
    cmp rcx, rdx        ; 先判断是否已经比较了rdx个字符
    je .return_equal    ; 达到最大长度,返回0

    mov al, byte [rdi]  ; 用al存储第一个字符串的当前字符(不破坏rdx)
    mov bl, byte [rsi]  ; 用bl存储第二个字符串的当前字符

    cmp al, 0           ; 检查第一个字符串是否结束
    je .return_diff
    cmp bl, 0           ; 检查第二个字符串是否结束
    je .return_diff

    cmp al, bl          ; 比较当前字符
    jne .return_diff    ; 字符不同,返回差值

    ; 字符相同,继续下一个
    inc rcx
    inc rdi
    inc rsi
    jmp .next

.return_equal:
    mov rax, 0
    ret

.return_diff:
    sub rax, rax        ; 清空rax
    mov al, byte [rdi]
    sub al, byte [rsi]  ; 计算差值:str1[i] - str2[i]
    ; 符号位会自动扩展到rax的高位,符合int返回值要求
    ret

修复说明

  1. 保护rdx寄存器:改用al和bl存储字符,避免修改作为参数传入的rdx,确保cmp rcx, rdx的比较始终基于原始的最大长度参数。
  2. 修正标签拼写:移除错误的标签定义,同时简化返回逻辑,用统一的差值计算代替固定返回值。
  3. 调整循环顺序:先判断是否达到最大比较长度,再处理字符比较,符合strncmp的逻辑——最多比较n个字符,不管字符串是否结束。
  4. 遵循标准返回值:通过sub al, byte [rsi]计算字符差值,利用x86的符号扩展特性,让rax自动成为正确的int返回值。

测试验证

用你的C测试代码调用修复后的函数:

#include <stdio.h>

extern int my_strncmp(const char *str1, const char *str2, size_t n);

int main(){
    printf("%d\n", my_strncmp("string2", "string1", 3));  // 前3个字符相同,返回0
    printf("%d\n", my_strncmp("string2", "string1", 7));  // 第7个字符'2'-'1'=1,返回1
    return 0;
}

编译运行后会得到符合预期的结果,且最大长度的判断逻辑正常生效。

内容的提问来源于stack exchange,提问作者Kings man

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:00:19