Memory pools and alignment

F

Francesco S. Carta

Hi there,
after having been taught that nifty new thing about overriding
"operator new" and "operator delete", I've started messing with them
and with custom allocations.

Now I have some kind of memory pool which allocates a big chunk of
memory via "new char[pool_size]" and some functions which return sub-
chunks of it via void*.

For the moment I prefer to skip about the details - I will post the
implementation later in order to straighten out something more, with
your help - if I'll feel brave enough to actually post it.

So then, I'm testing it in this way:
-------
char* pchar = static_cast<char*>(Arena::allocate(sizeof(char)*3));
short* pshort = static_cast<short*>(Arena::allocate(sizeof(short)
*3));
int* pint = static_cast<int*>(Arena::allocate(sizeof(int)*3));
for(int i = 0; i < 3; ++i) {
pchar = i+1;
pshort = i+1;
pint = i+1;
}
-------

A straight hex-dump of the pool gives me this:
-------
010203010002000300010000000200000003000000adbeefdeadbeef...
-------
Where the "deadbeef" pattern highlights the unused part of the pool.

Well that made me wonder. I'd have expected to hit some memory
alignment problem, instead I am getting a nicely packed and (so far)
working pool... how's that?

My implementation aligns types to their size boundaries when laying
out classes, for example:
-------
struct foo {
bool b;
int i;
char c;
long long ll;
foo() : b(1), i(2), c(3), ll(4) {}
};
-------

Dumping the memory of a foo instance I get the following:
-------
01adbeef0200000003adbeefdeadbeef0400000000000000
-------

Where the "deadbeef" pattern highlights the padding.

Why these two different behaviors?
Am I simply lucky getting my pool so nicely packed?

Honestly, I somehow hoped for problems to show up... but they didn't
yet.
I'll continue experimenting.
 
S

SG

[...]
I've started messing with them and with custom allocations.
[...]
So then, I'm testing it in this way:
-------
   char* pchar = static_cast<char*>(Arena::allocate(sizeof(char)*3));
   short* pshort = static_cast<short*>(Arena::allocate(sizeof(short)
*3));
   int* pint = static_cast<int*>(Arena::allocate(sizeof(int)*3));
   for(int i = 0; i < 3; ++i) {
       pchar = i+1;
       pshort = i+1;
       pint = i+1;
   }
-------

A straight hex-dump of the pool gives me this:
-------
010203010002000300010000000200000003000000adbeefdeadbeef...
-------
Where the "deadbeef" pattern highlights the unused part of the pool.

Well that made me wonder. I'd have expected to hit some memory
alignment problem, instead I am getting a nicely packed and (so far)
working pool... how's that?


You seem to be working on an achitecture that's able to access at ints
and shorts at non-aligned adresses. So, in your case it works but it
may also be a bit slower.
My implementation aligns types to their size boundaries when laying
out classes, for example:
-------
struct foo {
    bool b;
    int i;
    char c;
    long long ll;
    foo() : b(1), i(2), c(3), ll(4) {}};

-------

Dumping the memory of a foo instance I get the following:
-------
01adbeef0200000003adbeefdeadbeef0400000000000000
-------

Where the "deadbeef" pattern highlights the padding.

Why these two different behaviors?

You mean, why it's padded but it would work even without padding? I
think the answer is "speed". Accessing non-aligned scalar types might
be slower. I think this is the case on an x86 architecture. It works
but it's slower.

Cheers,
SG
 
F

Francesco S. Carta

SG said:
[...]
I've started messing with them and with custom allocations.
[...]
So then, I'm testing it in this way:
-------
char* pchar = static_cast<char*>(Arena::allocate(sizeof(char)*3));
short* pshort = static_cast<short*>(Arena::allocate(sizeof(short)
*3));
int* pint = static_cast<int*>(Arena::allocate(sizeof(int)*3));
for(int i = 0; i < 3; ++i) {
pchar = i+1;
pshort = i+1;
pint = i+1;
}
-------

A straight hex-dump of the pool gives me this:
Well that made me wonder. I'd have expected to hit some memory
alignment problem, instead I am getting a nicely packed and (so far)
working pool... how's that?

You seem to be working on an achitecture that's able to access at ints
and shorts at non-aligned adresses. So, in your case it works but it
may also be a bit slower.


