Post by R.WieserRobert,
Post by RobertIt might have some safeguards against executing data :)
I've used the "trick" before, so I don't think so. Currently I'm torn
between the posibilities that the processor I'm using might not be having
that command, that I'm simply bungling up or that there is some kind of
memory alignment involved (the latter one would not be the first time I've
run into it).
Is there any possibility you could take a look at and post what code gets
generated for an "FXSAVE {register pointer}" ?
Post by RobertPost by R.WieserI don't get that - why only the first one, and why would
it clobber (the value at) the stack top ?
The stack is eight FP registers, any load pushes the one
on the top into the bit bucket.
True. But such a push would only clobber anything if the (circular) stack
is completely full.
Post by RobertActually, I believe the registers are a circular file,
It has to be, as my example code works : after the second FLD1 the TOS is 6.
But I can still execute a FSTP ST(2) ,which seemingly points at 6+2 = 8.
Post by Robertand the load overwrites and decrements TOS.
The info to, for instance, FLD mentions decrementing first, than store
(which is why I didn't understand your "clobbering" remark).
Post by RobertAren't those three bits (0-7) the Top-of-Stack pointer?
Yep. I was assuming that that value would (implicitily) tell me how many
values where placed on the stack. Turns out it doesn't. :-\
Post by RobertPeople sometimes compare the FPSW with the x86 flags register.
It is not.
Similar perhaps (both contain status flags), but (ofcourse) not the same.
Post by Robert34 years ago I wrote an extention to MS-DOS DEBUG.COM
to examine the x87.
I'm not sure what you mean with an 'extension' (wasn't aware that Debug
supported such a thing), but years ago I wrote something for it (using
memory patching) so it could deal with a few more opcodes.
Post by RobertConverting binaryFP to decimal FP was hard.
Thats something I still have to take a look at. Just not at this moment.
You still haven't told us what OS (DOS, Windoze, Linux) or CPU (32/64 bit)
you're running this code on....
David Lindauer's GRDB (DOS) can show the contents of FPU registers, and as you
are/were a Pascal user, so can, I think Delphi. Virtual Pascal can definitely do
it, I use the (sadly) wrapping code below:
{************** Copyright (C) Robert AH Prins 2018-2018 ****************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA *
************************************************************************
+------------+---------------------------------------------------------+
| Date | Major changes |
+------------+---------------------------------------------------------+
| | |
+------------+---------------------------------------------------------+
| 2018-09-30 | Add x_int3 to selectively enable debug code |
+------------+---------------------------------------------------------+
| 2018-08-31 | Initial version |
+------------+---------------------------------------------------------+
************************************************************************
* DEBUG.PAS *
* *
* This unit contains some code that enables viewing of extended (XMM & *
* YMM) registers in various formats. *
***********************************************************************}
unit debug;
{============================} interface {=============================}
const x_int3: boolean = false;
type
r_fpu = record { 16}
st : extended;
zz : array [0..5] of byte;
end;
r_mmx = record { 16}
case integer of
1: (_by: array [0..7] of byte;
z1 : array [0..7] of byte);
2: (_in: array [0..3] of shortint;
z2 : array [0..7] of byte);
3: (_lo: array [0..1] of longint;
z3 : array [0..7] of byte);
4: (_si: array [0..1] of single;
z4 : array [0..7] of byte);
5: (_do: array [0..0] of double;
z5 : array [0..7] of byte);
6: (_ch: array [0..7] of char;
z0 : array [0..7] of byte);
end;
r_xmm = record { 16}
case integer of
1: (_by: array [0..15] of byte);
2: (_in: array [0.. 7] of shortint);
3: (_lo: array [0.. 3] of longint);
4: (_si: array [0.. 3] of single);
5: (_do: array [0.. 1] of double);
6: (_ch: array [0..15] of char);
end;
xsave_hdr = array [0..63] of byte; { 64}
fpu = array [0..7] of r_fpu; { 128}
mmx = array [0..7] of r_mmx; { 128}
xmm = array [0..7] of r_xmm; { 128}
xsptr = ^a_xs;
a_xs = record
case integer of
1: (legacy : array [0..159] of char; { 160} // raw
legacy data
xmm_32 : xmm; { 128} //
XMM0-7 (low part of YMM0-7)
xmm_64 : xmm; { 128} //
XMM8-15 (low part of YMM8-15) (AMD64)
xsave_hdr: xsave_hdr; { 64} //
Storage bitmap for additional data
ymm_32 : xmm; { 128} //
YMM0-7 (high part, low in XMM0-XMM7)
ymm_64 : xmm); { 128} //
YMM8-15 (high part, low in XMM8-XMM15) (AMD64)
2: (fcw : smallword; { 2} // x87
FPU control word
fsw : smallword; { 2} // x87
status word
ftw : byte; { 1} // x87
res_1 : byte; { 1}
fop : smallword; { 2} // x87
last opcode
fip : longint; { 4} // x87 EIP
fcs : smallword; { 2} // x87 CS:
res_1_x64: smallword; { 2} // +
previous: RIP (AMD64)
fdp : longint; { 4} // x87
data pointer
fds : smallword; { 2} // x87 DS:
res_2_x64: smallword; { 2} // +
previous: DIP (AMD64)
mxcsr : longint; { 4} // SSE
control word
mxcsr_msk: longint; { 4}
case integer of
3: (fpu: fpu); { 128} // x87
FPU registers
4: (mmx: mmx)); { 128} // x86
MMX registers
3: (raw : array [0..1023] of byte); { 1024} //
just raw data
end;
procedure xsave;
{==========================} implementation {==========================}
{***********************************************************************
* XSAVE: *
* *
* Save the entire processor state for debugging purposes *
***********************************************************************}
procedure xsave; assembler; {&uses none} {&frame+}
var xs: array [0..2047] of char;
var xp: xsptr;
asm
//a-in xsave
cmp x_int3, true
jne @99
pushad
//------------------------------------------------------------------
// clear out save area
//------------------------------------------------------------------
lea edi, xs
xor eax, eax
mov ecx, type xs / 4
rep stosd
//------------------------------------------------------------------
// save area must be aligned on 64-byte boundary
//------------------------------------------------------------------
lea edi, xs
add edi, 63
and edi, -64
mov xp, edi
//------------------------------------------------------------------
// save everything that can be saved
//------------------------------------------------------------------
or eax, -1
or edx, -1
{ xsave [edi] } db $0f,$ae,$27
//------------------------------------------------------------------
// display data in "Watches" window
// - xp^ : all
// - xp^.fpu : all FPU registers as extended
// - xmm_32[0]._lo: contents of XMM0 as 4 longints
// - etc...
//------------------------------------------------------------------
int 3
popad
@99:
//a-out
end; {xsave}
end.
Robert
--
Robert AH Prins
robert(a)prino(d)org
The hitchhiking grandfather - https://prino.neocities.org/indez.html
Some REXX code for use on z/OS - https://prino.neocities.org/zOS/zOS-Tools.html