64bit variable in x86 mode, possible? [SOLVED]

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.
Post Reply
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

64bit variable in x86 mode, possible? [SOLVED]

Post by ashishkumar4 »

Ibam Making a x86 OS with an x86 gcc compiler. Was developing my own FileSystem (no name given to it, its not fat or anything like that). Now the problem is, until now (before I stumbled on FS), I only required uint32_t provided by GCC. But now (as you might guess) the problem is, I am required to work with secondary storage media (SATA for now) which are generally more then 4GB. That means I require 64 bit addressing. Now there are several possible alternatives (thought of many) for this but I would like to use something like uint64_t just for simplicity sake. Now GCC 32bit provides a working uint64_t but as the compiler I compiled was 32 bits, even still I cant manage numbers more then 4*1024*1024*1024 :/ and that's the trouble. I have some alternatives for this like using 2 uint32_t vars(array) or using uint64_t itself by bit shifting (it still takes 8bytes space on RAM, checked it). But in either case, things like dividing the number by say size of sectors (512) would become a bit complicated and given my FileSystem is already so complicated, would only slow the performance if I don't do things the right way. further it would be an invitations for several bugs and flaws by even a single mistake; It would simply be too cumbersome. Now as a lazy person, I need a way to use 64 bit variables in GCC 32 bit compiler, manipulating as a unit. If I had one, I can just use it to address some location on the hard disk say above 4GB, and then get the data at that location by using my already working AHCI SATA drivers (with the read write functions provided by the wiki, just more abstracted away; I would just need to pass lower 32bits to appropriate places in the command table and higher bits to respective places)

Please help me, you see that now I am lazy + dumb :3

NOTE: I have completed my FileSystem (mostly, just the permissions things remain though already supported). But as you see, It only works with <4GB drives. Help
Last edited by ashishkumar4 on Thu Mar 24, 2016 10:47 pm, edited 1 time in total.
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: 64bit variable in x86 mode, possible?

Post by Octocontrabass »

Even 32-bit GCC is capable of generating functional code with 64-bit variables, using uint64_t and int64_t. If it's not working properly, it means you're doing something wrong, such as performing arithmetic between two 32-bit values and storing the result (which is truncated to 32-bits) into a 64-bit variable.
azblue
Member
Member
Posts: 147
Joined: Sat Feb 27, 2010 8:55 pm

Re: 64bit variable in x86 mode, possible?

Post by azblue »

Like Octo said, the compiler can handle it. For example, if you did x = y + z (all 64 bit ints), the compiler might do something like:

Code: Select all

mov eax, [y.lower32]
mov ebx, [y.upper32]
add eax, [z.lower32]
adc ebx, [z.upper32]
mov [x.lower32], eax
mov [x.upper32], ebx
For division things get more complicated, just as you said, but you don't have to worry about it; the compiler will figure it all out.
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

Re: 64bit variable in x86 mode, possible?

Post by ashishkumar4 »

:/ ok sorry, I got it. It worked earlier too but the problem was my printf wont print it. But now I am having this problem: Though I can get the upper 32bits and lower 32bits easily (and print them too for testing); I still can just divide them by say 512 and get the lower 32bits and put them somewhere and the upper 32bits and put them somewhere; like:

