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

NASM中使用scanf读取浮点数组出现段错误,如何修复?

嘿,帮你搞定汇编代码的段错误问题!

首先看你给出的代码片段,能发现几个明显的坑,这些就是导致段错误的元凶,我一个个给你拆解,再给你修复后的完整代码:

1. 数组空间没分配对

你代码里的array res...明显没写完对吧?静态数组在.bss段得明确说要占多少空间,但你要存n个double(每个8字节),静态分配没法直接用变量n,所以最好用动态分配内存(调用malloc),这样能根据输入的n来分配刚好够的空间,不会浪费也不会不够。

2. scanf读取double的姿势错了

在x86-64的System V调用约定里,scanf的%lf要求传的是指向double的指针,而且得放在通用寄存器里,不是浮点寄存器。很多新手会直接传值,或者地址算错,这肯定会触发内存访问错误。

3. 循环里的数组索引算错了

每个double占8字节,循环访问的时候得把地址每次加8才能跳到下一个元素,如果偏移量算错,比如加了4,那就会访问到中间的字节,直接越界触发段错误。


修复后的完整代码(带注释)

%macro exit 0
 mov rax,60
 mov rdi,0
 syscall
%endmacro
extern printf
extern scanf
extern malloc   ; 引入malloc做动态内存分配
extern free     ; 用完内存记得释放,好习惯

;-------------------------------------------
section .data
nfmt db "%d",0
formatsf db "%lf",0
formatpf db "%.2lf",10,0  ; 格式化输出保留两位小数,看着更清楚
err_msg db "内存分配失败啦!",10,0
;-------------------------------------------
section .bss
n resq 1
array resq 1  ; 这里存动态分配的数组指针,不是数组本身
;-------------------------------------------
section .text
global main

main:
 ; 先读取n的值
 mov rdi, nfmt
 mov rsi, n
 mov rax, 0
 call scanf

 ; 计算需要的内存大小:n * 8字节(每个double占8字节)
 mov rdi, [n]
 imul rdi, 8
 call malloc
 cmp rax, 0
 je alloc_fail  ; 如果malloc返回0,说明分配失败,跳去处理错误
 mov [array], rax  ; 把分配到的数组指针存起来

 ; 循环读取n个double值
 mov rcx, [n]  ; 用rcx当循环计数器
 mov rbx, [array]  ; rbx存当前数组元素的地址
read_loop:
 mov rdi, formatsf
 mov rsi, rbx  ; 传当前元素的地址给scanf
 mov rax, 0
 call scanf
 add rbx, 8  ; 地址加8,跳到下一个double元素
 dec rcx
 jnz read_loop  ; 计数器没到0就继续循环

 ; 循环打印数组里的内容
 mov rcx, [n]
 mov rbx, [array]
print_loop:
 mov rdi, formatpf
 movsd xmm0, [rbx]  ; 把double值加载到XMM0寄存器(printf的浮点参数用XMM)
 mov rax, 1  ; 告诉printf:我有1个浮点参数在XMM寄存器里,这步很重要!
 call printf
 add rbx, 8
 dec rcx
 jnz print_loop

 ; 释放动态分配的内存,避免内存泄漏
 mov rdi, [array]
 call free

 exit

alloc_fail:
 ; 打印内存分配失败的提示
 mov rdi, err_msg
 mov rax, 0
 call printf
 exit

关键改动说明

  • 动态内存分配:用malloc根据输入的n来分配刚好的空间,还加了分配失败的处理,避免程序直接崩溃。
  • scanf参数修正:传的是数组元素的地址,完全符合%lf的要求,不会再乱访问内存。
  • printf的浮点参数处理:把double值加载到XMM0,还要设置rax为浮点参数的数量,这是x86-64调用约定的硬性要求,之前没做的话不仅输出错,还可能崩溃。
  • 循环地址偏移:每次加8,精准定位到下一个double元素,不会越界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:05:51