Thread overview
How can I point an array to existing data in memory while using Better C?
Jul 08
ag0aep6g
Jul 08
sarn
July 08
https://forum.dlang.org/thread/ddckhvcxlyuvuiyazpqy@forum.dlang.org is similar to what I want to do, but the code by Adam cannot be used when using Better C (I assume slicing isn't supported).

I have the following code:

environment.d

    public __gshared header* GPT_header;
    public __gshared partition_entry[128] GPT_entries;

main.d

    GPT_header = cast(header*)0x00007e00;
    *(GPT_entries).ptr = *(cast(partition_entry*)0x00008000);

Disassembled, the code from main.d looks like this:

mov     ds:_D4boot11environment10GPT_headerPSQBg3gpt6header, 7E00h
mov     esi, 8000h
mov     edi, offset _D4boot11environment11GPT_entriesG128SQBk3gpt15partition_entry
mov     ecx, 20h
rep movsd

So GPT_header points to 0x7e00 as desired, but for GPT_entries it copies the first array element to a different location and makes it point to that location instead of 0x8000.

I should point out that I only have a vague idea of what I'm doing, I tried things until it compiled and worked (at first glance). If there are any docs that properly explain the casting of pointers, I'd appreciate the links.
July 08
On 07/08/2018 10:27 PM, Stijn Herreman wrote:
> https://forum.dlang.org/thread/ddckhvcxlyuvuiyazpqy@forum.dlang.org is similar to what I want to do, but the code by Adam cannot be used when using Better C (I assume slicing isn't supported).

Slicing a pointer works fine for me with -betterC (DMD 2.081.0). Why do you think it doesn't work?

> I have the following code:
> 
> environment.d
> 
>      public __gshared header* GPT_header;
>      public __gshared partition_entry[128] GPT_entries;
> 
> main.d
> 
>      GPT_header = cast(header*)0x00007e00;
>      *(GPT_entries).ptr = *(cast(partition_entry*)0x00008000);
> 
> Disassembled, the code from main.d looks like this:
> 
> mov     ds:_D4boot11environment10GPT_headerPSQBg3gpt6header, 7E00h
> mov     esi, 8000h
> mov     edi, offset _D4boot11environment11GPT_entriesG128SQBk3gpt15partition_entry
> mov     ecx, 20h
> rep movsd
> 
> So GPT_header points to 0x7e00 as desired, but for GPT_entries it copies the first array element to a different location and makes it point to that location instead of 0x8000.

As far as I can tell, the assembler code does exactly what your D code says: Copy one partition_entry (size is apparently 128 bytes?) from 0x8000 to GPT_entries[0].

If you want to set the .ptr of GPT_entries explicitly, I don't know if that's possible. But the code you have is not how you'd do it. You're dereferencing GPT_entries.ptr, you're not setting it.

You can get a partition_entry[] that starts at 0x8000 by casting a pointer and slicing that. Works for me with -betterC:

----
struct partition_entry {}
public __gshared partition_entry[] GPT_entries;
extern(C) void main()
{
    GPT_entries = (cast(partition_entry*) 0x8000)[0 .. 128];
}
----
July 08
On Sunday, 8 July 2018 at 20:27:34 UTC, Stijn Herreman wrote:
> I should point out that I only have a vague idea of what I'm doing, I tried things until it compiled and worked (at first glance). If there are any docs that properly explain the casting of pointers, I'd appreciate the links.

I found the following works as desired:

environment.d

    public __gshared header* GPT_header;
    public __gshared partition_entry* GPT_entries;

main.d

    GPT_header = cast(header*)0x00007e00;
    GPT_entries = cast(partition_entry*)0x00008000;

That still lets me access GPT_entries with an index, e.g. GPT_entries[0]. Is this how it's supposed to be done, or is there a better way still?
July 08
On Sunday, 8 July 2018 at 21:10:50 UTC, ag0aep6g wrote:
> On 07/08/2018 10:27 PM, Stijn Herreman wrote:
>> https://forum.dlang.org/thread/ddckhvcxlyuvuiyazpqy@forum.dlang.org is similar to what I want to do, but the code by Adam cannot be used when using Better C (I assume slicing isn't supported).
>
> Slicing a pointer works fine for me with -betterC (DMD 2.081.0). Why do you think it doesn't work?

Oh it does, thank you for the example. I don't recall the code I had, but the compiler gave an error about TypeInfo (or a similar object) not being supported.


July 08
On Sunday, 8 July 2018 at 20:27:34 UTC, Stijn Herreman wrote:
>     public __gshared partition_entry[128] GPT_entries;

That's a block of memory rather than a pointer, so there's nothing to reassign there; the .ptr property is read-only there (and your reassignment is instead copying TO the address, instead of copying the address).

Instead just use a

partition_entry[] GPT_entries;

and it is a reassignable pointer.
July 08
On Sunday, 8 July 2018 at 21:11:53 UTC, Stijn Herreman wrote:
> On Sunday, 8 July 2018 at 20:27:34 UTC, Stijn Herreman wrote:
>> I should point out that I only have a vague idea of what I'm doing, I tried things until it compiled and worked (at first glance). If there are any docs that properly explain the casting of pointers, I'd appreciate the links.
>
> I found the following works as desired:
>
> environment.d
>
>     public __gshared header* GPT_header;
>     public __gshared partition_entry* GPT_entries;
>
> main.d
>
>     GPT_header = cast(header*)0x00007e00;
>     GPT_entries = cast(partition_entry*)0x00008000;
>
> That still lets me access GPT_entries with an index, e.g. GPT_entries[0]. Is this how it's supposed to be done, or is there a better way still?

You can also easily make slices out of pointers.  E.g.:

// Some backing memory
int[10] x;
// Take a pointer
int *xp = x.ptr;
// Convert pointer to D slice
int[] x2 = xp[0..10];
assert (x2.length == 10);

(Of course, you don't need to break it into steps in real code, and it works fine in betterC.)

There's still not a lot of info out there about doing betterC, but maybe you can find some examples in the following code.  It works without any druntime at all, including TypeInfo.  This is the entry point after a bootloader loads the D code and enters 32b protected mode:
https://gitlab.com/sarneaud/xanthe/blob/master/src/os/drivers-bios.d#L198