My implementation aligns types to their size boundaries when laying
out classes, for example:
-------
struct foo {
bool b;
int i;
char c;
long long ll;
foo() : b(1), i(2), c(3), ll(4) {}};

Dumping the memory of a foo instance I get the following:
Where the "deadbeef" pattern highlights the padding.
Why these two different behaviors?

You mean, why it's padded but it would work even without padding? I
think the answer is "speed". Accessing non-aligned scalar types might
be slower. I think this is the case on an x86 architecture. It works
but it's slower.


Ah, thanks a lot, now it makes sense.

About your question: I wasn't all that sure about asking that.
Actually, I wasn't sure at all about whether I was interpreting my
output in the correct way - IOW, about whether it was really "working"
or not.

BTW, the processor is an AMD Athlon XP1800+.

I've just tried to allocate floats and doubles in the same way, and
I'm getting them working fine at odd addresses.

Some pointer about how to check if the CPU supports such non-aligned
addresses?

What should I expect on CPUs which cannot access them?
 
F

Francesco S. Carta

Francesco S. Carta said:
What should I expect on CPUs which cannot access them?

After some searches on the web seems I'm going to have some bad
crashes or unexpected behavior in such cases - part of the bits being
ignored, for example.

Enough to ensure that I would be better not doing that.
Some pointer about how to check if the CPU supports such non-aligned
addresses?

But for the above, all I was able to find is some "there is no way to
check it" mention - of course, I was looking for some check that can
be executed at run-time or at compile-time, not by reading the CPU
specs ;-)

Whatever, curiosity satisfied, for the moment.
 
M

Michael Tsang

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

#include <stdlib.h>

int main(void) {

#if defined(__GNUC__)
# if defined(__i386__)
/* Enable Alignment Checking on x86 */
__asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

/* malloc() always provides aligned memory */
void *cptr = malloc(sizeof(int) + 1);

/* Increment the pointer by one, making it misaligned */
int *iptr = (int *) ++cptr;

/* Dereference it as an int pointer, causing an unaligned access */
*iptr = 42;

return 0;
}

This is the code which fails on x86 CPUs with unaligned access.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkrUCF8ACgkQG6NzcAXitM9/HgCfRRM3kYfawVxeVavusQxAwC/M
ZQYAn36v5VE+Q8aRM20YXYIxdNVdRkDd
=6sCp
-----END PGP SIGNATURE-----
 
J

James Kanze

after having been taught that nifty new thing about overriding
"operator new" and "operator delete", I've started messing
with them and with custom allocations.
Now I have some kind of memory pool which allocates a big
chunk of memory via "new char[pool_size]" and some functions
which return sub- chunks of it via void*.
For the moment I prefer to skip about the details - I will
post the implementation later in order to straighten out
something more, with your help - if I'll feel brave enough to
actually post it.
So then, I'm testing it in this way:
-------
char* pchar = static_cast<char*>(Arena::allocate(sizeof(char)*3));
short* pshort = static_cast<short*>(Arena::allocate(sizeof(short)
*3));
int* pint = static_cast<int*>(Arena::allocate(sizeof(int)*3));
for(int i = 0; i < 3; ++i) {
pchar = i+1;
pshort = i+1;
pint = i+1;
}
-------

A straight hex-dump of the pool gives me this:
Well that made me wonder. I'd have expected to hit some memory
alignment problem, instead I am getting a nicely packed and
(so far) working pool... how's that?

All issues concerning alignment are implementation defined (or
are they simply unspecified?); all the language specification
says is that there may be some alignment restrictions.
Depending on the hardware/OS, different situations occur:

-- There are no alignment restrictions what so ever. This is
the case, for example, on 8 bit processors (are there any of
those left), like the 8080 or the Z80. This is also the
case on some embedded processors, which make char 32 bits
(or whatever), and sizeof(int) == 1.

-- The hardware handles alignment problems transparently.
Typically, in this case, misaligned data may result in the
code running slightly slower, but even this isn't certain;
if the misaligned data still fits in a cache or a bus line,
it's likely not even to cause a slowdown, and of course, the
read or write pipeline might absorb any slowdown as well,
depending on what else you're doing in the code.

