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

MASM x64编写BMI计算器时printf_s与pow调用触发访问违规

问题分析与修复方案

你的MASM x64代码出现访问违规的核心原因是未遵守x64调用约定,包括栈对齐、参数传递规则,同时存在计算逻辑错误,以下是具体修复:

核心错误点

  1. 栈对齐与Shadow Space未正确分配
    x64 Microsoft调用约定要求:

    • 调用任何C函数前,RSP必须是16字节对齐
    • 必须为被调用函数分配32字节的shadow space(用于保存前4个寄存器参数)
      进入main时,RSP因返回地址压栈处于RSP%16=8的状态,你之前用sub rsp,100h未补充8字节对齐空间,导致RSP未对齐,触发访问违规。
  2. printf_s参数传递错误

    • 对于%lf格式的double参数,必须放入XMM寄存器(第一个浮点参数放XMM0),而非通用寄存器(RDX),你之前的movq rdx, xmm1完全不符合可变参数函数的浮点参数传递规则。
    • 调用printf_s这类可变参数函数时,必须在RAX中声明通过XMM寄存器传递的浮点参数数量,否则函数无法正确解析参数,引发内存错误。
  3. BMI计算逻辑倒置
    原代码中divsd xmm0, xmm1执行的是height² / mass,而正确的BMI公式是mass / height²,操作数顺序完全颠倒。

修复后的完整代码

includelib legacy_stdio_definitions.lib

extern printf_s:proc
extern scanf_s:proc
extern pow:proc

.data
    height real8 1.73
    mass real8 70.0
    square real8 2.0
    scanfGetDouble db "%lf", 0
    printfPrintDouble db "%lf", 0
    promptHeight db "Enter height (m): ", 0
    promptMass db "Enter mass (kg): ", 0
    resultBMI db "BMI: %lf", 0ah, 0dh, 0 ; 添加换行提升可读性

.code
main proc
    ; 分配32字节shadow space + 8字节对齐,总计40字节(28h),保证RSP16字节对齐
    sub rsp, 28h
    
    ; 提示输入身高
    lea rcx, promptHeight
    xor rax, rax ; 无浮点参数,RAX设为0
    call printf_s
    
    ; 读取身高
    lea rcx, scanfGetDouble
    lea rdx, height
    xor rax, rax
    call scanf_s
    
    ; 提示输入体重
    lea rcx, promptMass
    xor rax, rax
    call printf_s
    
    ; 读取体重
    lea rcx, scanfGetDouble
    lea rdx, mass
    xor rax, rax
    call scanf_s
    
    ; 打印身高
    lea rcx, printfPrintDouble
    movsd xmm0, height ; 将double值放入XMM0
    mov rax, 1 ; 声明1个浮点参数在XMM寄存器
    call printf_s
    
    ; 打印体重
    lea rcx, printfPrintDouble
    movsd xmm0, mass
    mov rax, 1
    call printf_s
    
    ; 计算height²:pow(height, 2.0)
    movsd xmm0, height ; pow的第一个参数(base)放入XMM0
    movsd xmm1, square ; pow的第二个参数(exp)放入XMM1
    call pow ; 返回值(height²)存于XMM0
    
    ; 计算BMI = mass / height²
    movsd xmm1, xmm0 ; 暂存height²到XMM1
    movsd xmm0, mass ; 将mass放入XMM0
    divsd xmm0, xmm1 ; XMM0 = mass / height²
    
    ; 打印BMI结果
    lea rcx, resultBMI
    mov rax, 1
    call printf_s
    
    xor rax, rax ; 返回0表示程序正常结束
    add rsp, 28h
    ret
main endp
end

测试说明

使用初始值height=1.73、mass=70.0时,计算结果为70/(1.73²)≈23.4,与预期一致。测试pow函数时,需保证sub rsp的取值为8 + 16*N(如28h),确保栈对齐,避免访问违规。

内容的提问来源于stack exchange,提问作者Forward-Fax3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:25:55