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
相关产品推荐
相关产品推荐

