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

NASM汇编冒泡排序程序出现段错误,求定位与修复方案

汇编冒泡排序程序段错误问题分析

问题背景

在Linux平台使用NASM编写了一个冒泡排序汇编程序,目标是生成1000个8字节随机值,从小到大排序后打印。编译运行命令如下:

nasm test.asm -f elf64
ld test.o
./a.out

运行时出现Segmentation Fault(段错误),程序代码如下:

section .text
    global _start

_start:
    mov rbp,rsp     ;save stack pointer
    sub rsp,8000        ;reserve 1000 times 64bit value


    mov rbx,rbp     ;save base pointer into rbx for Effective Address
    mov cx,1001     ;equal to for(int i=0; i<1000; ++i)
load:
    sub cx,1
    jz .exit

    rdrand eax      ;get random 64bit value in eax
    sub rbx,8
    mov [rbx],eax       ;save the random value in stack

    jmp load
.exit:
    mov rbx,rbp
    mov cx,1000     ;equal to for(int i=0; i<999; ++i)

sort:               ;Bubble Sort start here
    sub cx,1
    jz .exit

    sub rbx,8
    mov rax,[rbx]       ;last value in  rax
    mov rcx,[rbx-8]     ;last-1 value in rcx
    cmp rax,rcx
    jge .noOperation    ;if rax >= rcx continue

    mov [rbx],rcx       ;change
    mov [rbx-8],rax     ;change
.noOperation:
    jmp sort
.exit:
    mov rbx,rbp
    mov cx,1001     ;equal to for(int i=0; i<1000; ++i)


print:              ;classic decimal print
.init:
    sub cx,1
    jz .exit

    sub rbx,8
    mov rax,[rbx]
.divinit:
    mov rsi,10
    mov rdi,1
    sub rsp,1
    mov [rsp],byte 10
.div:
    mov rdx,0
    div rsi
    add dl,48
    add rdi,1
    sub rsp,1
    mov [rsp],byte dl
    cmp rax,0
    jnz .div
.syscall:
    mov rax,1
    mov rdx,rdi
    mov rdi,1
    mov rsi,rsp
    syscall

    add rsp,rdx
    jmp .init

.exit:
    add rsp,8000


programexit:

    mov rax,60
    mov rdi,0
    syscall

错误原因分析

1. 寄存器滥用直接触发段错误

排序阶段的sort循环里,你同时把rcx寄存器用作循环计数器和数据存储:

  • 先用cx(rcx的低16位)控制循环次数
  • 随后执行mov rcx,[rbx-8],把栈中值加载到完整64位rcx寄存器,直接覆盖了循环计数cx

这会导致循环终止条件jz .exit完全失效,程序会无限制执行sub rbx,8,最终访问到栈空间以外的非法内存,触发段错误。

解决方法:换用其他寄存器存储比较值,比如rdx,避免破坏循环计数器。

2. RDRAND指令使用错误(潜在问题)

你用rdrand eax获取随机值,但要存储的是8字节(64位)数据,eax仅为32位寄存器,高位4字节会是未定义的垃圾值。正确做法是用rdrand rax生成完整64位随机数。

3. 冒泡排序逻辑不完整

当前排序代码只实现了一轮相邻元素比较交换,完全缺少冒泡排序需要的外层循环控制排序轮数、内层循环遍历未排序区间的逻辑,即使修复寄存器问题,也无法完成正确排序。

4. 打印阶段栈恢复的潜在风险

打印字符时通过sub rsp,1临时存储字符,虽然每次打印后用add rsp,rdx恢复了这部分栈空间,但打印循环的.exit标签处仅恢复了存储随机数的8000字节栈空间,若打印过程异常退出,会导致栈不平衡,引发其他错误。

修复关键片段示例

以修复排序阶段寄存器问题为例:

sort:               ;Bubble Sort start here
    sub cx,1
    jz .exit

    sub rbx,8
    mov rax,[rbx]       ;last value in  rax
    mov rdx,[rbx-8]     ;用rdx代替rcx存前一个值,避免破坏循环计数器
    cmp rax,rdx
    jge .noOperation    ;if rax >= rdx continue

    mov [rbx],rdx       ;交换操作
    mov [rbx-8],rax     ;交换操作
.noOperation:
    jmp sort
.exit:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 04:45:41