【问题标题】:(fldcw [sp]) Control Word issue in assembly code(fldcw [sp]) 汇编代码中的控制字问题
【发布时间】:2018-01-29 00:04:39
【问题描述】:

我对汇编还很陌生,这是我的第一门编程语言。

我对这条线路有疑问:fldcw [sp]。它会导致构建错误:error A2031: must be index or base register

我知道:

sp 是 16 位堆栈指针

esp 是 32 位堆栈指针

-

我正在尝试了解如何使用 FPU 控制字。 我使用 Skylake 处理器。

我的所有信息都在:http://www.website.masmforum.com/tutorials/fptute/fpuchap3.htm#fstcw

当我用 sp 替换 esp 时,它构建得很好。

我是否误解了指南? 什么可能导致此错误?

.386
.model flat, stdcall
option casemap :none  

includelib \masm32\lib\msvcrt.lib
sprintf proto C :vararg
includelib \masm32\lib\user32.lib 
MessageBoxA proto :ptr,:ptr,:ptr,:DWORD
includelib \masm32\lib\kernel32.lib
ExitProcess proto :dword 

.data
   _title db "Result",13,10,0
   $interm db "%0.4f","+","%0.5f",13,10,0
   oldcw   dw   ?



.code
main PROC
LOCAL szBuf[9]:byte




  fstcw oldcw     ;get the current Control Word to retain all setting bits
                  ;not related to the rounding control (RC) bits
  fwait       ;to insure the storage instruction is completed
  mov   ax,oldcw
; and   ax,0F3FFh ;clears only the RC bits, leaving all other bits unchanged
                  ;not necessary here because both bits will be set
  or    ax,0C00h  ;this will set both bits of the RC field to the truncating mode
                  ;without affecting any of the other field's bits
  push  eax       ;use the stack to store the modified Control Word in memory
  fldcw [sp]      ;load the modified Control Word



  fldcw oldcw     ;restore the previous Control Word
  pop   eax       ;clean-up the stack
                  ;this could also retrieve a 16-bit or 32-bit integer
                  ;possibly returned by the "other FPU instruction(s)"

Finished:  


   invoke sprintf, addr szBuf, offset $interm, eax, edx
   invoke MessageBoxA, 0, addr szBuf, offset _title, 0
   invoke ExitProcess, 0



main ENDP
END main

【问题讨论】:

  • sp 是堆栈指针的低 16 位。您应该在 32 位代码中使用 esp[sp] 无论如何都不是有效的 16 位寻址。看起来链接页面中有错字。
  • eww,为什么该代码使用oldcw 的静态存储位置,但使用堆栈将新的从 EAX 反弹到 x87 单元?将两者都放在堆栈上(在不同的地方)会更有意义,因为它们都不需要超过函数。

标签: assembly x86 masm masm32


【解决方案1】:

在 16 位模式下,[sp] 不是有效的内存操作数。只有以下内存操作数是有效的,每个都有一个可选的位移:

[bx]
[bx+si]
[bx+di]
[bp]
[bp+si]
[bp+di]
[si]
[di]
[addr16]

要修复您的代码,我建议您设置一个堆栈框架并使用bp-相对寻址:

push bp       ; establish stack frame
mov bp,sp     ; dito
fstcw oldcw
fwait
mov ax,oldcw
or ax,0C00h
push ax
fldcw [bp-2]  ; load control word from stack
leave         ; tear down stack frame

但是,如果您处于 32 位模式,则应该只引用 esp,即 32 位堆栈指针。永远不要在内存操作数中使用 16 位寄存器,除非您处于 16 位模式或确切地知道自己在做什么:

fstcw oldcw
fwait
mov ax,oldcw
or ax,0C00h
push eax
fldcw [esp]   ; load control word from stack
pop eax       ; restore stack

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    相关资源
    最近更新 更多