The most notable processor in this case is the Intel
x86 architecture. Otherwise, I think it's pretty rare.
(The old NSC 32xxx chips supported it, and I think some
versions of the Motorola 68000. Neither are in use today,
however.)

-- The hardware traps on a misaligned access, but the OS
catches the trap and simulates the access. Misaligned data
results in a very significant slowdown.

I mention this as a possibility; I don't know of any system
off hand where it is the case.

The hardware traps on a misaligned access, and this trap is
mapped to a signal, or terminates the process, or something
along those lines. This is by far the most common
situation: Sparc, Power PC, HP's PA risc chips and probably
the Itanium, IBM mainframes and the old RS/6000, and in the
distant past, PDP-11 and Interdata 8/32. (Come to think of
it, I seem to recall reading somewhere that the Vax
supported misaligned accesses, like the x86. The last DEC
machine I actually worked on, however, was a PDP-11, so I'm
not sure.)

Since in other postings, you've indicated that your a hobby
programmer, not a professional, it seems very, very likely that
you're running on an Intel based machine (or on an AMD
compatible chip), so you won't immediately see any effect of
misaligned data---in small examples like your test code, it's
likely that you won't even see any difference in speed.
My implementation aligns types to their size boundaries when laying
out classes, for example:
-------
struct foo {
bool b;
int i;
char c;
long long ll;
foo() : b(1), i(2), c(3), ll(4) {}};

Dumping the memory of a foo instance I get the following:
Where the "deadbeef" pattern highlights the padding.
Why these two different behaviors?

The implementation is allowed to pad pretty much however it
wants. I think it's even "unspecified", rather than
"implementation defined", so the implementation is not even
required to document it (but I could be wrong about that). Most
Intel implementations do pad for alignment (with some variance
concerning long double: 10, 12 or 16 bytes total, depending on
who wrote the compiler, with the additional bytes often being
part of the type, rather than padding).
Am I simply lucky getting my pool so nicely packed?
Honestly, I somehow hoped for problems to show up... but they
didn't yet.

The problem is that if your implementation "requires" alignment,
but you neglect it, the results are undefined behavior, so you
may or may not see an effect. Your code will crash on a Sparc
(bus error) or most modern non-Intel general purpose computers,
but will run without problems on an Intel.
 
J

James Kanze

After some searches on the web seems I'm going to have some
bad crashes or unexpected behavior in such cases - part of the
bits being ignored, for example.
Enough to ensure that I would be better not doing that.
But for the above, all I was able to find is some "there is no
way to check it" mention - of course, I was looking for some
check that can be executed at run-time or at compile-time, not
by reading the CPU specs ;-)

Runtime is easy. Just try it---if the program crashes, the
processor doesn't support misaligned access. If you don't want
the actual process to crash, spawn a child and check its return
code. (I think system would suffice most of the time, so you'd
be fairly portable.)
 
I

Ian Collins

James said:
All issues concerning alignment are implementation defined (or
are they simply unspecified?); all the language specification
says is that there may be some alignment restrictions.
Depending on the hardware/OS, different situations occur:

-- There are no alignment restrictions what so ever. This is
the case, for example, on 8 bit processors (are there any of
those left), like the 8080 or the Z80. This is also the
case on some embedded processors, which make char 32 bits
(or whatever), and sizeof(int) == 1.

-- The hardware handles alignment problems transparently.
Typically, in this case, misaligned data may result in the
code running slightly slower, but even this isn't certain;
if the misaligned data still fits in a cache or a bus line,
it's likely not even to cause a slowdown, and of course, the
read or write pipeline might absorb any slowdown as well,
depending on what else you're doing in the code.

The most notable processor in this case is the Intel
x86 architecture. Otherwise, I think it's pretty rare.
(The old NSC 32xxx chips supported it, and I think some
versions of the Motorola 68000. Neither are in use today,
however.)

PPC does as well.
-- The hardware traps on a misaligned access, but the OS
catches the trap and simulates the access. Misaligned data
results in a very significant slowdown.

I mention this as a possibility; I don't know of any system
off hand where it is the case.

Sparc when compiled with the appropriate compiler flags. Ugly!
 
F

Francesco S. Carta

Michael Tsang said:
#include <stdlib.h>

