Assembly与C代码中Segmentation fault (core dumped)问题求助
段错误原因分析与修复方案
你的汇编代码存在几个关键语法和逻辑错误,直接触发了段错误并导致功能异常,以下是具体问题和修复方法:
核心错误点
1. mov指令语法完全颠倒
x86-64架构中,mov指令的语法为**mov 源操作数, 目的操作数**,且立即数必须加$前缀。你写的:
mov %rax, 0 ; 错误:试图将rax的值写入内存地址0(内核空间,用户程序无权限访问,直接触发段错误) mov %rcx, 1 ; 错误:试图将rcx的值写入内存地址1,同样属于非法操作
正确写法是把立即数加载到寄存器:
mov $0, %rax ; 初始化累加和为0 mov $1, %rcx ; 初始化循环变量i为1
2. add指令方向错误
你需要把i²的结果(存在rdx)加到累加和(rax)中,但当前代码:
add %rax, %rdx ; 错误:把rax的值加到rdx,累加和根本没更新
正确写法是:
add %rdx, %rax ; 把i²的值加到累加和rax中
3. 循环条件判断逻辑错误
当前的循环判断:
cmp %rcx, %rdi ; 计算 rdi - rcx(n - i) jle loop_start ; 当n <= i时继续循环
这个逻辑完全反了——我们需要在i <= n的时候继续循环,否则退出。正确的判断应该是:
cmp %rdi, %rcx ; 计算 rcx - rdi(i - n) jle loop_start ; 当i <= n时,跳转回循环
或者等价写法:
cmp %rcx, %rdi ; 计算 rdi - rcx(n - i) jge loop_start ; 当n >= i时,跳转回循环
之前的错误逻辑会导致循环直接退出(比如n=3时,i=1,3<=1不成立),如果n<=0还会进入死循环。
修复后的完整汇编代码
.globl sumOfPowers sumOfPowers: push %rbp mov %rsp, %rbp # Input: n in %rdi # Output: Result in %rax # Initialize sum to 0 mov $0, %rax # Initialize i to 1 mov $1, %rcx loop_start: # Calculate i^2 mov %rcx, %rdx # Move i to rdx imul %rdx, %rdx # rdx = rdx * rdx (i²) # Add i^2 to sum add %rdx, %rax # Increment i inc %rcx # Check if i <= n, if yes continue loop cmp %rdi, %rcx jle loop_start pop %rbp ret
额外优化建议
在x86-64 System V调用约定中,rcx属于调用者保存寄存器,如果后续函数需要调用其他函数,会破坏rcx的值。更规范的做法是使用被调用者保存寄存器(比如rbx),使用前先push保存,结束后pop恢复:
.globl sumOfPowers sumOfPowers: push %rbp mov %rsp, %rbp push %rbx ; 保存rbx寄存器 # Input: n in %rdi # Output: Result in %rax mov $0, %rax ; sum = 0 mov $1, %rbx ; i = 1 loop_start: mov %rbx, %rdx imul %rdx, %rdx add %rdx, %rax inc %rbx cmp %rdi, %rbx jle loop_start pop %rbx ; 恢复rbx寄存器 pop %rbp ret
内容的提问来源于stack exchange,提问作者James Hou
相关产品推荐
相关产品推荐

