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
相关产品推荐
相关产品推荐

