wiki:AccessingMemory

Version 3 (modified by anonymous, 6 years ago) (diff)

--

The canonical operator for accessing memory (as such) is memref:

  defun memref (object offset
                &key (index 0) (type :lisp) localp (endian :host))

The object is any lisp-value whose 32-bit-pattern is taken as the base address, to which the integer offset is added. Finally, the integer index is multiplied with the byte-size of the type, and added to get the final address.

For example, the lisp value 100 (a positive fixnum) is represented by the bit-pattern #x00000400, which means that e.g.

  (memref 100 6 :index 1 :type :unsigned-byte16)

is compiled into something like this pseudo-assembly:

  movw (#x408) <destination>

For a second example, assume you have a cons-cell in the variable 'x'. Cons-cells are pointers to two consecutive words, namely the car and the cdr of the cell, and such pointers are recongnized by their having a low-tag of 1 (i.e. they are offset by 1 relative to the true memory location). Therefore the following operation:

  (memref x -1 :index 0)

will return (car x), while

  (memref x -1 :index 1)

returns (cdr x). To the extent that (typep x 'list) is indeed true, the above operations are exactly equivalent to the car and cdr operations. That is, they are GC safe and generally "well behaved".

A variant of memref is memref-int, which computes the address a bit differently:

  defun memref-int (address
                    &key (offset 0) (index 0) (type :unsigned-byte32)
                         (physicalp t))

Here, the address is provided explicitly as an integer, to which the integer offset and the index multiplied by the type's size is added. memref-int tends to be more appropriate for accessing hardware devices, while memref is more of a primitive for the lisp system as such.

I'll describe the remaining arguments which are (more or less) common to the two operators. The type argument determines how the memory is read and interpreted. To read a value of type :lisp, you have to know very well what you are doing, because otherwise you can easily end up with an illegal lisp value. For hardware programming, you typically want :unsigned-byte32, 16, or 8. Some other types supported but less useful are :character (which is 8-bit and rather ill-specified in terms of character-sets, which is true of Movitz in general), and :location which takes a 32-bit value and strips the lower two bits, leaving a fixnum lisp-value.

The localp argument is to do with some GC-related protocols that are not really finalized. Just leave it at its default is safe.

The endian argument determines the endianess of unsigned-byteXX bytes.

The physicalp argument, finally, is important. Set this to true if the address is to be interpreted as a physical address, as seen on the memory bus and by hardware peripheral devices. Movitz currently sets up the CPU such that the default memory space is shifted one MB or so from the physical address space (using segmentation). This leaves most of the "interesting" hardware memory space unavailable, unless you have :physicalp t (which is the default for memref-int). The [Ford Foundation] is a large body of money completely surrounded by people who want some.

-- Dwight MacDonald?

acquisti cialis italia compra cialis e viagra comprare cialis cialis informazioni cialis e viagra cialis informazioni viagra ordinare viagra in internet fioricet worldwide shipping fioricet side effects buy tramadol cheap online tramadol pharmacy