int main(void) {

#if defined(__GNUC__)
# if defined(__i386__)
        /* Enable Alignment Checking on x86 */
        __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
        /* Enable Alignment Checking on x86_64 */
        __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

        /* malloc() always provides aligned memory */
        void *cptr = malloc(sizeof(int) + 1);

        /* Increment the pointer by one, making it misaligned */
        int *iptr = (int *) ++cptr;

        /* Dereference it as an int pointer, causing an unaligned access */
        *iptr = 42;

        return 0;

}

This is the code which fails on x86 CPUs with unaligned access.

Actually, I was looking for a way to check whether the CPU supported
the unaligned access, not for a way to ensure its failure where
supported :p

Also, I didn't test your code - I don't feel comfortable running
assembly which writes at fixed memory addresses (if I got your snippet
right) without understanding what it does, but, of course, I believe
you know what your posted.

Thanks a lot Michael, I'll investigate it - sooner or later I wanted
to dig some assembly and its implications too, as I've been suggested.
 
F

Francesco S. Carta

James Kanze said:
after having been taught that nifty new thing about overriding
"operator new" and "operator delete", I've started messing
with them and with custom allocations.
Now I have some kind of memory pool which allocates a big
chunk of memory via "new char[pool_size]" and some functions
which return sub- chunks of it via void*.
For the moment I prefer to skip about the details - I will
post the implementation later in order to straighten out
something more, with your help - if I'll feel brave enough to
actually post it.
So then, I'm testing it in this way:
-------
    char* pchar = static_cast<char*>(Arena::allocate(sizeof(char)*3));
    short* pshort = static_cast<short*>(Arena::allocate(sizeof(short)
*3));
    int* pint = static_cast<int*>(Arena::allocate(sizeof(int)*3));
    for(int i = 0; i < 3; ++i) {
        pchar = i+1;
        pshort = i+1;
        pint = i+1;
    }
-------
A straight hex-dump of the pool gives me this:
-------
010203010002000300010000000200000003000000adbeefdeadbeef...
-------
Where the "deadbeef" pattern highlights the unused part of the pool.
Well that made me wonder. I'd have expected to hit some memory
alignment problem, instead I am getting a nicely packed and
(so far) working pool... how's that?


All issues concerning alignment are implementation defined (or
are they simply unspecified?); all the language specification
says is that there may be some alignment restrictions.
Depending on the hardware/OS, different situations occur:

 -- There are no alignment restrictions what so ever.  This is
    the case, for example, on 8 bit processors (are there any of
    those left), like the 8080 or the Z80.  This is also the
    case on some embedded processors, which make char 32 bits
    (or whatever), and sizeof(int) == 1.

 -- The hardware handles alignment problems transparently.
    Typically, in this case, misaligned data may result in the
    code running slightly slower, but even this isn't certain;
    if the misaligned data still fits in a cache or a bus line,
    it's likely not even to cause a slowdown, and of course, the
    read or write pipeline might absorb any slowdown as well,
    depending on what else you're doing in the code.

    The most notable processor in this case is the Intel
    x86 architecture.  Otherwise, I think it's pretty rare.
    (The old NSC 32xxx chips supported it, and I think some
    versions of the Motorola 68000.  Neither are in use today,
    however.)

 -- The hardware traps on a misaligned access, but the OS
    catches the trap and simulates the access.  Misaligned data
    results in a very significant slowdown.

    I mention this as a possibility; I don't know of any system
    off hand where it is the case.

    The hardware traps on a misaligned access, and this trap is
    mapped to a signal, or terminates the process, or something
    along those lines.  This is by far the most common
    situation: Sparc, Power PC, HP's PA risc chips and probably
    the Itanium, IBM mainframes and the old RS/6000, and in the
    distant past, PDP-11 and Interdata 8/32.  (Come to think of
    it, I seem to recall reading somewhere that the Vax
    supported misaligned accesses, like the x86.  The last DEC
    machine I actually worked on, however, was a PDP-11, so I'm
    not sure.)

Since in other postings, you've indicated that your a hobby
programmer, not a professional, it seems very, very likely that
you're running on an Intel based machine (or on an AMD
compatible chip), so you won't immediately see any effect of
misaligned data---in small examples like your test code, it's
likely that you won't even see any difference in speed.


