Create an object at a given address: Difference between revisions

m
m (→‎{{header|8086 Assembly}}: better comment alignment)
m (→‎{{header|Wren}}: Minor tidy)
 
(17 intermediate revisions by 10 users not shown)
Line 23:
 
Data can be stored, one byte at a time, through the store instructions, for example to store data at $1900:
<langsyntaxhighlight lang="6502asm"> sta $1900
stx $1901
sty $1902</langsyntaxhighlight>
 
Storage can be indexed through the use of the X or Y registers:
<langsyntaxhighlight lang="6502asm"> ldx #54
.loop sta $1900,X
dex
bne loop</langsyntaxhighlight>
 
It can also be stored via indirect indexed addressing (i.e. memory points to an address), using the Y register:
<langsyntaxhighlight lang="6502asm"> lda #0
sta $70
lda #$20
sta $71
ldy #0
sta ($70),Y</langsyntaxhighlight>
 
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:
<langsyntaxhighlight lang="6502asm"> lda #0
sta $70
lda #$20
sta $71
ldx #0
sta ($70,X)</langsyntaxhighlight>
 
It should be noted that on the 6502 processor hardware is normally memory mapped, so this is often used for manipulating hardware.
=={{header|68000 Assembly}}==
First, an integer object will be created at address $100000:
<syntaxhighlight lang ="68000devpac">MOVE.L #$12345678,$100000</langsyntaxhighlight>
 
Finding the address of a given object isn't actually possible in the same way it would be on [[C]], since anything loaded from an address is just a numeric copy and is not actually related in any way to the "object." The closest way is to label a memory address and load that label as a numeric constant.
<langsyntaxhighlight lang="68000devpac">myVariable equ $100000
MOVE.L #myVariable,D0
JSR printLong ;some unimplemented printing routine.</langsyntaxhighlight>
 
Creating a new object at that location is as simple as storing a new value there.
<syntaxhighlight lang ="68000devpac">MOVE.L #$FFFFFFFF,myVariable</langsyntaxhighlight>
 
=={{header|8086 Assembly}}==
This example uses UASM to assemble MS-DOS compatible code.
<syntaxhighlight lang="asm">.model small ;specify memory model to use
<lang asm>
.model small ;specify memory model to use
.stack 1024 ;set up stack
 
Line 96 ⟶ 95:
 
;get the address of a variable
mov ax, tempLong_LoWord ;without "word ptr" and brackets, the assembler interprets a label as a constant.</langsyntaxhighlight>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE FIRST="12345"
DEFINE SECOND="54321"
DEFINE PTR="CARD"
 
PROC Main()
PTR base,copy=base
 
PrintF("Address of base variable: %H%E",@base)
PrintF("Address of copy variable: %H%E",@copy)
PutE()
 
PrintF("Assign %U value to base variable%E",FIRST)
base=FIRST
PrintF("Value of base variable: %U%E",base)
PrintF("Value of copy variable: %U%E",copy)
PutE()
 
PrintF("Assign %U value to base variable%E",SECOND)
base=SECOND
PrintF("Value of base variable: %U%E",base)
PrintF("Value of copy variable: %U%E",copy)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Create_an_object_at_a_given_address.png Screenshot from Atari 8-bit computer]
<pre>
Address of base variable: $268C
Address of copy variable: $268C
 
Assign 12345 value to base variable
Value of base variable: 12345
Value of copy variable: 12345
 
Assign 54321 value to base variable
Value of base variable: 54321
Value of copy variable: 54321
</pre>
 
