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

x86_64架构下用scanf读取float值时寄存器未正确接收数据

x86_64汇编中scanf读取浮点数失败的问题解决

在x86_64架构下编写汇编代码时,尝试用scanf读取float类型数值,使用了格式说明符%f但输入无法正确传入寄存器处理,相关代码如下:

section .data
    formato_entrada: dq "%f %f", 0
    formato_saida2: dq "%f", 10, 0
    formato_saida: db "%s", 0    
    msg_coordenadas_ponto_1: db "Digite as coordenadas do primeiro ponto (x,y): ", 0
    msg_coordenadas_ponto_2: db "Digite as coordenadas do segundo ponto (x,y): ", 0
    msg_coordenadas_ponto_3: db "Digite as coordenadas do terceiro ponto (x,y): ", 0
    msg_distancia_1: db "Primeira distância: %.2f", 10, 0
    msg_distancia_2: db "Segunda distância: %.2f", 10, 0
    msg_distancia_3: db "Terceira distância: %.2f", 10, 0
    msg_equilatero: db "O triângulo é equilátero.", 10, 0
    msg_isosceles: db "O triângulo é isósceles.", 10, 0
    msg_escaleno: db "O triângulo é escaleno.", 10, 0

section .bss
    x1: resq 1
    y1: resq 1
    x2: resq 1
    y2: resq 1
    x3: resq 1
    y3: resq 1
    distancia1: resq 1
    distancia2: resq 1
    distancia3: resq 1

section .text
    extern printf
    extern scanf
    extern sqrt
    extern round

global main
main:       
    push rbp
    mov rbp, rsp

    ; 读取第一个点的坐标
    xor eax, eax
    lea rdi, [msg_coordenadas_ponto_1]
    call printf

    xor eax, eax
    lea rdi, [formato_entrada]
    lea rsi, [x1]
    lea rdx, [y1]
    call scanf

    ; 读取第二个点的坐标
    xor eax, eax
    lea rdi, [msg_coordenadas_ponto_2]
    call printf

    xor eax, eax
    lea rdi, [formato_entrada]
    lea rsi, [x2]
    lea rdx, [y2]
    call scanf

    ; 读取第三个点的坐标
    xor eax, eax
    lea rdi, [msg_coordenadas_ponto_3]
    call printf

    xor eax, eax
    lea rdi, [formato_entrada]
    lea rsi, [x3]
    lea rdx, [y3]
    call scanf

错误原因分析

  1. 格式说明符与内存分配不匹配:C标准中,scanf的%f格式说明符要求对应float类型的指针(指向4字节内存),但代码中x1、y1等变量用resq 1分配了8字节内存(对应double类型),类型不匹配导致数据写入错误。
  2. 字符串定义不规范:formato_entrada用dq定义字符串,dq是8字节双字定义,适合存储64位数值,而字符串是字节序列,应该用db定义,否则可能因对齐或长度问题引发异常。

解决方法

方案一:使用float类型(4字节)

  1. 修改.bss段的内存分配,将resq 1改为resd 1(分配4字节,对应float):
section .bss
    x1: resd 1
    y1: resd 1
    x2: resd 1
    y2: resd 1
    x3: resd 1
    y3: resd 1
    distancia1: resd 1
    distancia2: resd 1
    distancia3: resd 1
  1. 保持格式说明符%f不变,同时修正字符串定义为db:
formato_entrada: db "%f %f", 0
  1. 后续处理浮点数时,使用movss指令将内存中的float值加载到XMM寄存器(如movss xmm0, [x1])。

方案二:改用double类型(推荐,更适配x86_64浮点数处理)

  1. 保持.bss段的resq 1(8字节,对应double)不变;
  2. 修改格式说明符为%lf(scanf中%lf对应double类型指针),同时修正字符串定义:
formato_entrada: db "%lf %lf", 0
  1. 后续处理时,使用movsd指令加载double值到XMM寄存器(如movsd xmm0, [x1])。

额外注意:调用scanf时,xor eax, eax的设置是正确的——在x86_64 System V调用约定中,eax用于指定通过SSE寄存器传递的浮点数参数数量,这里传递的是指针(通用寄存器传递),因此eax设为0是合规的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:03:09