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

NASM汇编实现5个不同长度字符串字符交错拼接求助

适配不同长度字符串的NASM交错提取实现与优化方案

核心问题分析

现有代码仅计算第一个字符串的长度并以此作为循环次数,未考虑其他字符串长度可能更短或更长的情况,导致短字符串会被读取到换行符或垃圾数据,长字符串的后续字符无法被提取。要实现不同长度字符串的交错提取,核心是为每个字符串单独记录长度,并在提取字符时判断当前索引是否在字符串的有效范围内。

优化实现思路

  • 为每个字符串单独计算并存储长度,避免依赖单一字符串的长度
  • 使用数组存储所有字符串的地址和对应长度,通过循环统一处理,消除冗余代码
  • 先确定所有字符串中的最大长度,以此作为外层循环的次数,确保所有字符串的有效字符都被提取
  • 每次提取字符前检查当前索引是否小于对应字符串的长度,仅提取有效范围内的字符

优化后的NASM代码

segment .data
    instruccion db 'Ingrese 5 cadenas (cada una no mayor a 20 caracteres):',0x0A
    lonI EQU ($-instruccion)

segment .bss
    ; 输入字符串缓冲区(多留1字节存换行符)
    cad1 resb 21
    cad2 resb 21
    cad3 resb 21
    cad4 resb 21
    cad5 resb 21
    ; 存储字符串地址与长度的数组
    str_ptrs resd 5   ; 每个元素存字符串起始地址(双字)
    str_lens resd 5   ; 每个元素存字符串有效长度(不含换行符,双字)
    output resb 101   ; 输出缓冲区,最多容纳5*20+1=101字节

segment .text
    global _start

_start:
    ; 打印提示信息
    mov edx, lonI
    mov ecx, instruccion
    call imprimir

    ; 读取5个字符串,记录地址与有效长度
    mov dword [str_ptrs], cad1
    mov ecx, cad1
    call leer
    call calc_len
    mov dword [str_lens], eax

    mov dword [str_ptrs+4], cad2
    mov ecx, cad2
    call leer
    call calc_len
    mov dword [str_lens+4], eax

    mov dword [str_ptrs+8], cad3
    mov ecx, cad3
    call leer
    call calc_len
    mov dword [str_lens+8], eax

    mov dword [str_ptrs+12], cad4
    mov ecx, cad4
    call leer
    call calc_len
    mov dword [str_lens+12], eax

    mov dword [str_ptrs+16], cad5
    mov ecx, cad5
    call leer
    call calc_len
    mov dword [str_lens+16], eax

    ; 找出最长字符串的长度,作为外层循环次数
    mov esi, str_lens
    mov ecx, 5
    mov eax, 0
find_max_len:
    cmp eax, [esi]
    jge skip_update
    mov eax, [esi]
skip_update:
    add esi, 4
    loop find_max_len
    mov ebx, eax  ; ebx存储最大长度

    ; 交错提取字符到输出缓冲区
    mov edi, output
    mov ecx, 0    ; ecx为当前字符索引i
outer_loop:
    cmp ecx, ebx
    jge end_outer_loop

    ; 遍历5个字符串,尝试提取第i个字符
    mov esi, str_ptrs
    mov edx, 5
inner_loop:
    mov eax, [esi + 4*(edx-1)]  ; 获取当前字符串地址
    mov ebp, [str_lens + 4*(edx-1)]  ; 获取当前字符串长度
    cmp ecx, ebp
    jge skip_char  ; 索引超出长度,跳过提取

    ; 复制字符到输出缓冲区
    mov al, [eax + ecx]
    stosb

skip_char:
    dec edx
    jnz inner_loop

    inc ecx
    jmp outer_loop

end_outer_loop:
    ; 添加换行符
    mov al, 0x0A
    stosb

    ; 打印结果
    mov edx, edi - output  ; 计算输出字符串实际长度
    mov ecx, output
    call imprimir

    ; 退出程序
    mov eax, 1
    int 0x80

; 子函数:读取字符串,ecx=缓冲区地址,edx=最大读取字节数
leer:
    mov edx, 21
    mov ebx, 0
    mov eax, 3
    int 0x80
    ret

; 子函数:计算字符串有效长度,ecx=缓冲区地址,返回eax=有效长度(不含换行符)
calc_len:
    mov edi, ecx
    mov eax, 0x0A
    mov ecx, 21
    repne scasb
    dec edi  ; 回到换行符位置
    mov eax, edi - ecx  ; 有效长度=换行符位置 - 起始地址
    ret

; 子函数:打印字符串,ecx=字符串地址,edx=长度
imprimir:
    mov ebx, 1
    mov eax, 4
    int 0x80
    ret

关键细节说明

  1. 字符串长度计算:calc_len子函数通过repne scasb定位换行符,用换行符地址减去字符串起始地址,得到不含换行符的有效长度,确保每个字符串的实际长度被准确记录。
  2. 最大长度获取:遍历长度数组找到最长字符串的长度,以此作为外层循环次数,保证所有字符串的有效字符都能被处理。
  3. 边界检查:内层循环处理每个字符串时,先判断当前索引是否小于该字符串的长度,仅在有效范围内才提取字符,避免读取无效内存。
  4. 代码复用:通过字符串地址数组和长度数组,用循环统一处理5个字符串,消除了原代码中重复的处理逻辑,提升了代码可维护性。

内容的提问来源于stack exchange,提问作者Emilio Díaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:44:53