=={{header|Ada}}==
In [[Ada]] object address can be specified using the address representation clause [http://www.adaic.org/standards/05rm/html/RM-13-3.html RM 13.3]:
<langsyntaxhighlight lang="ada">
type IO_Port is mod 2**8; -- One byte
Device_Port : type IO_Port;
for Device_Port'Address use 16#FFFF_F000#;
</syntaxhighlight>
</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:
<langsyntaxhighlight lang="ada">
with Ada.Text_IO; use Ada.Text_IO;
with System.Storage_Elements; use System.Storage_Elements;
Line 120 ⟶ 157:
Put_Line (Integer'Image (Y));
end Test_Address;
</syntaxhighlight>
</lang>
Sample output:
<pre>
Line 130 ⟶ 167:
=={{header|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 <code>peek</code> and <code>poke</code>. These can be used on both an integer representing an address (64 bit) or a value obtained from calling <code>malloc</code>.
<langsyntaxhighlight lang="aikido">
 
var portaddr = 0x80
Line 142 ⟶ 179:
poke (addr+6, 12, 2)
 
</syntaxhighlight>
</lang>
=={{header|Applesoft BASIC}}==
<syntaxhighlight lang="gwbasic"> 0 DEF FN P(A) = PEEK (A) + PEEK (A + 1) * 256
100 :
110 REM CREATE AN INTEGER OBJECT
120 :
130 I$ = CHR$ (42)
140 POKE 236, PEEK (131)
150 POKE 237, PEEK (132)
160 PRINT "HERE IS AN INTEGER : " ASC (I$)
200 :
210 REM PRINT THE MACHINE ADDRESS OF THE OBJECT
220 :
230 PRINT "ITS ADDRESS IS : " FN P( FN P(236) + 1)
300 :
310 REM TAKE THE ADDRESS OF THE OBJECT AND CREATE ANOTHER INTEGER OBJECT AT THIS ADDRESS
320 :
330 O$ = CHR$ (0)
340 POKE 250, PEEK (131)
350 POKE 251, PEEK (132)
360 POKE FN P(250) + 1, PEEK ( FN P(236) + 1)
370 POKE FN P(250) + 2, PEEK ( FN P(236) + 2)
400 :
410 REM PRINT THE VALUE OF THIS OBJECT TO VERIFY THAT IT IS SAME AS ONE OF THE ORIGIN
420 :
430 PRINT "COMPARE OTHER INTEGER : " ASC (O$)
500 :
510 REM CHANGE THE VALUE OF THE ORIGIN AND VERIFY IT AGAIN
520 :
530 POKE FN P( FN P(236) + 1),69
540 PRINT "NEW INTEGER VALUE : " ASC (I$)
550 PRINT "COMPARE OTHER INTEGER : " ASC (O$)</syntaxhighlight>
{{out}}
<pre>
HERE IS AN INTEGER : 42
ITS ADDRESS IS : 38399
COMPARE OTHER INTEGER : 42
NEW INTEGER VALUE : 69
COMPARE OTHER INTEGER : 69
</pre>
=={{header|ARM Assembly}}==
{{trans|68000 Assembly}}
 
First, an integer object will be created at address $100000:
<langsyntaxhighlight ARMlang="arm Assemblyassembly">mov r0,#0x00100000
ldr r1,testData
str r1,[r0] ;store 0x12345678 at address $100000
Line 153 ⟶ 229:
 
testData:
.long 0x12345678 ;VASM uses .long for 32 bit and .word for 16 bit values, unlike most ARM assemblers.</langsyntaxhighlight>
 
Finding the address of a given object isn't actually possible in the same way it would be on [[C]], since anything loaded from an address is just a numeric copy and is not actually related in any way to the "object." The closest way is to label a memory address and load that label as a numeric constant.
<langsyntaxhighlight ARMlang="arm Assemblyassembly">.equ myVariable,0x00100000
mov r0,#myVariable
bl printLong ;unimplemented printing routine</langsyntaxhighlight>
 
Creating a new object at that location is as simple as storing a new value there.
<langsyntaxhighlight ARMlang="arm Assemblyassembly">mov r0,#0x00100000
mov r1,#0
mvn r1,r1 ;flip the bits of r1
str r1,[r0] ;store 0xFFFFFFFF at address $100000
bx lr ;return from subroutine</langsyntaxhighlight>
 
=={{header|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.
 
<langsyntaxhighlight AutoHotkeylang="autohotkey">; Create a variable with 4 bytes size and show it's machine address.
VarSetCapacity(var, 4, 0)
pAddress := &var
Line 178 ⟶ 254:
; Write a number and read it back.
NumPut(123456, pAddress+0, 0, "UInt")
MsgBox % "Contents of *pAddress: " . NumGet(pAddress+0, 0, "UInt")</langsyntaxhighlight>
 
=={{header|BBC BASIC}}==
<langsyntaxhighlight lang="bbcbasic"> REM Create an integer object:
anInteger% = 12345678
PRINT "Original value =", anInteger%
Line 200 ⟶ 276:
anInteger% = 55555555
PRINT "Final value =", !address%
</syntaxhighlight>
</lang>
Output:
<pre>Original value = 12345678
Line 208 ⟶ 284:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
 
int main()
Line 226 ⟶ 302:
printf("%p: %08x (=%08x)\n", address, *address, intspace);
return 0;
}</langsyntaxhighlight>
 
<pre>0xbfc5675c: 0000ffff (=0000ffff)
Line 232 ⟶ 308:
 
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.
<langsyntaxhighlight lang="c">#include <stdint.h>
#include <stddef.h>
 
Line 248 ⟶ 324:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C++}}==
C++ supports this natively through placement new. This allows construction of complex object types in arbitrary memory locations.
<langsyntaxhighlight Cpplang="cpp">#include <string>
#include <iostream>
 
Line 275 ⟶ 351:
stringPtr->~basic_string();
delete[] data;
}</langsyntaxhighlight>
 
Sample output:
Line 284 ⟶ 360:
 
=={{header|COBOL}}==
{{works with|COBOL 2002}}
{{trans|PicoLisp}}
<syntaxhighlight lang="cobolfree">IDENTIFICATION DIVISION.
{{works with|COBOL|2002}}
PROGRAM-ID. object-address-test.
{{works with|OpenCOBOL|1.1}}
<lang COBOL> IDENTIFICATIONDATA DIVISION.
LOCAL-STORAGE SECTION.
PROGRAM-ID. object-address-test.
77 int-space PICTURE IS 9(5) VALUE IS 12345.
DATA DIVISION.
77 addr PICTURE IS 9(5) BASED VALUE IS ZERO.
LOCAL-STORAGE SECTION.
77 point 01 int-space USAGE IS POINTER.
PROCEDURE DIVISION.
05 val PICTURE 9(5) VALUE 12345.
DISPLAY "Value of integer object : " int-space
01 addr BASED.
SET point TO ADDRESS OF int-space
05 val PICTURE 9(5) VALUE ZERO.
DISPLAY "Machine address of object : " point
01 point USAGE POINTER.
SET ADDRESS OF PROCEDUREaddr DIVISION.TO point
DISPLAY "Value of referent object : " addr
DISPLAY val OF int-space END-DISPLAY
MOVE SET point65535 TO ADDRESS OF int-space
DISPLAY "New value of original : " addr
DISPLAY point END-DISPLAY
DISPLAY "New value of reference SET ADDRESS OF addr: TO" pointint-space
GOBACK.
DISPLAY val OF addr END-DISPLAY
END PROGRAM object-address-test.</syntaxhighlight>
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:
<pre>
Value of integer object : 12345
12345
Machine address of object : 0x0000563e11e77fd0
3215227472
Value of referent object : 12345
12345
New value of original : 65535
65535
New value of reference : 65535
65535
</pre>
 
=={{header|Commodore BASIC}}==
The <code>PEEK</code> and <code>POKE</code> commands allow the [[Commodore BASIC]] user to perform limited [[6502 Assembly]] operations.
<langsyntaxhighlight lang="gwbasic">10 POKE 50000,(3) REM EQUIVALENT OF LDA #$03 STA 50000
20 PEEK(50000) REM READ THE VALUE AT MEMORY ADDRESS 50000</langsyntaxhighlight>
 
=={{header|D}}==
 
A better presentation.
<langsyntaxhighlight lang="d">import std.stdio ;
 
void main() {
Line 358 ⟶ 430:
*fPtr = 0.5f ; // change value
writefln("arr[3] = 0x%8x (%9.4f) @ 0x%08X", *iPtr, *fPtr, iPtr) ;
}</langsyntaxhighlight>
output:
<pre>arr(as X)'s msg = '~~~A~~~B~~~C~~~D' (len 16) @ 0x401C2F80
Line 366 ⟶ 438:
</pre>
=={{header|Delphi}}==
<syntaxhighlight lang="delphi">
<lang Delphi>
program Create_an_object_at_a_given_address;
 
Line 394 ⟶ 466:
Readln;
 
end.</langsyntaxhighlight>
{{out}}
<pre>The "origem" adress is: 4261256
Line 409 ⟶ 481:
=={{header|Forth}}==
As an untyped language, specific machine addresses are very easy to represent in Forth. This is usually most useful for embedded targets.
<langsyntaxhighlight lang="forth">
$3f8 constant LPT1:
 
LPT1: c@ .
$3f LPT1: c!
</syntaxhighlight>
</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.
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0
 
Type Person
Line 451 ⟶ 523:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
 
{{out}}
Line 458 ⟶ 530:
Teresa 60
</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
 
local fn DoIt
NSLog( @"Dimension in integer \"x\", but do not assign it a value.\n" )
long x
// Note that the @ (at sign) prefixing x is a pointer to its machine address
NSLog( @"The machine address of x is: %p", @x )
NSLog( @"While x is unassigned, the machine address will contain a garbage value: %ld\n", x )
// Assign x a value of 1234
x = 1234
NSLog( @"When x is assigned a value of %ld, that value will be stored in the machine address: %p", x, @x )
NSLog( @"The machine address now contains the value: %ld\n", x )
// Reassign x a value of 5678
x = 5678
NSLog( @"Wnen x is reassigned the new value %ld, that value will be stored in the existing machine address: %p", x, @x )
NSLog( @"The machine address now contains the value: %ld\n", x )
end fn
 
fn DoIt
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
Dimension in integer "x", but do not assign it a value.
 
The machine address of x is: 0x7ffee279bb58
While x is unassigned, the machine address will contain a garbage value: 1099524915200
 
When x is assigned a value of 1234, that value will be stored in the machine address: 0x7ffee279bb58
The machine address now contains the value: 1234
 
Wnen x is reassigned the new value 5678, that value will be stored in the existing machine address: 0x7ffee279bb58
The machine address now contains the value: 5678
 
</pre>
 
 
=={{header|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.
<langsyntaxhighlight lang="go">package main
 
import(
Line 518 ⟶ 633:
 
slice()
}</langsyntaxhighlight>
Output:
<pre>
Line 535 ⟶ 650:
a: [65 32 115 116 114 105 110 103 46 0]
</pre>
 
=={{header|J}}==
 
For this task, it's probably best to use the [[#C|C]] implementation via a [[j:Guides/DLLs/Calling_DLLs|shared library]] (which requires changing the C function name from <code>main</code> to something else).
 
=={{header|Julia}}==
Line 540 ⟶ 659:
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.
<langsyntaxhighlight lang="julia">
function unsafepointers()
intspace = [42]
Line 554 ⟶ 673:
 
unsafepointers()
</syntaxhighlight>
</lang>
{{output}}<pre>
The address of intspace is Ptr{Void} @0x0000000007271030
Line 564 ⟶ 683:
=={{header|Kotlin}}==
{{Works with|Ubuntu|14.04}}
<langsyntaxhighlight lang="scala">// Kotlin/Native Technology Preview
 
import kotlinx.cinterop.*
Line 574 ⟶ 693:
with(intVar) { println("Value is $value, address is $rawPtr") }
nativeHeap.free(intVar)
}</langsyntaxhighlight>
 
{{out}}
Line 581 ⟶ 700:
Value is 42, address is 26431776
Value is 52, address is 26431776
</pre>
 
=={{header|Lua}}==
Lua has addresses by tables:
<syntaxhighlight lang="lua">local a = {10}
local b = a
 
print ("address a:"..tostring(a), "value a:"..a[1])
print ("address b:"..tostring(b), "value b:"..b[1])
 
b[1] = 42
 
print ("address a:"..tostring(a), "value a:"..a[1])
print ("address b:"..tostring(b), "value b:"..b[1])</syntaxhighlight>
 
{{out}}
Sample output:
<pre>address a:table: 007c8d48 value a:10
address b:table: 007c8d48 value b:10
address a:table: 007c8d48 value a:42
address b:table: 007c8d48 value b:42
</pre>
 
Line 589 ⟶ 729:
 
Memory addresses are nit the physical address, it's from virtual space.
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module CheckIt {
structure alfa {
Line 627 ⟶ 767:
}
Checkit
</syntaxhighlight>
</lang>
 
=={{header|Nim}}==
 
<langsyntaxhighlight lang="nim">type
MyObject = object
x: int
Line 643 ⟶ 783:
objPtr[] = MyObject(x: 42, y: 3.1415)
echo "object at ", cast[int](mem), ": ", objPtr[]
</syntaxhighlight>
</lang>
 
Output:
Line 653 ⟶ 793:
This works for global variables too:
 
<langsyntaxhighlight Nimlang="nim">var x: int = 3
var p: ptr int
 
Line 660 ⟶ 800:
echo "Before ", x
p[] = 5
echo "After: ", x</langsyntaxhighlight>
 
Output:
Line 669 ⟶ 809:
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.
<langsyntaxhighlight lang="pascal">program test;
type
t8Byte = array[0..7] of byte;
Line 689 ⟶ 829:
writeln(#8#32);
writeln(L);
end.</langsyntaxhighlight>{OUT}<pre>255
4711
0 1 2 3 4 5 6 7
Line 696 ⟶ 836:
=={{header|Perl}}==
The is basically a simplified version of the solution to the [https://rosettacode.org/wiki/Address_of_a_variable#Perl Address of a variable] task, so for more detail please consult that entry.
<langsyntaxhighlight lang="perl"># 20210218 Perl programming solution
 
use strict;
Line 715 ⟶ 855:
# print the value of this object to verify that it is same as one of the origin
 
print "Then compare with the referent : ", $target, "\n"; </langsyntaxhighlight>
{{out}}
<pre>
Line 727 ⟶ 867:
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.
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #7060A8;">poke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0x80</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">or_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">peek</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0x80</span><span style="color: #0000FF;">),</span><span style="color: #000000;">0x40</span><span style="color: #0000FF;">))</span>
#ilASM{ mov al,[0x80]
or al,0x40
mov [0x80],al}
<!--</langsyntaxhighlight>-->
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">: (setq IntSpace 12345) # Integer
-> 12345
 
Line 745 ⟶ 885:
 
: IntSpace # Show the new value
-> 65535</langsyntaxhighlight>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="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)
Line 769 ⟶ 909:
EndIf
Next
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
#lang racket
(require ffi/unsafe)
Line 798 ⟶ 938:
;; or start with a given address of something like a memory-mapped IO
;; object
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
Raku has fairly comprehensive facilities for accessing allocating and accessing memory and also declaring C-style structs, via the NativeCall interface, as this example demonstrates.
<syntaxhighlight lang="raku" perl6line>use NativeCall;
use NativeCall::Types;
 
Line 859 ⟶ 999:
free($base-p);
done-testing;
</syntaxhighlight>
</lang>
{{out}}
<pre>creating object at address 94299589110352
Line 871 ⟶ 1,011:
=={{header|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.
<langsyntaxhighlight lang="rust">use std::{mem,ptr};
 
fn main() {
Line 889 ⟶ 1,029:
println!("{0:p}: {0}", &data);
 
}</langsyntaxhighlight>
 
 
=={{header|S-BASIC}}==
S-BASIC fully supports "based" variables that can be positioned at run-time.
<syntaxhighlight lang="basic">
var first, addr = integer
based second = integer
 
first = 12345
location var addr = first
base second at addr
 
print "Value of first variable ="; first
print "Address of first variable = "; hex$(addr)
print "Value of second variable ="; second
 
end
</syntaxhighlight>
{{out}}
<pre>
Value of first variable = 12345
Address of first variable = 0CEE
Value of second variable = 12345
</pre>
 
=={{header|Scala}}==
Line 902 ⟶ 1,066:
 
{{libheader|critcl}}
<langsyntaxhighlight lang="tcl">package require critcl
 
# A command to 'make an integer object' and couple it to a Tcl variable
Line 922 ⟶ 1,086:
# Conventionally, programs that use critcl structure in packages
# This is used to prevent recompilation, especially on systems like Windows
package provide machAddrDemo 1</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">package require machAddrDemo
set addr [linkvar foo]
puts "var 'foo' at $addr with value $foo"
Line 930 ⟶ 1,094:
puts "var 'bar' at $addr with value $bar"
incr foo
puts "incremented 'foo' so 'bar' is $bar"</langsyntaxhighlight>
Example output (your mileage may vary when it comes to addresses):
<pre>var 'foo' at 19363848 with value 0
var 'bar' at 19363848 with value 0
incremented 'foo' so 'bar' is 1</pre>
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
Wren is a high-level scripting language which doesn't support pointers and has no way of obtaining the machine address of variables.
 
This is still true even when Wren is embedded in a program written in a low-level language such as C because the embedding API has been designed so as not to expose raw pointers to memory managed by Wren to the host.
 
Perhaps the closest we can get to the spirit of this task is to create a new ''foreign'' class, ''Integer'', memory for which is allocated from a C host and the machine address is therefore available. We can then use this class to wrap Wren integers (though, strictly speaking, Wren doesn't have integers - they're just a special case of the ''Num'' class), get and set their values and take their address.
 
Note that it is not possible to specify the address at which the embedding API function ''wrenSetSlotNewForeign'' allocates new objects and any attempt to allocate a new object at the same address as an old one by juggling with pointers will almost certainly lead to a seg fault. So all we can sensibly do is to change the value of the current object.
 
<syntaxhighlight lang="wren">/* Create_an_object_at_a_given_address.wren */
 
import "./fmt" for Fmt
 
foreign class Integer {
construct new(i) {}
 
foreign value
 
foreign value=(i)
 
foreign address
}
 
var i = Integer.new(42)
Fmt.print("Integer object with value of: $d allocated at address $#x.", i.value, i.address)
i.value = 42
Fmt.print("Integer object value reset to: $d but still at address $#x.", i.value, i.address)
i.value = 43
Fmt.print("Integer object value changed to: $d but still at address $#x.", i.value, i.address)</syntaxhighlight>
<br>
We now embed this in the following C program, compile and run it.
<syntaxhighlight lang="c">/* gcc Create_an_object_at_a_given_address.c -o Create_an_object_at_a_given_address -lwren -lm */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wren.h"
 
/* C <=> Wren interface functions */
 
void C_integerAllocate(WrenVM* vm) {
long *pi = (long *)wrenSetSlotNewForeign(vm, 0, 0, sizeof(long));
long i = (long)wrenGetSlotDouble(vm, 1);
*pi = i;
}
 
void C_value(WrenVM* vm) {
long i = *(long *)wrenGetSlotForeign(vm, 0);
wrenSetSlotDouble(vm, 0, (double)i);
}
 
void C_setValue(WrenVM* vm) {
long *pi = (long *)wrenGetSlotForeign(vm, 0);
long i = (long)wrenGetSlotDouble(vm, 1);
*pi = i;
}
 
void C_address(WrenVM* vm) {
long *pi = (long *)wrenGetSlotForeign(vm, 0);
wrenSetSlotDouble(vm, 0, (double)(unsigned long long)pi);
}
 
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.allocate = NULL;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Integer") == 0) {
methods.allocate = C_integerAllocate;
}
}
return methods;
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Integer") == 0) {
if (!isStatic && strcmp(signature, "value") == 0) return C_value;
if (!isStatic && strcmp(signature, "value=(_)") == 0) return C_setValue;
if (!isStatic && strcmp(signature, "address") == 0) return C_address;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
if( result.source) free((void*)result.source);
}
 
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
WrenLoadModuleResult result = {0};
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
result.onComplete = loadModuleComplete;
char fullName[strlen(name) + 6];
strcpy(fullName, name);
strcat(fullName, ".wren");
result.source = readFile(fullName);
}
return result;
}
 
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
config.loadModuleFn = &loadModule;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Create_an_object_at_a_given_address.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{out}}
Sample output:
<pre>
Integer object with value of: 42 allocated at address 0x55a56e0f2dd8.
Integer object value reset to: 42 but still at address 0x55a56e0f2dd8.
Integer object value changed to: 43 but still at address 0x55a56e0f2dd8.
</pre>
 
=={{header|Z80 Assembly}}==
When writing assembly yourself, you'll know any object's memory location in advance.
This code creates the 16-bit integer object 0xFFFF at memory address 0xC000:
<syntaxhighlight lang="z80">LD HL,&FFFF
LD (&C000),HL</syntaxhighlight>
 
Loading a value into a register from memory only loads a copy; the original value at that memory location isn't altered, nor is the memory location of that value. Assume this code is executed immediately after the above example:
<syntaxhighlight lang="z80">LD HL,(&C000) ;load &FFFF into HL
INC HL ;HL now equals &0000
LD BC,(&C000) ;load &FFFF into BC.</syntaxhighlight>
 
In order to change a value at a memory location, it either needs to be loaded into a register and stored back after altering that register in some way, or by using certain indirect addressing modes, like so:
<syntaxhighlight lang="z80">LD HL,&C000 ;get the address of our variable.
INC (hl) ;increment the low byte.
LD HL,(&C000) ;load &FF00 into HL.</syntaxhighlight>
 
If you're not familiar with the Z80's syntax, this can be a bit confusing. The brackets are like the dereference operator in C, and not having brackets is like the unary <code>&</code> operator in C. The Z80's ability to do 16-bit operations is limited; it can load from two consecutive memory locations into a 16-bit register pair, however when using <code>(hl)</code> as an operand it is only operating on the lower 8 bits. When learning Z80 Assembly, it is very helpful to view a hex editor while learning the instruction set.
 
{{omit from|AWK}}
9,476

edits