首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >存储x87 FPU控制字

存储x87 FPU控制字
EN

Stack Overflow用户
提问于 2018-05-12 16:23:31
回答 1查看 1.5K关注 0票数 1

我正在做一个函数,返回FPU控制字寄存器(16位)。

根据文档,我必须使用fstcw和内存位置。

我在记忆中的位置是:

代码语言:javascript
复制
fpuctl: .word 0

我的职责是:

代码语言:javascript
复制
.global getFPUControlState
    .type getFPUControlState, function
    getFPUControlState:
    pushl %ebp
    movl %esp, %ebp 
    xorl %eax, %eax #clear eax (ax too)

    fnstcw fpuctl #store in fpuCTL
    mov fpuctl, %ax #put it in 8bit %ax

    leave
    ret

控制台上写着:

内存保护违规。

如何正确使用fnstcw

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-13 23:33:52

TL:您可能会将fpuctl: .word 0与代码一起放在只读.text部分。存储到堆栈上的一些划痕空间,或者如果您真的想使用静态存储,则存储到BSS。

你说得对,fnstcw是记忆的目的地.更常用的fnstsw %ax ( x87状态词)有一个AX目的地形式,但fnstcw没有。

(当然,x87是过时的,除非您实际上需要80位精度;现代x86至少有SSE2,所以您可以并且应该在XMM寄存器中进行标量FP计算。。SSE的控件和状态位都在MXCSR中,与x87控件和状态不同。)

还请注意,如果您从C调用这个命令,然后转到修改 x87控件字,则需要告诉编译器,这样它就不会假设舍入模式仍然是四舍五入,或者精度仍然是80位(64位尾数)。这对于编译时常量传播和其他优化都很重要。例如,gcc拥有-frounding-math-fsignaling-nans。它也可能支持C99 #pragma STDC FENV ACCESS ON,但我不确定gcc或clang是否完全符合标准。另见https://gcc.gnu.org/wiki/FloatingPointMath。(您应该使用来自fenv.h的标准C函数来修改FP环境,比如fegetenv /fesetenv。)

如果您要从手写的asm中使用这个,请将它变成一个宏,将第二个arg作为一个划痕内存位置,而不是一个函数。作为一个非内联函数,这太小了;它是两个有用的指令(fnstcw和重新加载);其余的都是开销。

顺便说一句,AX是一个16位寄存器。AL是EAX的低8位。

此外,movzwl fpuctl, %eax将执行零扩展字加载,这样您就不需要先xor-零eax。

您还没有提供MCVE,但是fpuctl: .word 0 可能会将与代码一起放在“只读”一节中,这样就可以得到与使用mov %eax, getFPUControlState相同的错误。

相反,将其放入BSS (零init静态存储,其中零没有存储在您的可执行文件中,只是总大小)。

代码语言:javascript
复制
.bss
fpuctl: .zero 2         # 2 bytes of zeros in the BSS

.text                   # switch back to the .text section
.globl getFPUControlState         # GAS does accept .global as a synonym for .globl
.type getFPUControlState, function
getFPUControlState:
       # leave out the EBP stack-frame stuff, you're not using it for anything
    fnstcw   fpuctl
    movzwl   fpuctl, %eax       # zero-extending word load into EAX

    ret
.size getFPUControlState, . - getFPUControlState

作为另一种选择,将在BSS中保留2个字节和fpuctl标记为非导出的标签:

代码语言:javascript
复制
.lcomm  fpuctl, 2     # puts stuff in the BSS regardless of current section

但实际上,你根本不需要静态存储

因此,只需使用堆栈就可以为自己节省一个潜在的页面错误。

代码语言:javascript
复制
.globl getFPUControlState
.type getFPUControlState, function
getFPUControlState:

    sub      $4, %esp          # reserve space on the stack
    fnstcw   (%esp)
    movzwl   (%esp), %eax
    add      $4, %esp          # restore ESP to point at the return address

    ret

或者,如果您宁愿以存储转发摊档为代价来优化代码大小,那么在一个单词存储之后再加载一个dword:

代码语言:javascript
复制
    push     $0
    fnstcw   (%esp)
    pop      %eax         # upper 2 bytes are zero from the PUSHed data
    ret
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50308366

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档