Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

popfd compile error on win64

Naveen_Tulabandula
2,596 Views

This is what i am trying to achieve ::
I got eflags value into a context structure "ctx" using GetThreadContext Microsoft API
Now my intention is to set the eflags value in this structure to current thread
This is how i am doing

/*I got to know that we cannot directly modify eflags register,so....
1. I am getting the value in ctx structure to Eax register
2. Pushing the value in Eax register to stack
3. Poping the recently pushed value into eflags register */

    mov eax, dword ptr [ctx+0x044];   // as eflags is 32-bit I am using eax instead of rax
    push eax;
    popfd;

when i try to compile this, i am seeing below compile error

C:\1\stacktracing.c(81): (col. 5) error #13252: Unsupported instruction form in asm instruction push.
C:\1\stacktracing.c(82): (col. 5) error #13250: Opcode POPFD unsupported by architecture in asm instruction popfd.

1. Can't we push 32-bit eax  to a stack in 64-bit machine ....if yes, any alternative?
2. Can't we use popfd in 64-bit machine ?

Thanks & Regards
Naveen

0 Kudos
33 Replies
SergeyKostrov
Valued Contributor II
2,095 Views
Do you use Intel or Microsoft C++ compiler on a 64-bit Windows platform?
0 Kudos
Naveen_Tulabandula
2,095 Views

Let me know if i am in the right path -- reg what i want to achieve or is there any drawback in the way i am doing

0 Kudos
Naveen_Tulabandula
2,095 Views

I use icl of below version

icl
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.5.229 Build 20120731
Copyright (C) 1985-2011 Intel Corporation. All rights reserved.

icl: command line error: no files specified; for help type "icl /help"

0 Kudos
SergeyKostrov
Valued Contributor II
2,095 Views
Do you use inline assembler in a C/C++ source file? >>...Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.5.229 Build 20120731... I will verify Push Eax and Popfd with a version 13 of Intel C++ compiler ( 64-bit ).
0 Kudos
mecej4
Honored Contributor III
2,095 Views

Can't we push 32-bit eax  to a stack in 64-bit machine

No. Just as you cannot do push ax or pop ax in 32-bit ASM, and you cannot do push al or pop al in 16-bit ASM. The primary reason is that in 64-bit mode the stack has to be aligned on 8-byte boundaries.

Secondly, why are you bothering with eflags in 64-bit mode, instead of using rflags?

For definitive answers on these and related questions, refer to the Intel instruction set reference manuals:

http://download.intel.com/products/processor/manual/253666.pdf

http://download.intel.com/products/processor/manual/253667.pdf

0 Kudos
Naveen_Tulabandula
2,095 Views

@Sergey Kostrov

I couldn't get what you mean by "Do you use inline assembler in a C/C++ source file?"

I am writing assembly as below

_asm
{

//First restore eflags
//mov eflags, dword ptr [ctx+0x044];
mov eax, dword ptr [ctx+0x044];
push Rax;
popfq;



mov Rax,qword ptr [ctx+0x078] ;
mov Rcx,qword ptr [ctx+0x080];
mov Rdx,qword ptr [ctx+0x088] ;
mov Rbx,qword ptr [ctx+0x090];
mov Rsp,qword ptr [ctx+0x098] ;
mov Rbp,qword ptr [ctx+0x0a0];
mov Rsi,qword ptr [ctx+0x0a8] ;
mov Rdi,qword ptr [ctx+0x0b0];
mov R8,qword ptr [ctx+0x0b8] ;
mov R9,qword ptr [ctx+0x0c0];
mov R10,qword ptr [ctx+0x0c8] ;
mov R11,qword ptr [ctx+0x0d0];
mov R12,qword ptr [ctx+0x0d8] ;
mov R13,qword ptr [ctx+0x0e0];
mov R14,qword ptr [ctx+0x0e8] ;
mov R15,qword ptr [ctx+0x0f0];


mov cs, WORD ptr [ctx+0x038];
mov ds, WORD ptr [ctx+0x03a];
mov es, WORD ptr [ctx+0x03c];
mov fs, WORD ptr [ctx+0x03e];
mov gs, WORD ptr [ctx+0x040];
mov ss, WORD ptr [ctx+0x042];


//mov Rip,qword ptr [ctx+0x0f8];
jmp qword ptr [ctx+0x0f8];
done:
}