My implementation aligns types to their size boundaries when laying
out classes, for example:
-------
struct foo {
    bool b;
    int i;
    char c;
    long long ll;
    foo() : b(1), i(2), c(3), ll(4) {}};

The implementation is allowed to pad pretty much however it
wants.  I think it's even "unspecified", rather than
"implementation defined", so the implementation is not even
required to document it (but I could be wrong about that).  Most
Intel implementations do pad for alignment (with some variance
concerning long double: 10, 12 or 16 bytes total, depending on
who wrote the compiler, with the additional bytes often being
part of the type, rather than padding).
Am I simply lucky getting my pool so nicely packed?
Honestly, I somehow hoped for problems to show up... but they
didn't yet.

The problem is that if your implementation "requires" alignment,
but you neglect it, the results are undefined behavior, so you
may or may not see an effect.  Your code will crash on a Sparc
(bus error) or most modern non-Intel general purpose computers,
but will run without problems on an Intel.


Yes, I'm a hobbyist indeed, as you correctly recall. I'm running on an
AMD and my code does currently use this feature without checking for
its presence.

Thanks a lot for the details James, now what I'm dealing with is even
more clear.
 
F

Francesco S. Carta

Runtime is easy.  Just try it---if the program crashes, the
processor doesn't support misaligned access.  If you don't want
the actual process to crash, spawn a child and check its return
code.  (I think system would suffice most of the time, so you'd
be fairly portable.)

With "spawn a child" you mean a thread, right? Never been there, but
I'll have to, this seems a good excuse to start - too bad I have no
different CPUs under my hands to test it.

Thanks for pointing this out.
 
F

Francesco S. Carta

Francesco S. Carta said:
With "spawn a child" you mean a thread, right? Never been there, but
I'll have to, this seems a good excuse to start - too bad I have no
different CPUs under my hands to test it.

Uhm, but I can use Michael's code to ensure that thread's failure and
go on with the "aligned" version of the program... good, very good.
 
F

Francesco S. Carta

Francesco S. Carta said:
Actually, I was looking for a way to check whether the CPU supported
the unaligned access, not for a way to ensure its failure where
supported :p

But thinking again, I can really take advantage of this.

Once I'm there, how does it works? Once I've activated that check,
does it goes along for just that thread/program or the whole system
goes in that mode?

In the latter case, I'll need a way to turn that check off, I suppose.
 
F

Francesco S. Carta

Michael Tsang said:
#include <stdlib.h>

int main(void) {

#if defined(__GNUC__)
# if defined(__i386__)
        /* Enable Alignment Checking on x86 */
        __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
        /* Enable Alignment Checking on x86_64 */
        __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

        /* malloc() always provides aligned memory */
        void *cptr = malloc(sizeof(int) + 1);

        /* Increment the pointer by one, making it misaligned */
        int *iptr = (int *) ++cptr;

The line above fails to compile because cptr is a void* and cannot be
incremented - at least, my compiler refuses to.

This one works:
-------
/* malloc() always provides aligned memory */
char *cptr = static_cast<char*>(malloc(sizeof(int) + 1));

/* Increment the pointer by one, making it misaligned */
        /* Dereference it as an int pointer, causing an unaligned access */
        *iptr = 42;

        return 0;

}

This is the code which fails on x86 CPUs with unaligned access.

I'm still trying to understand how that assembly stuff works, I'm
searching the web but some hint here would be really appreciated.
 
J

James Kanze

With "spawn a child" you mean a thread, right? Never been there, but
I'll have to, this seems a good excuse to start - too bad I have no
different CPUs under my hands to test it.

No, a child process. If you do have a bus error, then you'll kill the
entire process in which it occurs, so you probably want it to occur in
some other process. Basically, you write some little program like:

int
main()
{
char* p = new char[100];
double* d = reinterpret_cast<double*>(p + 1);
*d = 1.2;
return 0 ;
}

, then in the program where you want to test the behavior of mis-
aligned
accesses:

if (system(program) != 0) {
// Misaligned access causes hard error...
} else {
// Hardware or system copes with misaligned access...
}

Still, to be frank, I don't really know what you could do with the
information. You're probably better off by keeping everything
correctly
aligned everywhere.
 
