Strings

There are four ways to express strings:
  1. A list of characters

    The expression "fred" is the four bytes 'f', 'r', 'e', and 'd'.

    If used to initialize and allocate the space for a variable, four bytes will be allocated for the variable and the first value will be 'f'.

    If used in a function, the four bytes will be pushed onto the data stack with the 'f' on the top of the data stack.

  2. Null-terminated (like C)

    The expression N"fred" is the four bytes 'f', 'r', 'e', 'd', and '\0' (the null character).

    If used to initialize and allocate the space for a variable, five bytes will be allocated for the variable and the first value will be 'f'.

    If used in a function, the five bytes will be pushed onto the data stack with the 'f' on the top of the data stack.

  3. Counted (like Forth)

    The expression C"fred" is the five bytes 4, 'f', 'r', 'e', and 'd'.

    If used to initialize and allocate the space for a variable, five bytes will be allocated for the variable and the first value will be 4 and the second value will be 'f'.

    If used in a function, the five bytes will be pushed onto the data stack with the the number 4 on the top of the data stack and 'f' in the next-to-top of the data stack.

  4. Lesser-counted

    The expression c"fred" is the five bytes 3, 'f', 'r', 'e', and 'd'.

    If used to initialize and allocate the space for a variable, five bytes will be allocated for the variable and the first value will be 3 and the second value will be 'f'.

    If used in a function, the five bytes will be pushed onto the data stack with the the number 3 on the top of the data stack and 'f' in the next-to-top of the data stack.

Examples

A list of characters

If the variable nibble_to_hex is set to the length 16 string "0123456789ABCDEF", then it can be used to convert a nibble (with a value between 0 and 15 inclusive) to the corresponding hex character.

The following is a function that converts a byte to its two-character hex representation with the most significant digit on the top of the stack.

  .memory ROM rom
  .varaible nibble_to_hex "0123456789ABCDEF"

  .function convert_byte_to_hex
    dup 0x0F & .fetchindexed(nibble_to_hex)
    swap 0>> 0>> 0>> 0>> .fetchindexed(nibble_to_hex)
  .return

Null-Terminated String

The null-terminator in a null-terminated string can be used by a "print" function to terminate transmitting the string. For example, if O_UART_Tx is the output port to a UART (and no status checking is performed), the following will send each byte of the message to the UART:

  N"Hello World!\r\n"
  :loop .outport(O_UART_Tx) .jumpc(loop,nop) drop


Note that this is equivalent to the following:

  N"Hello World!\r\n"
  :loop O_UART_Tx outport drop .jumpc(loop,nop) drop


The loop will transmit characters until the next character to transmit is the null-terminator, which has the value 0, and for which the conditional to the jumpc instruction will be false. The "nop" is required so that the loop does not drop every other byte. The final drop removes the null-terminator from the data stack.

Counted String

Sometimes strings to be transmitted over UARTS have null-characters embedded within them. In this case a different method is required to determine whether or not the end of the string has been reached. Forth's concept of a counted string can be used to resolve this.

For example, FLIR's Tau 320 camera has the following as an example sequence of bytes to send to the camera, which has several null bytes:

  0x6E 0x00 0x00 0x08 0x00 0x02 0x0F 0x08 0x00 0x01 0x10 0x21

This sequence of bytes can be sent to the camera's serial port using the following code:

  C"\x6E\x00\x00\x08\x00\x02\x0F\x08\x00\x01\x10\x21"
  :loop swap .outport(O_UART_Tx) 1- .jumpc(loop,nop) drop


Note that the count must be decremented before the conditional jump.

Lesser-Counted Strings

Since the count for a lesser-counted string is effectively pre-decremented, the preceding example can be implemented slightly more efficiently as:

  c"\x6E\x00\x00\x08\x00\x02\x0F\x08\x00\x01\x10\x21"
  :loop swap .outport(O_UART_Tx) .jumpc(loop,1-) drop