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

合并有序数组问题:无法正确处理重复值与比较逻辑

合并降序去重数组的汇编问题修复

需求说明

需要合并两个元素为4字节int、降序排列且以0结尾的数组,结果存入mergedArray地址,要求新数组满足:

  • 保持降序排列
  • 以0结尾
  • 每个值最多出现一次

现有代码在数组存在重复值时失效,尝试通过比较原数组与新数组的值跳过重复项,但该逻辑未起作用。

原代码

.global _start

.section .text
_start:
    mov $array1, %rax
    mov $array2, %rcx
    mov $mergedArray, %r8

    xor %r14,%r14
    
loopcheck: #checks if arrays are finished

    movl (%rax), %r9d 
    movl (%rcx), %r10d 
    movl (%r8), %r11d

    testl %r9d, %r9d
    jz rest_of_array2

    
    testl %r10d, %r10d
    jz rest_of_array1
    
loop: #the main loop
    cmp %r10d, %r9d 
    jg add_r9d
    jmp add_r10d
    

add_r9d: #add rax value
    cmp %r11d,%r9d
    jz remove_current_r9d
    
    mov %r9d, (%r8)

    lea 4(%r8), %r14
    mov %r14 , %r8
    

remove_current_r9d: #adv rax

    lea 4(%rax), %r14
    mov %r14, %rax
    jmp loopcheck

add_r10d: #add rcx value
    cmp %r11d, %r10d
    jz remove_current_r10d
    mov %r10d, (%r8)

    lea 4(%r8),%r14
    mov %r14, %r8

remove_current_r10d: #adv rcx
    lea 4(%rcx), %r14
    mov %r14, %rcx
    jmp loopcheck


rest_of_array2: #adding the rest of array 2 once array 1 is finished
    testl %r10d, %r10d
    jz end
    cmp %r10d,%r11d
    jz finish_loop2
    movl %r10d, (%r8)

    lea 4(%r8),%r14
    mov %r14, %r8

finish_loop2:
    lea 4(%rcx), %r14
    mov %r14 ,%rcx

    movl (%rcx), %r10d 
    movl (%r8), %r11d

    jmp rest_of_array2



rest_of_array1: #adding the rest of array 1 once array 2 is finished
    testl %r9d,%r9d
    jz end
    cmp %r9d,%r11d
    jz finish_loop1
    movl %r9d, (%r8)

    lea 4(%r8),%r14
    mov %r14, %r8

finish_loop1:
    lea 4(%rax),%r14
    mov %r14 ,%rax

    movl (%rax), %r9d 
    movl (%r8), %r11d

    jmp rest_of_array1


end: #ennd
    xor %r14,%r14
    mov %r14, (%r8)

问题根源

  1. 去重逻辑的比较对象错误:代码中用movl (%r8), %r11d获取比较值,但%r8始终指向下一个要写入的位置,而非最后一个已写入的元素。初始时mergedArray未初始化,%r11d是随机垃圾值;写入后,%r8已移动到下一个位置,该位置的值仍是未知的,导致比较完全失效。
  2. 未维护最后写入的元素状态:没有变量记录已写入数组的最后一个值,无法准确判断当前元素是否重复。

修复后的代码

.global _start

.section .text
_start:
    mov $array1, %rax       # 指向array1当前元素
    mov $array2, %rcx       # 指向array2当前元素
    mov $mergedArray, %r8   # 指向mergedArray的写入位置
    movl $-1, %r11d         # 初始化最后写入的值为-1(适配原数组非负特性,若含负数可改为0x80000000)

loopcheck:
    movl (%rax), %r9d       # 取array1当前元素
    movl (%rcx), %r10d      # 取array2当前元素

    # 检查array1是否已遍历完(遇到0)
    testl %r9d, %r9d
    jz rest_of_array2

    # 检查array2是否已遍历完(遇到0)
    testl %r10d, %r10d
    jz rest_of_array1

loop:
    # 比较两个数组当前元素,选择较大的优先处理
    cmp %r10d, %r9d
    jg add_r9d
    jmp add_r10d

add_r9d:
    # 检查当前元素是否与最后写入的元素重复
    cmp %r11d, %r9d
    jz skip_r9d             # 重复则跳过,直接移动array1指针

    # 不重复则写入mergedArray
    mov %r9d, (%r8)
    mov %r9d, %r11d         # 更新最后写入的值
    lea 4(%r8), %r8         # 移动写入指针到下一个位置

skip_r9d:
    lea 4(%rax), %rax       # 移动array1指针
    jmp loopcheck

add_r10d:
    # 检查当前元素是否与最后写入的元素重复
    cmp %r11d, %r10d
    jz skip_r10d            # 重复则跳过,直接移动array2指针

    # 不重复则写入mergedArray
    mov %r10d, (%r8)
    mov %r10d, %r11d        # 更新最后写入的值
    lea 4(%r8), %r8         # 移动写入指针到下一个位置

skip_r10d:
    lea 4(%rcx), %rcx       # 移动array2指针
    jmp loopcheck

rest_of_array2:
    # 处理array2剩余元素
    testl %r10d, %r10d
    jz end

    cmp %r11d, %r10d
    jz skip_rest2

    mov %r10d, (%r8)
    mov %r10d, %r11d
    lea 4(%r8), %r8

skip_rest2:
    lea 4(%rcx), %rcx
    movl (%rcx), %r10d
    jmp rest_of_array2

rest_of_array1:
    # 处理array1剩余元素
    testl %r9d, %r9d
    jz end

    cmp %r11d, %r9d
    jz skip_rest1

    mov %r9d, (%r8)
    mov %r9d, %r11d
    lea 4(%r8), %r8

skip_rest1:
    lea 4(%rax), %rax
    movl (%rax), %r9d
    jmp rest_of_array1

end:
    # 写入结束标记0
    movl $0, (%r8)

关键修改点

  • 新增%r11d变量维护最后写入mergedArray的元素值,初始值根据数组元素范围调整,确保不会与有效元素重复。
  • 所有去重比较逻辑改为和%r11d(最后写入值)对比,而非%r8指向的未写入位置。
  • 每次写入元素后,立即更新%r11d为当前写入的值,保证后续比较准确。
  • 简化指针移动逻辑,去掉冗余的%r14中转,直接用lea更新寄存器。

内容的提问来源于stack exchange,提问作者a boi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:05:12