Chris
Chris

Reputation: 107

(fldcw [sp]) Control Word issue in assembly code

I am fairly new to assembly & it is my first programming language.

I have a question about this line:fldcw [sp]. It causes a build error: error A2031: must be index or base register

I am aware that:

sp is the 16 bit stack pointer

esp is the 32 bit stack pointer

-

I am trying to learn about utilizing the FPU Control Word. I use a Skylake Processor.

All my information is obtained at: http://www.website.masmforum.com/tutorials/fptute/fpuchap3.htm#fstcw

When I replace esp with sp it builds just fine.

Am I misunderstanding the guide? What could be causing this error?

.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

Upvotes: 0

Views: 504

Answers (1)

fuz
fuz

Reputation: 93107

In 16 bit mode, [sp] is not a valid memory operand. Only the following memory operands are valid, each having an optional displacement:

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

To fix your code, I recommend you to set up a stack frame and use bp-relative addressing:

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

However, if you are in 32 bit mode, you should just refer to esp, the 32 bit stack pointer instead. Don't ever use 16 bit registers in memory operands unless you are in 16 bit mode or know exactly what you are doing:

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

Upvotes: 1

Related Questions