Page 1 of 1
64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 7:43 am
by thepowersgang
I'm attempting to create a 64-Bit version of my OS, and due to a problem in my toolchain (I need to find a 64-bit version of gas) I decided to make it in assembler.
Most of it is simple to understand but there is something I don't get, why does this work
Code: Select all
mov QWORD [QWORD _MM_PhysBitmap], rax
but this not
Code: Select all
mov qword [QWORD _MM_PhysSuperBitmap], r8
(this is from my memory manager, _MM_PhysBitmap and _MM_PhysSuperBitmap are both address symbols defined in the same file, but in .data)
The second code segment fails to compile in YASM with the error
Code: Select all
error: invalid combination of opcode and operands
and in nasm it seems to compile as a 32-bit address and LD quits saying
Code: Select all
relocation truncated to fit: R_X86_64_32 against `.data'
Does anyone know why this happens?
Re: 64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 8:37 am
by Zenith
About the toolchain, IIRC then all you need to do is to cross-compile binutils and gcc to the x86_64-elf target...
The problem might be that you're not specifying to assemble to a 64-bit binary. NASM has supported x86-64 instructions since version 0.99, and both assemblers should have a command line option to create an elf64 binary. If you're compiling to a flat executable, then the [BITS 64] directive might also be useful.
Re: 64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 7:11 pm
by thepowersgang
For the toolchain I did cross-compile binutils using the Wiki tutorial but only got LD.
As for telling them to use 64-bits I have. In all my source files I have included [BITS 64] at the beginning of the file.
Re: 64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 7:30 pm
by 01000101
you need to compile all of your 64-bit NASM files with the command line arg "-f elf64", and then link them all together using LD with the args "-m elf_x86_64 --oformat binary" included. This will result in a 64-bit binary.
Re: 64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 9:43 pm
by thepowersgang
What I get is a 64-bit binary, with access to R-registers, but absolute memory accesses don't seem to work to registers other than rax (I think, I know that to/from r8, rsi, and rdi do not work while to/from RAX does)
Using the same linking process I can run and access 64-bit code and data in bochs, just the memory access does not compile properly (And I have been compiling in NASM with -felf64)
Re: 64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 9:47 pm
by JohnnyTheDon
What I get is a 64-bit binary, with access to R-registers, but absolute memory accesses don't seem to work to registers other than rax (I think, I know that to/from r8, rsi, and rdi do not work while to/from RAX does
O.o Thats certaintly weird. You are switching into long mode right? How does your startup code work (your own bootloader, grub, etc.) ?
Re: 64-Bit Assembler Addressing
Posted: Wed Jan 14, 2009 11:34 pm
by thepowersgang
I'm using a 32-bit stub that's loaded by GRUB to 2Mb and that then parses the kernel Elf64 file which is passed as a module by GRUB.
I think the problem is that there might be a restriction on the source/destination registers for qword operations but I can't find any indication of that on the 'net and from my expirence with 16/32-bit operations there shouldn't be any.
Re: 64-Bit Assembler Addressing
Posted: Thu Jan 15, 2009 1:39 am
by 01000101
It kinda sounds like your GDT's bit-width (not the correct term, but it's close) bit is set to 32-bits and not 16-bits (which it needs to be for 64-bit operations).
Does bochs debugger (the log output version) give you some lines like this:
Code: Select all
00031471612i[CPU0 ] CPU is in long mode (halted)
00031471612i[CPU0 ] CS.d_b = 16 bit
00031471612i[CPU0 ] SS.d_b = 16 bit
If either one of those are 32, or if the long mode bit in MSR 0xC0000080 are not set, you are somehow stuck in-between 32-bit PMode and 64-bit LMode. =)
Re: 64-Bit Assembler Addressing
Posted: Thu Jan 15, 2009 4:29 am
by thepowersgang
I don't mean to be rude but I did say in my first post that the problem was at compile/link time. Yasm prints out an error on the memory access. If I take the extra lines of code to load the address into a register and then load the value it works perfectly, but AFIK you should not have to do that.
Re: 64-Bit Assembler Addressing
Posted: Thu Jan 15, 2009 8:25 am
by Brendan
Hi,
thepowersgang wrote:Does anyone know why this happens?
From the page about
AMD64 in YASM's web site:
YASM wrote:
Displacements
Just like immediates, displacements, for the most part, remain 32 bits and are sign extended prior to use. Again, the exception is one restricted form of the mov instruction: between the al/ax/eax/rax register and a 64-bit absolute address (no registers allowed in the effective address). In NASM syntax, use of the 64-bit absolute form requires [qword].
Basically, "
mov qword [QWORD _MM_PhysSuperBitmap], r8" is an instruction the CPU doesn't support, and you'd need to either make sure that the label "_MM_PhysSuperBitmap" is a 32-bit (signed) address, or use RIP relative addressing (where there's a 32-bit signed displacement relative to RIP), or use RAX instead of R8, or do something like:
Code: Select all
mov rbx,_MM_PhysSuperBitmap
mov [rbx], r8
Cheers,
Brendan
Re: 64-Bit Assembler Addressing
Posted: Fri Jan 16, 2009 8:16 pm
by thepowersgang
Does anyone have a list of what instructions are valid to use 64-bit offsets for, because I can't seem to find any?
Re: 64-Bit Assembler Addressing
Posted: Fri Jan 16, 2009 8:55 pm
by Love4Boobies
How about you take a look through the Intel manuals and see for yourself? You don't really exepct us to look through volumes 2A and 2B for you and post each and every instruction here, do you?
Re: 64-Bit Assembler Addressing
Posted: Fri Jan 16, 2009 9:08 pm
by thepowersgang
I thought there might be a list of instructions somewhere that go against what seems to be possible with the structure of the x86-64 (REX prefix denoting extra registers/64-offsets), I'll see if my edition of the Intel manuals has anything on it as I've used every 32-bit GP register in my code and a total rewrite is not what I feel like just now.
Thanks though.
----- STRIKE THAT ------
It seems that the only register that can be used as a destination for Absolute memory addresses is RAX.
(Vol. 2A 3-639 of Intel Manuals)