uint64_t abc=0xffffffffffff; //random number :P
printf("\n%x %x",(abc>>32),(abc & 0xffffffff); //This works, prints equivalent decimal for 0xffff and 0xffffffff
uint32_t a=(uint32_t)abc/1000000000;
printint(a);

This gives error on linking that "__udivdi3" :/ help me
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: 64bit variable in x86 mode, possible?

Post by alexfru »

ashishkumar4 wrote: This gives error on linking that "__udivdi3" :/ help me
http://llvm.org/svn/llvm-project/compil ... /udivdi3.c
or
https://sourceware.org/git/?p=glibc.git ... .c;hb=HEAD
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: 64bit variable in x86 mode, possible?

Post by Octocontrabass »

That error means you aren't linking libgcc (which contains __udivdi3) against your code. It can also be an indication of other problems, such as not using a cross-compiler.
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: 64bit variable in x86 mode, possible?

Post by kzinti »

This has nothing to do with having a cross compiler or not. You will get that even with a cross compiler if you don't link with standard libraries, which is implied with "-ffreestanding".

You need to explictly link with libgcc in this case, as it contains 64 bits integer arithmetic functions such as __udivdi3.

Now just using -lgcc probably won't work with "-ffreestanding" as the system library search path won't be set. What I do is find where libgcc is (using gcc!) and then add the full path to the linker. From my makefile:

Code: Select all

libgcc_path := $(shell $(CC) -print-file-name=libgcc.a)

kernel.elf: $(OBJECTS)
	$(LD) $(LDFLAGS) $(OBJECTS) $(libgcc_path) -o $@
Where CC is gcc and LD is ld.
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

Re: 64bit variable in x86 mode, possible?

Post by onlyonemac »

I used a uint64_t with 32-bit gcc and no libgcc (on the other hand, I explicitly told it not to use libgcc). This is my compiler command line:

Code: Select all

gcc -ffreestanding -fno-builtin -nostdlib -nostdinc -m32 -Wl,-Bstatic -Wall -c kernel/main.c -o kernel/main.o
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: 64bit variable in x86 mode, possible?

Post by Octocontrabass »

If gcc doesn't emit any references to libgcc, you won't have any errors from not linking libgcc. However, gcc can emit those references whenever it wants, so it's better to do things right from the beginning. You'll just end up fighting with it otherwise.

Same goes for not using a cross compiler.
ashishkumar4
Member
Member
Posts: 73
Joined: Wed Dec 23, 2015 10:42 pm

Re: 64bit variable in x86 mode, possible?

Post by ashishkumar4 »

Ah thanks everyone, Everything is now working as I wanted, the filesystem now supports 64bit addressing (probably, the true test would be conducted when the FS is completed in as what I call "The Stage 3 of FS dev" ). The only thing I did to make everything fit was to just use arithmatics on 64bit vars with 64bit vars and storing them in 64bit vars only. Means,

instead of
uint32_t abc=bc/512; //where bc is uint64_t var with possible value >4*1024*1024*1024

I just always do
uint64_t abc=bc/512; //It works well, no bugs till now
and just pass this 'abc' which in this case I would use as addressing for sectors to my read or write-to-sata drive functions which are just diferent versions of my general 'sata commander' function which itself does the task to separate the 64 bit value to upper 32 and lower 32 bits.
Thanks everyone :)

EDIT: I still don't have 100% confidence on this as I haven't tested writing more then 4GB data on any hard disk
The best method for accelerating a computer is the one that boosts it by 9.8 m/s2.
My OS : https://github.com/AshishKumar4/Aqeous
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: 64bit variable in x86 mode, possible?

Post by jnc100 »

kiznit wrote:This has nothing to do with having a cross compiler or not. You will get that even with a cross compiler if you don't link with standard libraries, which is implied with "-ffreestanding".
Not quite. libgcc is not included if you either 1) use ld to link (instead of driving it through gcc) or 2) use gcc to link but pass the -nostdlib or -nodefaultlibs options to it. -ffreestanding is a compiler option (i.e. only affecting the translation of source code to object code, rather than the link itself) that tells gcc to make certain defines and not others, and only support a few default headers (see e.g. C Library).

The recommended way to compile and link is something like:

Code: Select all

; Compile
i686-elf-gcc -ffreestanding -mno-mmx (insert other -mno-cpu-features here) -c -o main.o main.c

; Link
i686-elf-gcc -nostdlib -T linker.ld -o kernel.elf main.o -lgcc
which should accomplish what you want without having to resort to such Makefile trickery.
onlyonemac wrote:I used a uint64_t with 32-bit gcc and no libgcc
Whilst this may have worked in your particular use case, the moment you start using functionality that cannot easily be expressed in simple machine operations, gcc will start to emit calls to libgcc and your build may break at any time (even with the same code and different compiler versions). To quote libgcc: All code compiled with gcc must be linked with libgcc.

Specifically for 64-bit integer support on 32-bit platforms, gcc is quite clever and will avoid libgcc calls if at all possible. Examples where it is not called include addition and subtraction (add/adc and sub/sbb are used instead), single-bit shifts (using shifts via CF) and simple power-of-two multiplications and divides (where shifts are used). It is when you start doing more complex stuff that libgcc gets used. On other platforms that don't support any form of interger divide (even word size) such as certain ARM platforms, libgcc is even more heavily relied upon.

Regards,
John.
Post Reply