x86-64汇编实现func函数运行触发Segmentation fault问题求助
问题排查
以下是导致段错误和逻辑错误的所有问题点:
- 栈操作错误:64位模式下栈指针寄存器是
rsp,你代码末尾栈恢复用了add sp,16,会直接破坏栈结构导致段错误。同时x86-64 System V调用约定要求调用C库函数前栈必须16字节对齐,你开头sub rsp,16后,call指令会压入8字节返回地址,此时栈偏移为8字节,不满足对齐要求。 - 输入变量定义错误:你需要存储32位有符号int,但是用
.word 0定义的var1只有16位长度,scanf输入时会越界覆盖后续内存数据。 - 外部变量声明错误:
A是外部导入的指针,你用.global A是导出符号,应该改为.extern A,同时需要显式声明用到的C库函数scanf、printf。 - 数组访问逻辑错误:你每次直接读取
A指针本身的值参与计算,没有根据循环下标读取数组A的对应元素,完全不符合需求。 - 乘法逻辑完全错误:
- 有符号数相乘需要用
imul指令,你用的mul是无符号乘法,结果会出错 mul/imul使用寄存器操作数时,默认源操作数之一是rax,你没有把输入的整数存入rax就直接调用乘法指令- 你代码里乘法后直接加
rcx的值,加的是A的指针值,根本不是乘法结果
- 有符号数相乘需要用
- 可变参数函数调用规则错误:调用
scanf、printf这类可变参数C函数前,需要将rax清零,标记没有使用向量寄存器传参。
修正后的完整代码
.intel_syntax noprefix .text .global func .extern A .extern scanf .extern printf func: # 栈对齐:预留24字节,保证call之前栈16字节对齐 sub rsp, 24 xor r8, r8 # r8 存储累加和,初始为0 mov r9, rdi # r9 存储剩余循环次数,初始为N loop: test r9, r9 je end_loop dec r9 # 调用scanf读取输入 xor eax, eax mov rdi, offset scan_format mov rsi, offset var1 call scanf # 读取输入的32位整数,符号扩展到64位 movsxd rsi, dword ptr [var1] # 读取数组A的当前元素(r9为当前索引,int占4字节) mov rcx, qword ptr [A] movsxd rdx, dword ptr [rcx + r9*4] # 有符号数相乘 imul rsi, rdx # 累加结果 add r8, rsi jmp loop end_loop: # 调用printf输出结果 xor eax, eax mov rdi, offset print_format mov rsi, r8 call printf add rsp, 24 ret .data # 定义32位存储空间存输入 var1: .long 0 scan_format: .string "%d" # 适配64位累加和输出,避免截断 print_format: .string "%lld\n"
补充说明:如果业务要求累加和只能是32位int,可以将累加寄存器换为32位寄存器,输出格式改回
%d即可。
内容的提问来源于stack exchange,提问作者AshGi
相关产品推荐
相关产品推荐