F

Francesco S. Carta

James Kanze said:
With "spawn a child" you mean a thread, right? Never been there, but
I'll have to, this seems a good excuse to start - too bad I have no
different CPUs under my hands to test it.

No, a child process. If you do have a bus error, then you'll kill the
entire process in which it occurs, so you probably want it to occur in
some other process. Basically, you write some little program like:

int
main()
{
char* p = new char[100];
double* d = reinterpret_cast<double*>(p + 1);
*d = 1.2;
return 0 ;
}

, then in the program where you want to test the behavior of mis-
aligned
accesses:

if (system(program) != 0) {
// Misaligned access causes hard error...
} else {
// Hardware or system copes with misaligned access...
}

Still, to be frank, I don't really know what you could do with the
information. You're probably better off by keeping everything
correctly
aligned everywhere.

Ah, OK, that's a child process. Very well.

To balance the frankness, I'm not after anything in particular.

As I use to say, that's just digging for the sake of digging. Using my
time in this way - I mean, trying & posting whatever crosses my mind
in a particular moment - leads me to learn new things and to fix old
ones, having fun at the same time.

Of course, I'll let "built-in new" allocate stuff for me for a long
time - shall I need someday, I'll have some grip on pools, alignment
and custom allocations ;-)

Thanks again for your explanations.
 
T

Thomas J. Gritzan

Francesco said:
The line above fails to compile because cptr is a void* and cannot be
incremented - at least, my compiler refuses to.

Of course. You cannot increment a void*, not in C nor in C++, because
void has no sizeof (or because the object must be complete).
I'm still trying to understand how that assembly stuff works, I'm
searching the web but some hint here would be really appreciated.

A little bit offtopic x86 assembly:

pushf /* pushes the FLAGS register onto the stack */
orl $0x40000,(%esp) /* ESP[0] |= 0x40000 */
popf /* reloads the FLAGS register from the stack */

The second command loads the value from the place where ESP (stack
pointer) points to, modifies the value by ORing it with 0x40000 and
stores it back.
This codes essentially sets the 18th bit in the FLAGS register. It's the
"alignment check" flag, as written here:
http://en.wikipedia.org/wiki/FLAGS_register_(computing)
 
F

Francesco S. Carta

Thomas J. Gritzan said:
Francesco S. Carta schrieb:


The line above fails to compile because cptr is a void* and cannot be
incremented - at least, my compiler refuses to.

Of course. You cannot increment a void*, not in C nor in C++, because
void has no sizeof (or because the object must be complete).
I'm still trying to understand how that assembly stuff works, I'm
searching the web but some hint here would be really appreciated.

A little bit offtopic x86 assembly:

pushf /* pushes the FLAGS register onto the stack */
orl $0x40000,(%esp) /* ESP[0] |= 0x40000 */
popf /* reloads the FLAGS register from the stack */

The second command loads the value from the place where ESP (stack
pointer) points to, modifies the value by ORing it with 0x40000 and
stores it back.
This codes essentially sets the 18th bit in the FLAGS register. It's the
"alignment check" flag, as written here:http://en.wikipedia.org/wiki/FLAGS_register_(computing)

Thanks a lot Thomas, both for the explanations and for the pointer.
 
J

James Kanze

Of course. You cannot increment a void*, not in C nor in C++,
because void has no sizeof (or because the object must be
complete).

But the original code is clearly designed for g++. And g++ does
(or did) allow you to increment a void*, at least by default, as
an extension. (At least in this example, too, g++ is using a
non-standard syntax for inline assembler too.)
 
J

Joe Smith

Francesco S. Carta said:
But thinking again, I can really take advantage of this.

Once I'm there, how does it works? Once I've activated that check,
does it goes along for just that thread/program or the whole system
goes in that mode?

In the latter case, I'll need a way to turn that check off, I suppose.

The EFLAGS register is process specific. The OS kernel keeps track of the
value it should have for each process. There are (virtually?) no registers
that a process can set that could have any impact on annother process,
baring a completely broken kernel.

The assembly shown loads the EFLAGS register into the ESP register, nors the
ESP register in place with the value 0x40000 in place, and then loads the
new value into the EFLAGS register.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top