All general purpose registers are getting updated properly...but i am seeing issue with eflags and segment registers

@mecej4

I generated a .i file and saw that CONTEXT structure in win64 is having EFLAGS in it....that is why i am trying to restore eflags inplace of rflags

0 Kudos
SergeyKostrov
Valued Contributor II
2,095 Views
>>...I couldn't get what you mean by "Do you use inline assembler in a C/C++ source file?" In general, C/C++ source files have extensions *.c or *.cpp. Source files for pure Assembler have extension *.asm.
0 Kudos
Naveen_Tulabandula
2,095 Views

OK. I am using inline assemby in "**.c" file

In my first post....you can see the file name in the error messages i posted.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,095 Views
0 Kudos
SergeyKostrov
Valued Contributor II
2,095 Views
>>OK. I am using inline assemby in "**.c" file >> >>In my first post....you can see the file name in the error messages i posted. I will be able to verify your codes with Intel C++ Compiler XE 13.1.0.149 [ IA-32 & X64 ] ( Update 2 ). Unfortunately I don't use a 64-bit version of Intel C++ compiler version 12.x.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,095 Views
0 Kudos
SergeyKostrov
Valued Contributor II
2,095 Views
I didn't have any problems with a 64-bit Intel C++ compiler version 13.1.0.149 Build 20130118 ( Update 2 ). Here is my test case: typedef struct tagCTX { __int64 reg[24]; } CTX; int main( void ) { CTX ctx = { 0x0 }; _asm { // First restore eflags // mov eflags, dword ptr [ ctx+0x044 ] mov eax, dword ptr [ ctx+0x044 ] push Rax popfq mov Rax, QWORD PTR [ ctx+0x078 ] mov Rcx, QWORD PTR [ ctx+0x080 ] mov Rdx, QWORD PTR [ ctx+0x088 ] mov Rbx, QWORD PTR [ ctx+0x090 ] mov Rsp, QWORD PTR [ ctx+0x098 ] mov Rbp, QWORD PTR [ ctx+0x0a0 ] mov Rsi, QWORD PTR [ ctx+0x0a8 ] mov Rdi, QWORD PTR [ ctx+0x0b0 ] mov R8, QWORD PTR [ ctx+0x0b8 ] mov R9, QWORD PTR [ ctx+0x0c0 ] mov R10, QWORD PTR [ ctx+0x0c8 ] mov R11, QWORD PTR [ ctx+0x0d0 ] mov R12, QWORD PTR [ ctx+0x0d8 ] mov R13, QWORD PTR [ ctx+0x0e0 ] mov R14, QWORD PTR [ ctx+0x0e8 ] mov R15, QWORD PTR [ ctx+0x0f0 ] mov cs, WORD PTR [ ctx+0x038 ] mov ds, WORD PTR [ ctx+0x03a ] mov es, WORD PTR [ ctx+0x03c ] mov fs, WORD PTR [ ctx+0x03e ] mov gs, WORD PTR [ ctx+0x040 ] mov ss, WORD PTR [ ctx+0x042 ] mov Rip, QWORD PTR [ ctx+0x0f8 ] // jmp QWORD PTR [ ctx+0x0f8 ] Done: } return ( int )0; }
0 Kudos
Marián__VooDooMan__M
New Contributor II
2,095 Views

For corectness, it should be

Sergey Kostrov wrote:

...

