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

x86-64 AT&T汇编使用printf打印float出现段错误求助

问题分析与修复

你的代码里有两个关键错误导致段错误,数组访问的写法是没问题的,下面拆解问题并给出修复方案:

1. printf参数类型不匹配

%f格式符要求传入double类型数据,但你当前xmm0里存的是float类型的求和结果。x86-64下float和double的存储格式不同,直接传递float会让printf解析出错,触发未定义行为(比如段错误)。需要用cvtss2sd指令把float转换成double:

cvtss2sd %xmm0, %xmm0  # 将XMM0中的float转成double

2. 未正确设置%eax的值

根据x86-64 System V调用约定,调用带有浮点参数(通过XMM寄存器传递)的函数时,%eax必须设置为实际使用的XMM寄存器数量。这里你用了1个XMM寄存器(xmm0)传递浮点参数,所以要把%eax设为1,而非0。

3. 额外优化:main函数的返回规范

虽然不是段错误的直接原因,但在main函数里直接调用exit不够规范,建议用ret返回,更符合C标准中main函数的行为逻辑。

修正后的完整代码

.section .data
msg: .asciz "Result is: %f\n"
n: .int 5
a: .float 1.1, 2.2, 3.3, 4.4, 5.5
res: .float 0

.section .text
.globl main
main:
    xor %ecx, %ecx
    movss res, %xmm0
    mov n, %ebx
    
while:
    cmp %ebx, %ecx
    je end_while
    
    addss a(,%ecx, 4) , %xmm0
    inc %ecx
    jmp while
    
end_while:
    ; 把float转成double,适配printf的%f
    cvtss2sd %xmm0, %xmm0
    mov $msg, %rdi
    mov $1, %eax  ; 告诉printf用了1个XMM寄存器
    call printf
    
    ret  ; 用ret替代exit,符合main函数的返回规范

关于数组访问的确认

你写的a(,%ecx,4)是完全正确的:AT&T语法中base(index,scale)的格式,这里base是数组起始地址a,index是循环计数器%ecx,scale是4(float每个元素占4字节),计算出的地址就是a + ecx*4,正好对应数组的第ecx个元素,没有问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:36:04