Direct Memorry Accessing?

BlitzMax Forums/BlitzMax Programming/Direct Memorry Accessing?

Damien Sturdy(Posted 2005) [#1]
Can i directly access memory in Max? if so, How? if not, why not?

I know this breaks compatibility, but its something ive missed in a programming language for ages and itd be lovely not to have to install a 3rd party dll etc.......


skidracer(Posted 2005) [#2]
On which OS? And Why?

Under Windows Google hardware driver development (DDK) for an insight into exactly what you're up against.


ImaginaryHuman(Posted 2005) [#3]
At the moment it's not too easy since Mark has designed it out, for the most part. ie you're supposed to use the `preferred method` of doing it so that it is legal. On modern systems for example the os may not allow you access memory areas that you haven't pre-allocated and so on.

If you take a look at the Poke and Peek commands, you'll notice you can only poke and peek with a bank, and you have to specify the bank handle with every call.

However, you can work on addresses. For example, you can use VarPtr to get the address of a variable. You can then wrap that variable's memory space in a static bank (ie 4 bytes) and then you can Poke and Peek to the memory space of the variable.

You can also get the pointer to bank memory or the pointer to incbin'd file memory. But I am thinking that to modify the incbin file's memory you have to again wrap it in a static bank and access it via the bank with poke and peek.

The theory goes something like this - if you are behaving yourself and poking around in memory that you're meant to be able to access, you should be using the standard tools such as the static bank, poke, peek, etc. If you're not accessing memory that you own and have allocated properly, then why are you poking around in it?

I know it is useful, but alas BlitzMax more or less disallows you from doing it. This is Mark's effort to ensure that people adopt a certain programming practice, I guess, mostly for their own good.

You might want to look at using [0] on the end of a pointer, such as memaddress[0], because that then write to or reads from the content of the memory held at that pointer. You see, although we programmers interpret teh BlitzMax language in a certain way, if you think about it, there isn't much different between saying myarray[4] and myintpointer[4]. You can just strap on an index ie [0] and access the memory. Note however that if you use a byte pointer, it accesses individual bytes. Int pointers access groups of 4 bytes.

There's nothing to stop you modifying the pointer or using a different index such as memaddress[16]. You just need to get a pointer from somewhere. If the debugger complains that you're not allowed to do what you're doing, you could try compiling with debug off? So long as you know what you're up to.

For example to change the content of a function pointer I found you could convert the function pointer into a byte pointer, convert the byte pointer into an int pointer, and then use intpointer[0] to access the memory of that function pointer. This way you can directly read and write different values to the function pointer that wouldn't normally be allowed due to type restrictions. Usually you can't make a function pointer equate to anything other than another function pointer, so using this way (or with a static bank) you can access the memory of the function pointer and write to it directly.

I haven't really experimented all that much with putting [0] on the end of pointers, I guess you should be able to access any memory anywhere using that. It's kind of like the old assembler addressing mode called `indirect addressing`, where you get the content of the memory held at the address stored in a register (ie a variable points to the memory and then you read/write that memory).

And ... it should work on all OS's, but you may have problems with the o/s itself noticing that you're fumbling around in memory you don't `officially own` and might shut you out or think that your software is a crashed program running amuck. If you want to directly access memory you've allocated, you should be okay.


col(Posted 2005) [#4]
I think it would be very bad to actually directly access some area of memory because most modern operating systems allocate and de-allocate memory dynamically. What would happen if you were to overwrite some critical area of memory that controlled your hard drive just as its writing data?? serious crash me thinks.

If on the other hand, you let the operating system allocate some memory to you and you want to access that given area directly then you can use the 'Banks' suite of cammands and also some 'stream' commands. This would be a lot safer.


ImaginaryHuman(Posted 2005) [#5]
In the good old days, mostly in the pre-internet era, it was perfectly normal for a person to access whatever memory they like. Take a look at Amiga and Atari computers for example. There is/was no official `memory protection`. And yes there were crashes and programs did, usually accidentally, access the wrong memory and end up overwriting stuff it shouldn't. This *could* lead to interfering with harddrive content and causing other crashes.

With the continued progress of `modern` operating systems, they decided hey, we keep getting this happen so lets make it so that each program thinks they own the whole system but actually they don't, they live in a confined box and only access the memory they've asked for. The hardware then sets up page faults and stuff like that which throw up (literally?) exceptions and such to indicate that some program tried to access memory it doesn't have the right to access. *SUPPOSEDLY* this is a cure for bad programs. However, in my book it is covering up a bigger issue of bad programming languages that don't produce safe code.

But even beyond that, I think there is also some merit to any program having the freedom to access any part of the system it wants to, to take over the whole thing if it likes. I don't see anything wrong with that, it's very commonplace on the Amiga for example. Memory protection is a half-measure, an attempt to compensate for poor programming and faulty languages and is also an attempt to make a system be a multi-program system even though there is really only one system there. Some people like it, some don't.

There are risks involved but if you know what you are doing there's no reason why the world shouldn't be your oyster or why you shouldn't be able to do whatever you like with your computer. Funny how people get locked out of their own computers these days.

I would recommend using static banks if you want to fiddle around in memory, unless you really need it to be fast in which case use [0] or even eachin might work.


col(Posted 2005) [#6]
@AngieldDaniel
Wise words. I remember the Amiga, I has a 1200. Really flash machine for its time. I ended up with an '040 processor in there and 32meg of RAM!!! and an 8! Gig hard drive. That was considered quite excessive back then!

I have played around with the memory pointers and de-referecing the pointers with [0]. I created a type that was a copy of a file header structure ( contained only int's and byte's, no other types or arrays ) and also created an array of bytes. I loaded the file into the array and used 'memcopy' to copy the file header information straight into the 'Type'. Worked rather well and was only about 5 lines of code, instead of reading each bit of data and transfering that data into the type fields.
This technique doesn't work if you have arrays or other 'Types' within your 'Type'.


Dreamora(Posted 2005) [#7]
Would be a useless idea

WinXP SP2 would block the app if it tries to access stuff outside its scope, making sure that 90% of the users won't be able to reactive it again.


Damien Sturdy(Posted 2005) [#8]

Under Windows Google hardware driver development (DDK) for an insight into exactly what you're up against.



I know what i'm up against ;)

@Col;

If i was going to cock up like that then i deserve what happens ;) (dont play with what you dont understand).
Direct Memory Access does not mean the memory windows alocates (if thats what you mean by dynamic :/) i mean the actual, physical address...
Say i wanted to directly access a parralel port; I could do this in QBasic in win95/98. Qbasic is old and wont run since 2000 very well.

Of course, its not recomended, but id find it useful. I assume the majority of you disagree and therefore Mark is right not to do it.

I have been thinking though, and its only real use would be for my want to play with home made devices, so wrapping a DLL to blitz commands may be the best way.

[edit]
I mainly want to access main system hardware, not windows hardware (as they tend to have drivers to access them correctly) A small idea would be to directly access the SPeaker (&H60 i think, cant remember off the top of my head the exact address). Hopefully blitzmax would be quick enough for me to be able to make it actually say something (which would be funny as a prank when i make my puter talk to its user... this puter has no speakers). I also have a lighting system ive built that i used to put into the BBC and made a "Binary-Logo" language to run it in. I would access it via the Printer port as i did on the bbc.

basically, its for fun. It looks like i will be needing to get some dll working in blitz :/

Unless theres a way to use the printer ports in max now? not just for printing? ;)
--
[edit2]
@Angel

Unfortunately, and this is where my problem is, Windows HAL hides hardware from you. Even if you manage to access that area of memory, its not the "true" address

Thanks for your views...


ImaginaryHuman(Posted 2005) [#9]
Um .. resort to c or assembler and write your own o/s? lol


ImaginaryHuman(Posted 2005) [#10]
What I would've liked would be to have Poke and Peek commands which, like in the original Basic, can poke or peek at any address rather than supplying a bank number each and every time. Or maybe in some combination with EachIn so the bank base address doesn't have to be looked up every time either. But of course, to make it easier to check that you're accessing something valid you need to know what kind of memory area you're poking around in, hense the banks.


ImaginaryHuman(Posted 2005) [#11]
Ahhhhhh, the good old days, poking around with hardware interrupts and AGA hardware registers. :-)


Damien Sturdy(Posted 2005) [#12]
Ive done the OS writing before too :P


What I would've liked would be to have Poke and Peek commands which, like in the original Basic, can poke or peek at any address rather than supplying a bank number each and every time



Yes. Those are the commands i was asking fore basically.


I wonder if that OS that was written in QBasic is still around. It was ace!


Michael Reitzenstein(Posted 2005) [#13]
Well then;

Global Memory:Byte Ptr = Byte Ptr( 0 )


Not that it'll do you much good!


marksibly(Posted 2005) [#14]
Function PokeByte( addr,value )
(Byte Ptr addr)[0]=value
End Function

Function PeekByte( addr,value )
Return (Byte Ptr addr)[0]
End Function

...etc with Int Ptr and so on...

However, you're better just sticking with pointers and [] if you want to do lots of mem access, eg:

Local p:Byte Ptr=MemAlloc( 1024 )
p[0]=0 'same as Poke p,0
p[1]=1 'same as Poke p,1 etc...don't poke beyond 1023 though!

If you need to cast the pointer:

(Int Ptr p)[0]=0 'pokes p[0..3]
(Int Ptr p)[1]=1 'pokes p[4...7]

And if you need to poke an int into a non-4 byte aligned offset:

(Int Ptr (p+offset))[0]=0


Damien Sturdy(Posted 2005) [#15]
neat, Il try something with that later, But for me to say, make a ptr of &H330 and poke/peek to [0]; Thats likely to cause a protection fault, isnt it?

Well, It shouldnt be too difficult for me to port NTport or something to MAX

Thanks for your Input