NASM x86_64中Vec2.imul函数实现触发段错误(核心已转储)
NASM x86_64 Vec2结构体乘法函数段错误排查与修复
常见问题分析与排查步骤
结构体成员偏移错误
确认Vec2结构体定义的成员大小和偏移是否正确。比如:struc Vec2 .x resd 1 ; 32位整数,偏移0 .y resd 1 ; 32位整数,偏移4 endstruc访问成员时必须使用正确的偏移(如
[rdi + Vec2.x]),若偏移计算错误(比如误将resd当成resw),会直接访问非法内存触发段错误。调用约定违规
x86_64 Linux下的调用规则:- 前6个整数参数用
rdi、rsi、rdx、rcx、r8、r9传递 - 返回值存在
rax中 - 函数需保留
rbx、rbp、r12-r15寄存器
若参数传错寄存器,或函数内修改了需保留的寄存器未恢复,会导致后续代码执行异常。
- 前6个整数参数用
imul指令操作数不匹配
若Vec2的x/y是32位整数,需用32位寄存器(eax、ebx等)配合imul操作,避免用64位寄存器操作32位成员导致内存越界。未初始化的结构体指针
确保Vec2实例的内存已正确分配:要么在栈上静态定义,要么用malloc动态分配后再使用,禁止直接使用未初始化的指针访问成员。
修复示例代码
以下是实现向量与标量相乘的正确代码,预期输出Vec2 [1190, 156]:
extern printf extern malloc struc Vec2 .x resd 1 .y resd 1 endstruc section .data fmt db "Vec2 [%d, %d]", 10, 0 section .text global _start _start: ; 动态分配Vec2内存并初始化(x=238, y=32) mov rdi, Vec2_size call malloc mov dword [rax + Vec2.x], 238 mov dword [rax + Vec2.y], 32 ; 调用乘法函数:rdi=Vec2指针,rsi=标量5 mov rsi, 5 mov rdi, rax call vec2_mul_scalar ; 打印结果 mov rdi, fmt mov esi, dword [rax + Vec2.x] mov edx, dword [rax + Vec2.y] call printf ; 退出程序 mov rax, 60 xor rdi, rdi syscall ; 函数:vec2_mul_scalar ; 输入:rdi=Vec2指针,rsi=32位标量 ; 返回:rax=新的Vec2指针(存储相乘结果) vec2_mul_scalar: push rbx ; 保存调用者寄存器 mov rbx, rdi ; 暂存原Vec2指针 ; 分配新内存存储结果 mov rdi, Vec2_size call malloc test rax, rax jz .malloc_fail ; 检查内存分配是否成功 ; 计算x = 原x * 标量 mov eax, dword [rbx + Vec2.x] imul eax, esi mov dword [rax + Vec2.x], eax ; 计算y = 原y * 标量 mov eax, dword [rbx + Vec2.y] imul eax, esi mov dword [rax + Vec2.y], eax pop rbx ret .malloc_fail: pop rbx xor rax, rax ; 返回空指针表示失败 ret
关键修复点
- 严格遵守x86_64调用约定,保留了
rbx寄存器 - 正确使用结构体成员偏移访问内存
- 检查
malloc返回值,避免空指针访问 - imul操作数大小匹配(32位寄存器操作32位成员)
内容的提问来源于stack exchange,提问作者Oh My Code
相关产品推荐
相关产品推荐

