Long jump in 64-bits: instruction not supported

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
chris13524
Member
Member
Posts: 45
Joined: Sat Feb 27, 2016 10:52 pm

Long jump in 64-bits: instruction not supported

Post by chris13524 »

I'm trying to setup my GDT table, however, when I try to assemble it, I get this error:

Code: Select all

src/kernel/gdtasm.s:28: error: instruction not supported in 64-bit mode
Here is my asm code for that section:

Code: Select all

[GLOBAL gdt_flush]
gdt_flush:
   mov eax, [esp+4]
   lgdt [eax]

   mov ax, 0x10
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
   mov ss, ax
   jmp 0x08:.flush ; this is line 28
.flush:
   ret
I am using nasm, and running it with this flag: '-f elf64'. I do not have any BITS 64 flags at the top of my asm file. UEFI is landing me in 64-bit mode, I am trying to change the GDT.
Last edited by chris13524 on Thu Aug 25, 2016 7:36 am, edited 1 time in total.
My operating system:
https://github.com/neonorb/aura
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: Long jump in 64-bits: instruction not supported

Post by Ycep »

Which emulator? QEMU?
chris13524
Member
Member
Posts: 45
Joined: Sat Feb 27, 2016 10:52 pm

Re: Long jump in 64-bits: instruction not supported

Post by chris13524 »

Lukand wrote:Which emulator? QEMU?
Yes, I am using QEMU, but I don't see how this is related.
My operating system:
https://github.com/neonorb/aura
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Long jump in 64-bits: instruction not supported

Post by Octacone »

64 bit mode requires 64 bit instructions. Also put "BITS 64" at the top of your 64 bit section.
For example:

Code: Select all

EAX -> RAX
EBX -> RBX
Etc...
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Long jump in 64-bits: instruction not supported

Post by jnc100 »

There is no jmp ptr16:64 instruction, and jmp ptr16:32 is not supported in 64 bit mode.

You probably want to do a far return, e.g.:

Code: Select all

push 0x08
push .flush
retf
Regards,
John.
chris13524
Member
Member
Posts: 45
Joined: Sat Feb 27, 2016 10:52 pm

Re: Long jump in 64-bits: instruction not supported

Post by chris13524 »

jnc100 wrote:There is no jmp ptr16:64 instruction, and jmp ptr16:32 is not supported in 64 bit mode.

You probably want to do a far return, e.g.:

Code: Select all

push 0x08
push .flush
retf
Regards,
John.
My understanding is I need to set the CS register with 0x8, I'm not sure that this does that.
My operating system:
https://github.com/neonorb/aura
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: Long jump in 64-bits: instruction not supported

Post by Ycep »

octacone wrote:64 bit mode requires 64 bit instructions. Also put "BITS 64" at the top of your 64 bit section.
For example:

Code: Select all

EAX -> RAX
EBX -> RBX
Etc...
Hmmm... this is not correct, since 64 bit archiceture supports RAX, EAX and AX, RBX, EBX and BX, RCX, ECX, CX, ...
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Long jump in 64-bits: instruction not supported

Post by Octacone »

chris13524 wrote:
jnc100 wrote:There is no jmp ptr16:64 instruction, and jmp ptr16:32 is not supported in 64 bit mode.

You probably want to do a far return, e.g.:

Code: Select all

push 0x08
push .flush
retf
Regards,
John.
My understanding is I need to set the CS register with 0x8, I'm not sure that this does that.
That is just a blank far jump. You basically jump to a specific far address and return from it.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
chris13524
Member
Member
Posts: 45
Joined: Sat Feb 27, 2016 10:52 pm

Re: Long jump in 64-bits: instruction not supported

Post by chris13524 »

When I replace:

Code: Select all

   jmp 0x08:.flush ; this is line 28
.flush:
   ret
with:

Code: Select all

   push 0x08
   push .flush
   retf
It can't find the .flush symbol:

Code: Select all

src/kernel/gdtasm.s:32: error: symbol `gdt_flush.flush' undefined
I understand why this is happening, but I don't know what you expected me to do. Where should I put the flush symbol?
My operating system:
https://github.com/neonorb/aura
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Long jump in 64-bits: instruction not supported

Post by jnc100 »

Keep it wherever it was before. Replace the jmp 0x08:.flush with these three lines and keep the .flush and ret afterwards.

Regards,
John.
chris13524
Member
Member
Posts: 45
Joined: Sat Feb 27, 2016 10:52 pm

Re: Long jump in 64-bits: instruction not supported

Post by chris13524 »

jnc100 wrote:Keep it wherever it was before. Replace the jmp 0x08:.flush with these three lines and keep the .flush and ret afterwards.

Regards,
John.
I did this, but now it won't link:

Code: Select all

ld: build/kernel/gdtasm.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
I'm assuming this is because I'm pushing a label, so that would be it's absolute address, rather than a relative one. I tried adding the 'DEFAULT REL' modifier (before and after 'BITS 64'), but it didn't help.

I'm building a shared object so UEFI can run it.
My operating system:
https://github.com/neonorb/aura
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Long jump in 64-bits: instruction not supported

Post by iansjack »

The question is, why are you wanting to do such a jump?

64-bit long mode uses a flat address space, so the only real point of changing the CS register is to change to privilege level. A far jump would not be the appropriate way to do this; normally you would do so via a syscall instruction or an interrupt. The sysret, or iret, instruction would then change the privilege level back again - manipulating these instructions can be done to put the processor into user mode initially; after that you shouldn't need to manipulate CS.
chris13524
Member
Member
Posts: 45
Joined: Sat Feb 27, 2016 10:52 pm

Re: Long jump in 64-bits: instruction not supported

Post by chris13524 »

iansjack wrote:The question is, why are you wanting to do such a jump?

64-bit long mode uses a flat address space, so the only real point of changing the CS register is to change to privilege level. A far jump would not be the appropriate way to do this; normally you would do so via a syscall instruction or an interrupt. The sysret, or iret, instruction would then change the privilege level back again - manipulating these instructions can be done to put the processor into user mode initially; after that you shouldn't need to manipulate CS.
I posted here: http://forum.osdev.org/viewtopic.php?f= ... 27#p264327. They told me to setup a GDT. I am now trying to port my previous GDT code from 32 to 64-bits.
My operating system:
https://github.com/neonorb/aura
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Long jump in 64-bits: instruction not supported

Post by iansjack »

I'd say that the reason that you were given there "to make sure you actually have access to all of the memory space" is invalid (in 64-bit mode). It is certainly true that you will want to create a valid IDT (I've no idea what UEFI sets up) and you may need to modify the GDT that UEFI has provided. But IMO you shouldn't need to do the sort of far jump that you propose.
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Long jump in 64-bits: instruction not supported

Post by Octocontrabass »

chris13524 wrote:I'm assuming this is because I'm pushing a label, so that would be it's absolute address, rather than a relative one. I tried adding the 'DEFAULT REL' modifier (before and after 'BITS 64'), but it didn't help.
That's because "push .flush" isn't calculating an effective address, it only pushes a fixed value. You need to use an instruction that calculates an effective address, for example:

Code: Select all

    lea rax, [rel .flush]
    push 0x08
    push rax
    retf
.flush:
iansjack wrote:It is certainly true that you will want to create a valid IDT (I've no idea what UEFI sets up) and you may need to modify the GDT that UEFI has provided. But IMO you shouldn't need to do the sort of far jump that you propose.
It's necessary to ensure that CS has a reasonable value so interrupts can return properly. Otherwise, the CS pushed to the stack when an interrupt occurs may not refer to a valid code selector.
Post Reply