User Tools

Site Tools


pointers

Pointers

SharpBASIC has a general pointer type ptr. It is general in that it will not bind to a specific type. Hence there is no type checking other than the pointer type itself (optionally enforced by the option strict directive). So pointers can point to any address and it is up to the programmer to take responsibility when using pointers.

read-memory functions

SharpBASIC has built-in functions for reading memory. These functions are:

  • aof() - address of
  • bya() - by address
  • sadd() - string address

In the following example a fixed-length string s with size 19, a pointer p and an unsigned integer n are declared. With the function aof() the descriptor address of string s is assigned to p. In SharpBASIC a string descriptor has the format [addr:size], a double dword in 32-bits. So p + 4 points to the size of the string and is assigned to n with the function bya().

option strict
incl "lib/sys.sbi";

dim s: str * 19;
dim p: ptr;
dim n: uint;

main do
  ' address of descriptor
  p = aof(s);
  ' size by address in second dword field
  n = bya(p + 4);
  ' output: 19
  print(n);
end

We can take the previous example a step further and get the value of each character of the string:

option strict
incl "lib/sys.sbi";

dim is
  s: str * 19 = "SharpBASIC is here!";
  p_desc, p_addr: ptr;
  n: uint;
  i: uitr;
  v: uint8;
end

main do
  ' address of descriptor
  p_desc = aof(s);
  ' string address
  p_addr = bya(p_desc);
  ' string size
  n = bya(p_desc + 4);
  ' print each character's value
  for i = 0 to n - 1 :++ do
     v = bya(p_addr + i);
     print(v);
  end
end

See how the function bya() is used three times and expected to return a different data type each time, including a pointer! In the loop we want the byte value stored at p_addr + i, so we declared v: uint8, which tells bya() that we want the byte value at the specified address.

If we do not need the descriptor address of a variable or fixed-length string, we can use the function sadd() to obtain the address of a string directly. The following example uses sadd() and bya() to convert a hexadecimal string to a decimal number.

option strict;
incl "lib/sys.sbi";

dim hex: str = "7FFF";
dim p: ptr;
dim r: uint = 0;
dim b: uint8;

main do
  p = sadd(hex);
  loop do
    b = bya(p):++;
    when b
      is 97 to 102 do     ' a..f = 10..15
        b:-87;
      is 65 to 70 do      ' A..F = 10..15
        b:-55;
      is 48 to 57 do      ' 0..9
        b:-48;
      is other do
        break;
    end
    r:*16+b;
  end
  print(r);
end

write-memory subroutines

SharpBASIC has built-in subroutines that allow data to be written to memory. These subroutines are:

  • stob() - store byte
  • stow() - store word
  • stod() - store dword
  • stoq() - store qword

The value to be written to memory can be numeric or string. For example, to write the one byte character 'A' (ascii code 65) to memory, both of the following statements are valid:

stob(pointer, "A");
stob(pointer, 65);

The following example converts an integer to its binary string representation. For this, a 64-bytes fixed length string is used. With the function sadd() the string address is assigned to p. Variable n then starts counting from byte 64 backwards so that the bits can be put at the right position in the string with the subroutine stob(). Finally, the string function mid() returns the binary representation starting where variable n left off.

func int2bin(d: int): str
  dim n: uint;
  dim r: str * 64;
  dim p: ptr;
do
  p = sadd(r);
  n = len(r);
  
  if d == 0 do
    n:--;
    stob(p + n, "0");
  end

  loop do
    while d > 0;
    n:--;
    ' d modulo 2 + 48 stores 0 or 1
    stob(p + n, d % 2 + 48);
    d:/2;
  end
  ' mid positions are one based, therefore n + 1
  int2bin = mid(r, n + 1);
end

pointers.txt · Last modified: 2023/06/19 15:27 by admin