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

C++内联汇编实现选择排序输出原序列,应如何修正代码?

内联汇编实现选择排序的错误修复方案

你的代码排序后完全无变化是多个错误共同导致的,核心修改点如下:

1. 输入参数传递逻辑错误

你当前使用"m"约束传入list变量,movq %0, %%rax拿到的是list指针变量自身在栈上的内存地址,而非list存储的数组首地址,导致所有数组读写操作都指向了错误的内存区域,完全没有修改原数组。
需要把输入约束改为寄存器约束,直接把参数值加载到对应寄存器:

// 原输入约束
: "m" (list), "m" (opcode), "m" (count), "m" (temp)
// 修改为
: "r"(list), "r"(opcode), "r"(count), "r"(temp)

同时寄存器赋值逻辑也要对应调整,避免重复读内存:

"movq %0, %%rax;"   // 直接拿list的值(数组首地址)给rax
"movq %1, %%rbx;"   // 拿opcode的值给rbx
"movq %2, %%rcx;"   // 拿count的值给rcx

2. 比较跳转逻辑完全反转

你要实现的升序逻辑是if(list[x] > list[y])则交换,当前代码:

"cmpq %%r8, %%rsi;" // 计算array[x] - array[y]
"jle swap;"         // 结果<=0时跳交换,和预期逻辑完全相反

需要改为:

"cmpq %%r8, %%rsi;"
"jg swap;" // 只有array[x] > array[y]时才执行交换

3. 交换操作只修改了寄存器,没有写回内存

你当前的swap逻辑只是交换了rsi、r8两个寄存器里的临时值,完全没有把修改后的值写回数组对应的内存地址,原数组自然不会有任何变化,需要修改swap逻辑:

"swap:"
// 把交换后的值写回数组内存
"movq %%r8, (%%rax, %%rdx, 8);" // array[x] = 原array[y]的值
"movq %%rsi, (%%rax, %%rdi, 8);" // array[y] = 原array[x]的值
"jmp inner_loop;"

4. 内循环边界判断逻辑错误

你当前内循环的边界判断放在了比较逻辑之后,且外层循环修改了rcx的值导致内循环遍历范围不对,需要调整执行顺序,单独用一个寄存器存储原始count值作为内循环边界:

"movq %2, %%r12;" // 提前把原始count存在r12里,避免被外层循环修改
"inner_loop:"
"cmpq %%r12, %%rdi;" // 先判断y是否>=count
"jge end_inner;" // 超出范围就结束内循环
// 再执行元素比较逻辑
"movq (%%rax, %%rdx, 8), %%rsi;"
"movq (%%rax, %%rdi, 8), %%r8;"
"cmpq %%r8, %%rsi;"
"jg swap;"
"inc %%rdi;"
"jmp inner_loop;"
"end_inner:"
"inc %%rdx;"
"jmp loop_start;"

5. 补充寄存器损毁声明

你在内联汇编中修改了多个寄存器,还修改了内存数据,必须在clobber列表中声明,避免编译器优化出错:

: 
: "r"(list), "r"(opcode), "r"(count), "r"(temp)
: "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "memory"

修复后完整代码示例

void sorter (long* list, long count, long opcode)
{
    long temp;
asm
(
    "movq %0, %%rax;"                       // 数组首地址存rax
    "movq %1, %%rbx;"                       // opcode存rbx
    "movq %2, %%rcx;"                       // count存rcx
    "movq %2, %%r12;"                       // 原始count存r12做内循环边界
    "xorq %%rdx, %%rdx;"                    // x计数器清0

"loop_start:"
    "cmpq %%rdx, %%rcx;"                    // 外层循环:x < count-1
    "jle done;"                             
    "cmpq $1,%%rbx;"                        
    "jne desc;"                             

    "mov %%rdx, %%rdi;"                     // y = x
    "inc %%rdi;"                            // y从x+1开始遍历

"inner_loop:"
    "cmpq %%r12, %%rdi;"                    // 判断y是否超出数组边界
    "jge end_inner;"
    "movq (%%rax, %%rdx, 8), %%rsi;"        // 读array[x]
    "movq (%%rax, %%rdi, 8), %%r8;"         // 读array[y]
    "cmpq %%r8, %%rsi;"
    "jg swap;"                              // 升序:array[x]>array[y]则交换
"continue_inner:"
    "inc %%rdi;"
    "jmp inner_loop;"

"swap:"
    "movq %%r8, (%%rax, %%rdx, 8);"         // 写回修改后的array[x]
    "movq %%rsi, (%%rax, %%rdi, 8);"         // 写回修改后的array[y]
    "jmp continue_inner;"

"desc:"                                     
    // 降序逻辑可参考升序逻辑修改比较条件即可,原倒序逻辑不符合选择排序要求
    "mov %%rdx, %%rdi;"                     
    "inc %%rdi;"                            
"desc_inner:"
    "cmpq %%r12, %%rdi;"                    
    "jge desc_end_inner;"
    "movq (%%rax, %%rdx, 8), %%rsi;"        
    "movq (%%rax, %%rdi, 8), %%r8;"         
    "cmpq %%r8, %%rsi;"
    "jl swap;"                              // 降序:array[x]<array[y]则交换
    "inc %%rdi;"
    "jmp desc_inner;"
"desc_end_inner:"
    "inc %%rdx;"
    "jmp loop_start;"

"done:"
     : 
     : "r" (list), "r" (opcode), "r" (count), "r" (temp)
     : "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "memory"
     ); 
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:06:02