Create an object at a given address

From Rosetta Code
Task
Create an object at a given address
You are encouraged to solve this task according to the task description, using any language you may know.

Basic Data Operation
This is a basic data operation. It represents a fundamental action on a basic data type.

You may see other such operations in the Basic Data Operations category, or:

Integer Operations
Arithmetic | Comparison

Boolean Operations
Bitwise | Logical

String Operations
Concatenation | Interpolation | Comparison | Matching

Memory Operations
Pointers & references | Addresses

In systems programing it is sometimes required to place language objects at specific memory locations, like I/O registers, hardware interrupt vectors etc.

Task

Show how language objects can be allocated at a specific machine addresses.

Since most OSes prohibit access to the physical memory if it is not mapped by the application, as an example, rather than a physical address, take the address of some existing object (using suitable address operations if necessary). For example, create an integer object. Print the machine address of the object. Take the address of the object and create another integer object at this address. Print the value of this object to verify that it is same as one of the origin. Change the value of the origin and verify it again.

6502 Assembly

In 6502 Assembly memory is represented by either an 8-bit or a 16-bit address (i.e. $0000 - $FFFF). 8-bit address are reserved for the memory from $00 to $FF - known as zero page; access to this memory takes one less byte in the opcode and one less cycle to execute.

Data can be stored, one byte at a time, through the store instructions, for example to store data at $1900: <lang 6502asm> sta $1900

       stx $1901
       sty $1902</lang>

Storage can be indexed through the use of the X or Y registers: <lang 6502asm> ldx #54 .loop sta $1900,X

       dex
       bne loop</lang>

It can also be stored via indirect indexed addressing (i.e. memory points to an address), using the Y register: <lang 6502asm> lda #0

       sta $70
       lda #$20
       sta $71
       ldy #0
       sta ($70),Y</lang>

Finally, it can be stored via indexed indirect addressing (i.e. read the address of memory from the table stored at the parameter), using the X register: <lang 6502asm> lda #0

       sta $70
       lda #$20
       sta $71
       ldx #0
       sta ($70,X)</lang>

It should be noted that on the 6502 processor hardware is normally memory mapped, so this is often used for manipulating hardware.

Ada

In Ada object address can be specified using the address representation clause RM 13.3: <lang ada> type IO_Port is mod 2**8; -- One byte Device_Port : type IO_Port; for Device_Port'Address use 16#FFFF_F000#; </lang> In the example above the address is specified constant. It is also possible to specify address dynamically as the following solution of the task does: <lang ada> with Ada.Text_IO; use Ada.Text_IO; with System.Storage_Elements; use System.Storage_Elements;

procedure Test_Address is

  X : Integer := 123;
  Y : Integer;
  for Y'Address use X'Address;

