Expand/Shrink

peek

Definition: integer i = peek(atom addr)
-- or --
sequence s = peek({addr, len})
Description: Return a single byte value in the range 0 to 255 from machine address addr in memory, or
return a sequence containing len consecutive byte values starting at address addr.
pwa/p2js: Not supported.
Comments: There are in fact eleven further variations of the peek function:

      peek1s  peek2s  peek4s  peek8s
      peek1u  peek2u  peek4u  peek8u
      peekNS  peekns  peeknu

The first two rows, from left to right retrieve bytes, words, dwords, and qwords, with the first row obtaining signed values and the second unsigned.

The peekNS() function takes three parameters: (addr or {addr,len}), size, and signed.
By way of illustration, peek4u(a)===peekNS(a,4,false).
The peekns() function is a simple hll wrapper of peekNS() that defaults size to machine_word() and signed to true; more convenient but less performant (see Implementation notes below).
The peeknu() function is identical to peekns() except that it defaults signed to false.

The peek routine is actually an alias of peek1u, and when passed a parameter of {addr,len} returns a string, whereas when given the same parameter all the others, including peek1s, return a dword-sequence.

The peek8s/u routines are not intended for use on 32-bit, see technicalia.

The 32-bit values returned by peek4s/u() may be too large for the 32-bit phix integer type (31-bits), so you should use atom variables, likewise for 64-bit values returned by peek8s() on 64-bit phix.

For similar reasons all variables that hold an address should also be declared as atoms.

When passed an atom parameter, peek(1|2)(s|u) (and peek4(s|u) on 64-bit) are however guaranteed to return an integer, should that help any.

Historically the peek({a,i}) form was faster than reading one byte at a time in a loop, however recent optimisations mean that is no longer necessarily (but will more often than not be) true. Specifically, when the overhead of subscripting to extract the individual elements of a sequence result that might otherwise not exist is taken into account, then individual peeks in a loop is likely to be faster. Of course if you are retreiving a string/sequence, and keeping a copy of it anyway, then whether or not you examine the individual characters/elements the peek({a,i}) form will almost certainly be faster.

Remember that peek always takes just one argument, which in the second form is actually a 2-element sequence (except for peekNS, which takes 3 parameters).
Example: The following are equivalent:
-- method 1
s = {peek(addr), peek(addr+1), peek(addr+2), peek(addr+3)}
-- method 2
s = peek({addr, 4})
Implementation: via :%opPeekNx in builtins\VM\pMem.e (an autoinclude) - be warned however it is low-level complicated stuff that you do not need to know.
The peekns and peeknu routines are (trivially) implemented in builtins\peekns.e (an autoinclude). In some future release that mapping may be taken over by the compiler front end (in pmain.e), thereby eliminating any performance overhead, or perhaps directly in VM\pMem.e, if I ever decide that having yet 2 more opcodes is worth it (and some real program arises that could really benefit from it). For the moment, at least, library code or anything that may be invoked millions of times should prefer a longhand peekNS() over peekns()/peeknu(), then again millions of peekNS() suggests you might be somewhat better off with a little #ilASM{}.
See Also: poke, allocate, free, call, machine_bits
Expand/Shrink