Reputation: 107
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
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