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

Linux x86_64汇编实现冒泡/快速排序遇阻:swapij子程序失效

x86_64 Linux汇编中swap子程序的常见问题与修复方案

在x86_64 Linux环境下实现排序算法时,swap子程序出错大概率和调用约定不匹配、内存地址处理错误或非易失性寄存器未保存有关,以下是具体问题分析和可行的实现方案:

核心问题排查点

  • System V AMD64调用约定未遵守:Linux x86_64的函数调用默认遵循System V ABI,前两个参数通过rdi、rsi传递,而非易失性寄存器(如rbx、rbp、r12-r15)在函数调用后必须保持原值,若你的swap子程序修改了这些寄存器却未保存/恢复,会破坏调用者的上下文。
  • 内存访问逻辑错误:如果swap目标是数组元素,必须传递元素的内存地址而非值,若直接用寄存器中的数值交换,不会修改原数组的内容。
  • 数据类型不匹配:如果数组是int(4字节)和long long(8字节),内存偏移计算和寄存器使用要对应,比如int用32位寄存器,long long用64位寄存器。

正确的swap子程序示例(针对int数组)

; 函数功能:交换两个int类型变量的值
; 参数:rdi = 第一个int的地址,rsi = 第二个int的地址
swap:
    push rbx                    ; rbx是非易失性寄存器,调用前需入栈保存
    mov eax, [rdi]              ; 读取第一个int的值到eax
    mov ebx, [rsi]              ; 读取第二个int的值到ebx
    mov [rdi], ebx              ; 将第二个值写入第一个地址
    mov [rsi], eax              ; 将第一个值写入第二个地址
    pop rbx                     ; 恢复rbx寄存器的值
    ret

冒泡排序中调用swap的示例片段

; 函数参数:rdi = int数组首地址,rsi = 数组元素个数
bubblesort:
    mov rcx, rsi
    dec rcx                     ; 外层循环次数为n-1
outer_loop:
    mov rdx, 0                  ; 内层循环计数器初始化
inner_loop:
    ; 比较当前元素和下一个元素
    mov eax, [rdi + rdx*4]
    cmp eax, [rdi + rdx*4 + 4]
    jle skip_swap               ; 当前元素更小,无需交换

    ; 准备调用swap,先保存rdi和rsi(因为swap会修改这两个寄存器)
    push rdi
    push rsi
    ; 计算两个元素的地址
    lea rdi, [rdi + rdx*4]
    lea rsi, [rdi + 4]          ; 这里注意:rdi已经被修改,所以+4是下一个元素地址
    call swap
    ; 恢复原寄存器
    pop rsi
    pop rdi

skip_swap:
    inc rdx
    cmp rdx, rcx
    jl inner_loop
    dec rcx
    jnz outer_loop
    ret

调试建议

  1. 使用gdb testStr启动调试,在swap函数入口设置断点:b swap,运行后查看rdi和rsi是否为有效的内存地址,用x/d $rdi和x/d $rsi查看地址中的数值是否符合预期。
  2. 检查数组初始化是否正确,确保传入排序函数的数组地址和长度无误。
  3. 若使用long long类型数组,需将寄存器改为64位(如rax、rbx),内存偏移改为rdx*8。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:03:10