begin

  Put_Line ("At address:" & Integer_Address'Image (To_Integer (Y'Address)));
  Put_Line (Integer'Image (Y));
  X := 456;
  Put_Line (Integer'Image (Y));

end Test_Address; </lang> Sample output:

At address: 38207236
 123
 456

Aikido

Aikido doesn't support getting the address of a variable. However, in the spirit of this task, it does support raw memory access using peek and poke. These can be used on both an integer representing an address (64 bit) or a value obtained from calling malloc. <lang aikido>

var portaddr = 0x80 var v = peek (portaddr, 1) // 1 byte v |= 0x40 poke (portaddr, v, 1) // 1 byte back again

var addr = malloc (16) poke (addr, 1234, 4) poke (addr+4, 0, 2) poke (addr+6, 12, 2)

</lang>

AutoHotkey

In AutoHotkey indeed no language objects can be created at a specified address. But it's very well possible to read and write memory addresses directly. All standard number types are allowed.

<lang AutoHotkey>; Create a variable with 4 bytes size and show it's machine address. VarSetCapacity(var, 4, 0) pAddress := &var MsgBox Machine address: %pAddress%

pAddress contains the memory address.
Write a number and read it back.

NumPut(123456, pAddress+0, 0, "UInt") MsgBox % "Contents of *pAddress: " . NumGet(pAddress+0, 0, "UInt")</lang>

BBC BASIC

<lang bbcbasic> REM Create an integer object:

     anInteger% = 12345678
     PRINT "Original value =", anInteger%
     
     REM Print the machine address of the object:
     address% = ^anInteger%
     PRINT "Hexadecimal address =   ";~address%
     
     REM Take the address of the object and create
     REM another integer object at this address:
     !address% = 87654321
     
     REM Print the value of this object to verify
     REM that it is same as one of the origin:
     PRINT "New value =", anInteger%
     
     REM Change the value and verify it again:
     anInteger% = 55555555
     PRINT "Final value =", !address%

</lang> Output:

Original value =      12345678
Hexadecimal address =   B51955
New value =           87654321
Final value =         55555555

C

<lang c>#include <stdio.h>

int main() {

 int intspace;
 int *address;
 address = &intspace; // address = 0x100;
 *address = 65535;
 printf("%p: %08x (=%08x)\n", address, *address, intspace);
 // likely we must be worried about endianness, e.g.
 *((char*)address) = 0x00;
 *((char*)address+1) = 0x00;
 *((char*)address+2) = 0xff;
 *((char*)address+3) = 0xff; // if sizeof(int) == 4!
 // which maybe is not the best way of writing 32 bit values...
 printf("%p: %08x (=%08x)\n", address, *address, intspace);
 return 0;

}</lang>

0xbfc5675c: 0000ffff (=0000ffff)
0xbfc5675c: ffff0000 (=ffff0000)

A more typical embedded way of doing this is below. Note that the OS will probably not allow this due to memory protections. Embedded systems often do not have memory managers. <lang c>#include <stdint.h>

  1. include <stddef.h>

// This is a port variable located at address 0x100

  1. define PORT_A (*(volatile uint32_t*)0x100)

int main() {

 uint32_t dat;
 size_t addr;
 PORT_A ^= 0x01;   // Toggle bit 0 of PORT_A
 dat = PORT_A;     // Read PORT_A
 addr = &PORT_A;   // addr = 0x100
 return 0;

}</lang>

C++

C++ supports this natively through placement new. This allows construction of complex object types in arbitrary memory locations. <lang Cpp>#include <string>

  1. include <iostream>

int main() {

   // Allocate enough memory to hold an instance of std::string
   char* data = new char[sizeof(std::string)];
   // use placement new to construct a std::string in the memory we allocated previously
   std::string* stringPtr = new (data) std::string("ABCD");
   std::cout << *stringPtr << " 0x" << stringPtr << std::endl;
   // use placement new to construct a new string object in the same memory location
   // remember to manually call destructor
   stringPtr->~basic_string();
   stringPtr = new (data) std::string("123456");
   std::cout << *stringPtr << " 0x" << stringPtr << std::endl;
   // clean up
   stringPtr->~basic_string();
   delete[] data;

}</lang>

Sample output:

ABCD 0x00204040
123456 0x00204040

COBOL

Translation of: PicoLisp
Works with: COBOL version 2002
Works with: OpenCOBOL version 1.1

<lang COBOL> IDENTIFICATION DIVISION.

      PROGRAM-ID. object-address-test.
      DATA DIVISION.
      LOCAL-STORAGE SECTION.
      01 int-space.
         05 val PICTURE 9(5) VALUE 12345.
      01 addr BASED.
         05 val PICTURE 9(5) VALUE ZERO.
      01 point USAGE POINTER.
      PROCEDURE DIVISION.
        DISPLAY val OF int-space END-DISPLAY
        SET point TO ADDRESS OF int-space
        DISPLAY point END-DISPLAY
        SET ADDRESS OF addr TO point
        DISPLAY val OF addr END-DISPLAY
        MOVE 65535 TO val OF addr
        DISPLAY val OF addr END-DISPLAY
        DISPLAY val OF int-space END-DISPLAY
        STOP RUN.
      END PROGRAM object-address-test.

</lang>

Output:

12345
3215227472
12345
65535
65535

D

A better presentation. <lang d>import std.stdio ;

void main() {

   int[] arr ;
   foreach(i; [0,1,2,3])
       arr ~= i*(1 << 24) + 0x417e7e7e ;
   struct X {
       char[16] msg ;
   }
   X* xPtr ;
   int* iPtr ;
   float* fPtr ;
   int adrSpace = cast(int) arr.ptr ;
   // get address of an existing object arr
   xPtr = cast(X*) adrSpace ;
   // xPtr now point to arr, as a struct X
   writefln("arr(as X)'s msg = '%s' (len %d) @ 0x%08x",
       xPtr.msg, xPtr.msg.length, xPtr) ;
   iPtr = cast(int*) (adrSpace + 1 * 4 /*bytes*/) ;
   fPtr = cast(float*) iPtr ;
   // pointers now point to arr[1]
   writefln("arr[1] = 0x%8x (%9.4f) @ 0x%08X", *iPtr, *fPtr, iPtr) ;
   iPtr = cast(int*) (adrSpace + 3 * 4 /*bytes*/) ;
   fPtr = cast(float*) iPtr ;
   // pointers now point to arr[3]
   writefln("arr[3] = 0x%8x (%9.4f) @ 0x%08X", *iPtr, *fPtr, iPtr) ;
   *fPtr = 0.5f ; // change value
   writefln("arr[3] = 0x%8x (%9.4f) @ 0x%08X", *iPtr, *fPtr, iPtr) ;

}</lang> output:

arr(as X)'s msg = '~~~A~~~B~~~C~~~D' (len 16) @ 0x401C2F80
arr[1] = 0x427e7e7e (  63.6235) @ 0x401C2F84
arr[3] = 0x447e7e7e (1017.9764) @ 0x401C2F8C
arr[3] = 0x3f000000 (   0.5000) @ 0x401C2F8C

Forth

As an untyped language, specific machine addresses are very easy to represent in Forth. This is usually most useful for embedded targets. <lang forth> $3f8 constant LPT1:

LPT1: c@ . $3f LPT1: c! </lang> Some architectures may require special fetch and store operators to access ports. For example, Open Firmware defines l@ and l! for safe 32-bit port writes.

FreeBASIC

<lang freebasic>' FB 1.05.0

Type Person

 As String name
 As Integer age
 Declare Constructor(name As String, age As Integer)

End Type

Constructor Person(name As String, age As Integer)

 This.name = name
 This.age = age

End Constructor

Dim ap As Any Ptr = CAllocate(SizeOf(Person)) ' allocate memory to store a Person object

'create a Person object at the address of the memory we've just allocated

Dim p As Person Ptr = New(ap) Person("Teresa", 60)

'check addresses are same Print ap, p

'check data is not corrupt Print p -> name, p -> age

'call implicit destructor p -> Destructor

'free memory Deallocate(ap)

Print Print "Press any key to quit" Sleep</lang>

Output:
4790800       4790800
Teresa         60

Go

Go has several ways to access arbitrary memory locations using the built-in unsafe package. If the desired memory contains an array, since Go doesn't have pointer arithmetic, then a slice should be used instead of a pointer. The following solution demonstrates both a pointer and a slice. <lang go>package main

import( "fmt" "unsafe" "reflect" )

func pointer() { fmt.Printf("Pointer:\n")

// Create a *int and store the address of 'i' in it. To create a pointer to // an arbitrary memory location, use something like the following: // p := (*int)(unsafe.Pointer(uintptr(0x100))) // And replace '0x100' with the desired address. var i int p := &i

fmt.Printf("Before:\n\t%v: %v, %v\n", p, *p, i)

*p = 3

fmt.Printf("After:\n\t%v: %v, %v\n", p, *p, i) }

func slice() { fmt.Printf("Slice:\n")

var a [10]byte

// reflect.SliceHeader is a runtime representation of the internal workings // of a slice. To make it point to a specific address, use something like // the following: // h.Data = uintptr(0x100) // And replace '0x100' with the desired address. var h reflect.SliceHeader h.Data = uintptr(unsafe.Pointer(&a)) // The address of the first element of the underlying array. h.Len = len(a) h.Cap = len(a)

// Create an actual slice from the SliceHeader. s := *(*[]byte)(unsafe.Pointer(&h))

fmt.Printf("Before:\n\ts: %v\n\ta: %v\n", s, a)

// Copy a string into the slice. This fills the underlying array, which in // this case has been manually set to 'a'. copy(s, "A string.")

fmt.Printf("After:\n\ts: %v\n\ta: %v\n", s, a) }

func main() { pointer() fmt.Println()

slice() }</lang> Output:

Pointer:
Before:
        0xf840026018: 0, 0
After:
        0xf840026018: 3, 3

Slice:
Before:
        s: [0 0 0 0 0 0 0 0 0 0]
        a: [0 0 0 0 0 0 0 0 0 0]
After:
        s: [65 32 115 116 114 105 110 103 46 0]
        a: [65 32 115 116 114 105 110 103 46 0]

Julia

Julia has pointer access functions for interface with C code. Because the address of a Julia integer variable within the VM may change when it is re-assigned a new value, an array of a single integer is used below. <lang julia> function unsafepointers()

   intspace = [42]
   address = pointer_from_objref(intspace)
   println("The address of intspace is $address")
   anotherint = unsafe_pointer_to_objref(address)
   println("intspace is $(intspace[1]), memory at $address, reference value $(anotherint[1])")
   intspace[1] = 123456
   println("Now, intspace is $(intspace[1]), memory at $address, reference value $(anotherint[1])")
   anotherint[1] = 7890
   println("Now, intspace is $(intspace[1]), memory at $address, reference value $(anotherint[1])")

end

unsafepointers() </lang>

Output:

The address of intspace is Ptr{Void} @0x0000000007271030 intspace is 42, memory at Ptr{Void} @0x0000000007271030, reference value 42 Now, intspace is 123456, memory at Ptr{Void} @0x0000000007271030, reference value 123456 Now, intspace is 7890, memory at Ptr{Void} @0x0000000007271030, reference value 7890

Kotlin

Works with: Ubuntu version 14.04

<lang scala>// Kotlin/Native Technology Preview

import kotlinx.cinterop.*

fun main(args: Array<String>) {

   val intVar = nativeHeap.alloc<IntVar>().apply { value = 42 }
   with(intVar) { println("Value is $value, address is $rawPtr") }
   intVar.value = 52  // create new value at this address
   with(intVar) { println("Value is $value, address is $rawPtr") }
   nativeHeap.free(intVar)

}</lang>

Output:

Sample output:

Value is 42, address is 26431776
Value is 52, address is 26431776

Pascal

Like in Ada you can assigne different variables at the same adress of an already declared variable. Nice to get the bytes out of an Int64. <lang pascal>program test; type

 t8Byte =  array[0..7] of byte;

var

 I : integer;
 A : integer absolute I;
 K : t8Byte;
 L : Int64 absolute K;

begin

 I := 0;
 A := 255; writeln(I);
 I := 4711;writeln(A);
 For i in t8Byte do
 Begin
   K[i]:=i;
   write(i:3,' ');
 end;
 writeln(#8#32);
 writeln(L);

end.</lang>{OUT}

255
4711
  0  1  2  3  4  5  6  7 
506097522914230528

Phix

Phix does not support creation of a "language object" at a specific address, but you can peek and poke bytes, words, dwords and qwords to any address, as long as doing so does not trigger a hardware exception. You could also use inline assembly, if that helps any. <lang Phix>poke(0x80,or_bits(peek(0x80),0x40))

  1. ilASM{ mov al,[0x80]
       or al,0x40
       mov [0x80],al}</lang>

PicoLisp

<lang PicoLisp>: (setq IntSpace 12345) # Integer -> 12345

(setq Address (adr 'IntSpace)) # Encoded machine address

-> -2969166782547

(set (adr Address) 65535) # Set this address to a new value

-> 65535

IntSpace # Show the new value

-> 65535</lang>

PureBasic

<lang PureBasic>; Allocate a 1Mb memory area work within to avoid conflicts,

this address could be any number but it may then fail on some systems.
  • a=AllocateMemory(1024*1024)
Write a int wit value "31415" at address +312,
using pointer '*a' with a displacement.

PokeI(*a+312, 31415)

Write a float with value Pi at address +316,
by creating a new pointer '*b' for this address
  • b=*a+316

PokeF(*b, #PI)

Now test it

For i=0 To 1024000 Step 4

 n=PeekI(*a+i)
 If n
   Debug "Int at +"+Str(i)+"  = "+Str(n)
   Debug "Float at +"+Str(i)+"= "+StrF(PeekF(*a+i))
 EndIf

Next </lang>

Racket

<lang racket>

  1. lang racket

(require ffi/unsafe)

(define x #"Foo")

Get the address of the `x' object

(printf "The address of `x' is: ~s\n" (cast x _scheme _long)) (define address (cast x _bytes _long)) (printf "The address of the bytestring it holds: ~s\n" address) (define y (cast address _long _bytes)) (printf "Converting this back to a bytestring: ~s\n" y) (bytes-set! y 0 71) (printf "Changed the converted bytestring: ~s\n" y) (printf "The original one is now: ~s\n" x)

But (bytes-set! x 0 71) will throw an error since `x' is immutable,
showing that we've really modifed the memory directly in a way that
the runtime doesn't like.
Also, the above can fail at any moment if a GC happens, since
Racket's GC moves objects. So a proper way to do this is not to
start from an existing object, but allocate one outside of the GC's
reach, using raw malloc()

(define buf (malloc 4 'raw)) (make-sized-byte-string buf 4)

or start with a given address of something like a memory-mapped IO
object

</lang>

Rust

In a real program, most if not all of the contents of main would all be in one `unsafe` block, however in this one each unsafe operation gets its own block to emphasize exactly which actions Rust considers unsafe. <lang rust>use std::{mem,ptr};

fn main() {

   let mut data: i32;
   // Rust does not allow us to use uninitialized memory but the STL provides an `unsafe`
   // function to override this protection.
   unsafe {data = mem::uninitialized()}
   // Construct a raw pointer (perfectly safe)
   let address = &mut data as *mut _;
   unsafe {ptr::write(address, 5)}
   println!("{0:p}: {0}", &data);
   unsafe {ptr::write(address, 6)}
   println!("{0:p}: {0}", &data);

}</lang>

Tcl

As noted in the Address Operations task, it is highly unusual to work with low-level addresses in Tcl. However it is possible to use Tcl's C API (specifically Tcl_LinkVar) to couple Tcl variables to a particular address:

Library: critcl

<lang tcl>package require critcl

  1. A command to 'make an integer object' and couple it to a Tcl variable

critcl::cproc linkvar {Tcl_Interp* interp char* var1} int {

   int *intPtr = (int *) ckalloc(sizeof(int));
   *intPtr = 0;
   Tcl_LinkVar(interp, var1, (void *) intPtr, TCL_LINK_INT);
   return (int) intPtr;

}

  1. A command to couple another Tcl variable to an 'integer object'; UNSAFE!

critcl::cproc linkagain(Tcl_Interp* interp int addr char* var2} void {

   int *intPtr = (int *) addr;
   Tcl_LinkVar(interp, var2, (void *) intPtr, TCL_LINK_INT);

}

  1. Conventionally, programs that use critcl structure in packages
  2. This is used to prevent recompilation, especially on systems like Windows

package provide machAddrDemo 1</lang> Demonstrating: <lang tcl>package require machAddrDemo set addr [linkvar foo] puts "var 'foo' at $addr with value $foo" linkagain $addr bar puts "var 'bar' at $addr with value $bar" incr foo puts "incremented 'foo' so 'bar' is $bar"</lang> Example output (your mileage may vary when it comes to addresses):

var 'foo' at 19363848 with value 0
var 'bar' at 19363848 with value 0
incremented 'foo' so 'bar' is 1