Posted: Thu Apr 02, 2026 11:32 am Post subject: Push/Pop Floats the correct way... [Closed]
Goal: "update" an existing float stack value.
=> details: see here [ https://ibb.co/album/ccBpXF ] (pics in reverse order)
1. the current float_value on the stack = 66 (which i'd like to change to 100)
2. what i do now, is pop - in this case - that 1st value - then push/load the new value...
Is this the proper way to do it ? And whatIf you'd like to update st(3) here instead ?
and yep, did some googling here, but could not find a single page describing exactly what i "wanted" to do (sort of). Most of them refer to the FLD instruction.
ps:
> When you break and follow through the action, you'll notice that the stack then shuffles one value down; and the 1st value wounds up at st(7).
> the FLD then pushes the new value to st(0) and "drops" st(7) entirely
Last edited by paul44 on Mon Apr 06, 2026 12:09 pm; edited 1 time in total
1. the current float_value on the stack = 66 (which i'd like to change to 100)
2. what i do now, is pop - in this case - that 1st value - then push/load the new value...
Is this the proper way to do it ? And whatIf you'd like to update st(3) here instead ?
I think that's fine.
For modifying ST(3), you can use `fxch st(3)` to swap ST(0) and ST(3), do the same pop old value / push new value, and `fxch st(3)` again to put the values back in place before you return to the original code.
paul44 wrote:
ps:
> When you break and follow through the action, you'll notice that the stack then shuffles one value down; and the 1st value wounds up at st(7).
> the FLD then pushes the new value to st(0) and "drops" st(7) entirely
Virtually, the x87 FPU operates as a stack. You can push values onto it and pop values off. When you pop a value off the stack, it is removed from the stack and can't be accessed again.
Physically, the x87 FPU has 8 data registers that are used to store values. There's a pointer that points to the register that's currently the top of the stack. "Pushing" a value corresponds to decrementing this pointer and loading the value from memory into the register, while "popping" a value corresponds to incrementing this pointer and storing the value from the register into memory. The pointer will "wrap around" like a ring buffer when needed.
There's also a "tag" associated with each of the 8 data registers that indicates whether a register is in use or empty. You generally can't access empty registers through normal means.
Example:
Code:
reg tag value
7 Empty 0
6 Empty 0
5 Empty 0 <- TOP
4 Empty 0
3 Empty 0
2 Empty 0
1 Empty 0
0 Empty 0
fld [value1]
fld [value2]
fld [value3]
reg tag value
7 Empty 0
6 Empty 0
5 Empty 0
4 Number 1 ST(2)
3 Number 2 ST(1)
2 Number 3 ST(0) <- TOP
1 Empty 0
0 Empty 0
fstp st(0)
fstp st(0)
reg tag value
7 Empty 0
6 Empty 0
5 Empty 0
4 Number 1 ST(0) <- TOP
3 Empty 2
2 Empty 3
1 Empty 0
0 Empty 0
This loads 3 values then pops 2 values. Even though the values were popped and are now "empty", they can still be accessed through other means such as debuggers like CE. CE doesn't account for the tag at all, however, and simply displays each register as ST(0) - ST(7) relative to the TOP pointer. This is why you see st(0) end up as st(7) after you pop it.
Pushing a new value would overwrite what CE displays as ST(7). This overwrites the old data and "drops it entirely."
For more information, see Intel's Software Developer's Manual Volume 1: Basic Architecture, chapter 8 "Programming with the x87 FPU". _________________
I don't know where I'm going, but I'll figure it out when I get there.
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum