Page 1 of 1

64-bit retf with NASM

Posted: Thu Apr 26, 2012 8:38 am
by bluemoon
I noticed that nasm do not generate the REX.w prefix with 64-bit retf

For example, I have this code within BITS 64 section:

Code: Select all

    mov     rdi, gdtr
    lgdt    [rdi]

    mov     ax, SEG_DATA64_0
    mov     ds, ax
    mov     es, ax
    mov     fs, ax
    mov     gs, ax
    mov     ss, ax
    mov     rsp, kstack_end
    push    qword 2
    popf

    mov     rcx, qword .reloadcs
;    jmp     rcx

    push    qword SEG_CODE64_0
    push    rcx
    db 0x48
    retf
As you can see, I need to hand code the prefix. Is it a bug in nasm or do I suppose to manually type the prefix whenever needed? I'm new to all these REX stuff.

Re: 64-bit retf with NASM

Posted: Thu Apr 26, 2012 8:45 am
by bluemoon
Oh I see that NASM manual said "yasm insert REX automatically", but I guess nasm itself do not, or it might not in 2.09.10 which I'm using.

Re: 64-bit retf with NASM

Posted: Thu Apr 26, 2012 9:34 am
by Brendan
Hi,
bluemoon wrote:As you can see, I need to hand code the prefix. Is it a bug in nasm or do I suppose to manually type the prefix whenever needed? I'm new to all these REX stuff.
For normal 64-bit code (where everything is "flat"), there's no reason to use far calls and far returns, except for returning to 16-bit or 32-bit code. For rare cases (like shifting to a different GDT where CS uses a different descriptor number) you'd have to use "a64 retf".


Cheers,

Brendan

Re: 64-bit retf with NASM

Posted: Thu Apr 26, 2012 9:43 am
by bluemoon
a64 has no effect. The output from nasm for "a64 retf" is:

Code: Select all

ffffffff801010af:	6a 20                	pushq  $0x20
ffffffff801010b1:	57                   	push   %rdi
ffffffff801010b2:	cb                   	lret
I still need to manually code that 0x48. But I got your point, retf with operand size=64 is rare case.

Re: 64-bit retf with NASM

Posted: Thu Apr 26, 2012 10:05 am
by Gigasoft
Brendan wrote:For normal 64-bit code (where everything is "flat"), there's no reason to use far calls and far returns, except for returning to 16-bit or 32-bit code.
Or it could be a return to user mode.

Re: 64-bit retf with NASM

Posted: Thu Apr 26, 2012 7:51 pm
by Rudster816
According to the Intel Manual:
In 64-bit mode, the default operation size of this instruction is the stack-address size, i.e. 64 bits.
I'm not 100% sure, but from the sounds of that, it doesn't look like you need a REX prefix.

Re: 64-bit retf with NASM

Posted: Thu Apr 26, 2012 8:26 pm
by gerryg400
Rudster816 wrote:According to the Intel Manual:
In 64-bit mode, the default operation size of this instruction is the stack-address size, i.e. 64 bits.
I'm not 100% sure, but from the sounds of that, it doesn't look like you need a REX prefix.
Yes it's not needed. IRET on the other hand does need REX.

Re: 64-bit retf with NASM

Posted: Fri Apr 27, 2012 6:27 pm
by bluemoon
However, someone also wrote on the wiki: X86-64_Instruction_Encoding
1: The following instructions default to (or are fixed at) 64-bit operands and do not need the REX prefix for this: CALL (near), ENTER, Jcc, JrCXZ, JMP (near), LEAVE, LGDT, LIDT, LLDT, LOOP, LOOPcc, LTR, MOV CR(n), MOV DR(n), POP reg/mem, POP reg, POP FS, POP GS, POPFQ, PUSH imm8, PUSH imm32, PUSH reg/mem,
PUSH reg, PUSH FS, PUSH GS, PUSHFQ and RET (near).
I suppose the RET(near) is implying RETF is not default to 64-bit. Anyway, REX.w = 1 is needed in my case to explicitly set to use 64-bit operands.
btw, yasm does generate REX for this automatically. berkus is right, I should switch to yasm.

Re: 64-bit retf with NASM

Posted: Fri Apr 27, 2012 6:48 pm
by gerryg400
bluemoon wrote:I suppose the RET(near) is implying RETF is not default to 64-bit. Anyway, REX.w = 1 is needed in my case to explicitly set to use 64-bit operands.
btw, yasm does generate REX for this automatically. berkus is right, I should switch to yasm.
A few years ago someone on the list (I think it was Owen) tested some machines and found that FAR CALL in 64bit mode only works on Intel machines. It does not work on AMD machines. The Intel docs imply that it works while the AMD docs say that it doesn't work. So the docs are reasonably 'correct'.

There is a good chance that the same applies to FAR RET.

I think care is needed here and you may find that you code does not work on all machines. To be sure you really should use the documented method which is to use an IRET.

Re: 64-bit retf with NASM

Posted: Fri Apr 27, 2012 7:08 pm
by bluemoon
OK Thanks for the advice.

EDIT: I got the iret worked. The sad news is that nasm 2.09 does not emit REX for iret as well (and yasm does emit REX, for the same code).
EDIT2: IRETQ does the tricks. Time for me to re-read the assembler manual for 64-bit stuff.

Re: 64-bit retf with NASM

Posted: Fri Apr 27, 2012 7:22 pm
by gerryg400
Bluemoon, I found the thread. Actually it seems that Owen did try FAR RET and it worked. I would still be cautious though. IRET is the documented method and will always work.

http://forum.osdev.org/viewtopic.php?f= ... 51&start=0