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

不同UEFI实现下ret指令行为差异导致字符串打印异常问题咨询

问题原因分析

该问题是你的代码没有遵守UEFI x64的调用约定导致,和UEFI实现差异没有直接关系:
UEFI x64环境严格遵循Microsoft x64调用约定,你的代码违反了两个核心规则:

  • 没有为被调用的UEFI函数预留32字节影子栈空间:按照约定,调用任意函数前,调用者需要在栈上预留32字节的空间,供被调用函数临时存储rcx、rdx、r8、r9四个参数寄存器的值。你的代码没有预留该空间,CONOUT_PRINT_STRING(即EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL的OutputString服务)运行时会直接向栈上返回地址附近的区域写入数据,覆盖原本的返回地址,导致ret指令跳转错误。
  • 栈对齐不符合要求:UEFI要求调用任意服务前栈必须16字节对齐,你的代码在调用CONOUT_PRINT_STRING时没有对齐栈,部分实机固件会因对齐异常导致函数执行异常。

QEMU使用的OVMF固件对调用约定的容错性更高,没有用到影子栈也没有做严格的对齐检查,所以代码可以正常运行;而你的华擎主板的UEFI固件严格执行了调用约定,所以出现异常。

修复方案

只需要在你的printString函数中按照调用约定调整栈即可,无需硬编码返回地址,调整后的可复用代码如下:

;prints a string
;rdx = the address of the string
printString:
    sub rsp, 0x28    ; 0x20为32字节影子栈,额外减0x8保证调用前栈16字节对齐
    mov rcx, [CONOUT]
    call [CONOUT_PRINT_STRING]
    add rsp, 0x28    ; 调用完成后恢复栈指针
    ret

同时注意你代码中所有直接调用UEFI服务的位置,都需要遵循同样的栈调整规则,比如你直接调用CONOUT_PRINT_STRING打印info和info3的位置,也需要在调用前调整栈、调用后恢复,否则仍可能出现异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:27:02