_asm
{
// First restore eflags
// mov rflags, qword ptr [ ctx+0x044 ]
mov rax, qword ptr [ ctx+0x044 ]

push Rax
popfq

...

...since upper half of rflags (reserved - do not use) is filled with leftover trash in upper half of RAX.

Indeed s/he should use pushfq/popfq pair, since there is no such instruction in long mode such as pushfd nor popfd. If there were such instructions, it would lead to stack pointer mis-alignment.

0 Kudos
SergeyKostrov
Valued Contributor II
2,095 Views
>>...For corectness, it should be... Marian, Take a look at these two error messages: >>... >>C:\1\stacktracing.c(81): (col. 5) error #13252: Unsupported instruction form in asm instruction push. >>C:\1\stacktracing.c(82): (col. 5) error #13250: Opcode POPFD unsupported by architecture in asm instruction popfd. >>... 1. These two messages are very confusing and Naveen thinks that these two instructions are not supported on a 64-bit platform. Try to use the test case I've posted with Microsoft 64-bit C++ compiler and you will see similar error messages. 2. Then, we're trying to understand what is wrong with compilation of Naveen's codes with inline assembler because something else is really wrong. Microsoft's 64-bit C++ compiler doesn't support inline assembles at all (!) for 64-bit platforms. Intel 64-bit C++ compiler supports inline assembler for 64-bit platforms and I verified it with version 13. But, Naveen is using version 12 and I don't have any chance to verify it. It is possible that version 12 doesn't support it. So, If you have Intel 64-bit C++ compiler version 12 simply try to compile a test case I've posted. All the rest things, I mean execution at run-time, is Naveen's assignment. Naveen, Take a look at Intel Instruction Reference Guide because it has complete descriptions for these two instructions.
0 Kudos
SergeyKostrov
Valued Contributor II
2,095 Views
Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2 (2A, 2B & 2C): Instruction Set Reference, A-Z Order Number: 325383-044US August 2012 Page 794 ... Description Pops a doubleword (POPFD) from the top of the stack (if the current operand-size attribute is 32) and stores the value in the EFLAGS register, or pops a word from the top of the stack (if the operand-size attribute is 16) and stores it in the lower 16 bits of the EFLAGS register (that is, the FLAGS register). These instructions reverse the operation of the PUSHF/PUSHFD instructions. The POPF (pop flags) and POPFD (pop flags double) mnemonics reference the same opcode. The POPF instruction is intended for use when the operand-size attribute is 16; the POPFD instruction is intended for use when the operand-size attribute is 32. Some assemblers may force the operand size to 16 for POPF and to 32 for POPFD. Others may treat the mnemonics as synonyms (POPF/POPFD) and use the setting of the operand-size attribute to determine the size of values to pop from the stack. The effect of POPF/POPFD on the EFLAGS register changes, depending on the mode of operation. When the processor is operating in protected mode at privilege level 0 (or in real-address mode, the equivalent to privilege level 0), all non-reserved flags in the EFLAGS register except RF1, VIP, VIF, and VM may be modified. VIP, VIF and VM remain unaffected. When operating in protected mode with a privilege level greater than 0, but less than or equal to IOPL, all flags can be modified except the IOPL field and VIP, VIF, and VM. Here, the IOPL flags are unaffected, the VIP and VIF flags are cleared, and the VM flag is unaffected. The interrupt flag (IF) is altered only when executing at a level at least as privileged as the IOPL. If a POPF/POPFD instruction is executed with insufficient privilege, an exception does not occur but privileged bits do not change. When operating in virtual-8086 mode, the IOPL must be equal to 3 to use POPF/POPFD instructions; VM, RF, IOPL, VIP, and VIF are unaffected. If the IOPL is less than 3, POPF/POPFD causes a general-protection exception (#GP). In 64-bit mode, use REX.W to pop the top of stack to RFLAGS. The mnemonic assigned is POPFQ (note that the 32- bit operand is not encodable). POPFQ pops 64 bits from the stack, loads the lower 32 bits into RFLAGS, and zero extends the upper bits of RFLAGS. See Chapter 3 of the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1, for more information about the EFLAGS registers. ...
0 Kudos
Marián__VooDooMan__M
New Contributor II
2,095 Views

Sergey Kostrov wrote:

Take a look at these two error messages:

>>...
>>C:\1\stacktracing.c(81): (col. 5) error #13252: Unsupported instruction form in asm instruction push.
>>C:\1\stacktracing.c(82): (col. 5) error #13250: Opcode POPFD unsupported by architecture in asm instruction popfd.
>>...

1. These two messages are very confusing and Naveen thinks that these two instructions are not supported on a 64-bit platform. Try to use the test case I've posted with Microsoft 64-bit C++ compiler and you will see similar error messages.

IMO, they are not confusing at all. It clearly states that "popfd" is not supported on amd64/IA-64 architecture running in 64-bit mode, which is indeed truth (see reference manual from Intel or AMD). But there is popfq for this purpose - others said this as well in this forum topic.

Sergey Kostrov wrote:

2. Then, we're trying to understand what is wrong with compilation of Naveen's codes with inline assembler because something else is really wrong. Microsoft's 64-bit C++ compiler doesn't support inline assembles at all (!) for 64-bit platforms.

Yes, MS compiler has not implemented 64-bit inline assembler. I know this fact, though, I am unable to compile the test case right now.

Sergey Kostrov wrote:

Intel 64-bit C++ compiler supports inline assembler for 64-bit platforms and I verified it with version 13. But, Naveen is using version 12 and I don't have any chance to verify it. It is possible that version 12 doesn't support it. So, If you have Intel 64-bit C++ compiler version 12 simply try to compile a test

Sorry, I missed the fact Naveen is using ICC 12. I was thinking about ICC 13, sorry for the noise. I don't have this version at the hand as well. And I will not in near future as well :-( .

Sergey Kostrov wrote:

case I've posted. All the rest things, I mean execution at run-time, is Naveen's assignment.

Of course.

Good luck Naveen. I hope ICC 12 has correctly implemented pushfq/popfq in 64-bit mode without a bug.

Once again, I am sorry for confusion.

0 Kudos
Marián__VooDooMan__M
New Contributor II
2,095 Views

To be more precise, in amd64 instruction set, there are no such instructions as POPFD nor PUSHFD at all.

0 Kudos
Naveen_Tulabandula
2,095 Views

Initially when i posted this...i used popfd......with this i saw compile error

Later i myself changed to popfq, with this compilation is going fine......but

1. eflags value is not getting updated

2. when i am executing segment registers related assembly, i am seeing this error message

(ccc.1464): Illegal instruction - code c000001d (!!! second chance !!!)
stacktracing!PrintStackTrc+0x2e7:
00000001`3fd4132d 668e0dc47c0000  mov     cs,word ptr [stacktracing!ctx+0x38 (00000001`3fd48ff8)] ds:00000001`3fd48ff8=0033

0 Kudos
Marián__VooDooMan__M
New Contributor II
2,095 Views

Naveen Tulabandula wrote:

Initially when i posted this...i used popfd......with this i saw compile error

Later i myself changed to popfq, with this compilation is going fine......but

1. eflags value is not getting updated

2. when i am executing segment registers related assembly, i am seeing this error message

(ccc.1464): Illegal instruction - code c000001d (!!! second chance !!!)
stacktracing!PrintStackTrc+0x2e7:
00000001`3fd4132d 668e0dc47c0000  mov     cs,word ptr [stacktracing!ctx+0x38 (00000001`3fd48ff8)] ds:00000001`3fd48ff8=0033

regarding [1.] are you sure you are restoring the CORRECT value stored before? make your checks in debugger.

[2.] in user mode (i.e. your application is application (ring 3), not kernel driver (ring 0 - supervisor), as far as I know you are not able to modify segment registers. Even more, you need not to restore them at all in this case, since they are always constant for given program instance thru its life, and they are not volatile - even OS will not change it. and *IF* OS wanted change them (but no OS do such hacks), it will use its own mechanisms to do it, via modifying TSS (task state segment).

0 Kudos
Naveen_Tulabandula
1,837 Views

After call to GetThreadContext, i see the value in ctx structure as 0x100202 or something like that....later i manipuated the structure value as 0x64....and executed the above assembly......I expect 0x64 in eflags....but that is not the case.  I am using "r" command in windbg to see the value of eflags and other registers

0 Kudos
Reply