1 |
2 |
sinclairrf |
<html>
|
2 |
|
|
<title>
|
3 |
|
|
Strings
|
4 |
|
|
</title>
|
5 |
|
|
<body>
|
6 |
|
|
<h1>Strings</h1>
|
7 |
|
|
There are four ways to express strings:
|
8 |
|
|
<ol>
|
9 |
|
|
<li>A list of characters<br/><br/>
|
10 |
|
|
The expression <tt>"fred"</tt> is the four bytes 'f', 'r', 'e', and
|
11 |
|
|
'd'.<br/><br/>
|
12 |
|
|
If used to initialize and allocate the space for a variable, four bytes will
|
13 |
|
|
be allocated for the variable and the first value will be 'f'.<br/><br/>
|
14 |
|
|
If used in a function, the four bytes will be pushed onto the data stack
|
15 |
|
|
with the 'f' on the top of the data stack.<br/><br/>
|
16 |
|
|
<li>Null-terminated (like C)<br/><br/>
|
17 |
|
|
The expression <tt>N"fred"</tt> is the four bytes 'f', 'r', 'e', 'd', and
|
18 |
|
|
'\0' (the null character).<br/><br/>
|
19 |
|
|
If used to initialize and allocate the space for a variable, five bytes will
|
20 |
|
|
be allocated for the variable and the first value will be 'f'.<br/><br/>
|
21 |
|
|
If used in a function, the five bytes will be pushed onto the data stack
|
22 |
|
|
with the 'f' on the top of the data stack.<br/><br/>
|
23 |
|
|
<li>Counted (like Forth)<br/><br/>
|
24 |
|
|
The expression <tt>C"fred"</tt> is the five bytes 4, 'f', 'r', 'e', and
|
25 |
|
|
'd'.<br/><br/>
|
26 |
|
|
If used to initialize and allocate the space for a variable, five bytes will
|
27 |
|
|
be allocated for the variable and the first value will be 4 and the second
|
28 |
|
|
value will be 'f'.<br/><br/>
|
29 |
|
|
If used in a function, the five bytes will be pushed onto the data stack
|
30 |
|
|
with the the number 4 on the top of the data stack and 'f' in the
|
31 |
|
|
next-to-top of the data stack.<br/><br/>
|
32 |
|
|
<li>Lesser-counted<br/><br/>
|
33 |
|
|
The expression <tt>c"fred"</tt> is the five bytes 3, 'f', 'r', 'e', and
|
34 |
|
|
'd'.<br/><br/>
|
35 |
|
|
If used to initialize and allocate the space for a variable, five bytes will
|
36 |
|
|
be allocated for the variable and the first value will be 3 and the second
|
37 |
|
|
value will be 'f'.<br/><br/>
|
38 |
|
|
If used in a function, the five bytes will be pushed onto the data stack
|
39 |
|
|
with the the number 3 on the top of the data stack and 'f' in the
|
40 |
|
|
next-to-top of the data stack.<br/><br/>
|
41 |
|
|
</ol>
|
42 |
|
|
<h1>Examples</h1>
|
43 |
|
|
<h2>A list of characters</h2>
|
44 |
|
|
If the variable <tt>nibble_to_hex</tt> is set to the length 16
|
45 |
|
|
string <tt>"0123456789ABCDEF"</tt>, then it can be used to convert a
|
46 |
|
|
nibble (with a value between 0 and 15 inclusive) to the corresponding hex
|
47 |
|
|
character.<br/><br/>
|
48 |
|
|
The following is a function that converts a byte to its two-character hex
|
49 |
|
|
representation with the most significant digit on the top of the
|
50 |
|
|
stack.<br/><br/>
|
51 |
|
|
<tt> .memory ROM rom<br/>
|
52 |
|
|
.varaible nibble_to_hex "0123456789ABCDEF"<br/>
|
53 |
|
|
<br/>
|
54 |
|
|
.function convert_byte_to_hex<br/>
|
55 |
|
|
dup 0x0F & .fetchindexed(nibble_to_hex)<br/>
|
56 |
|
|
swap 0>> 0>> 0>> 0>> .fetchindexed(nibble_to_hex)<br/>
|
57 |
|
|
.return</tt><br/>
|
58 |
|
|
<h2>Null-Terminated String</h2>
|
59 |
|
|
The null-terminator in a null-terminated string can be used by a "print"
|
60 |
|
|
function to terminate transmitting the string. For example, if
|
61 |
|
|
<tt>O_UART_Tx</tt> is the output port to a UART (and no status checking is
|
62 |
|
|
performed), the following will send each byte of the message to the
|
63 |
|
|
UART:<br/><br/>
|
64 |
|
|
<tt> N"Hello World!\r\n"<br/>
|
65 |
|
|
:loop .outport(O_UART_Tx) .jumpc(loop,nop) drop</tt><br/><br/>
|
66 |
|
|
Note that this is equivalent to the following:<br/><br/>
|
67 |
|
|
<tt> N"Hello World!\r\n"<br/>
|
68 |
|
|
:loop O_UART_Tx outport drop .jumpc(loop,nop) drop</tt><br/><br/>
|
69 |
|
|
The loop will transmit characters until the next character to transmit is
|
70 |
|
|
the null-terminator, which has the value 0, and for which the conditional
|
71 |
|
|
to the <tt>jumpc</tt> instruction will be false. The "<tt>nop</tt>" is
|
72 |
|
|
required so that the loop does not drop every other byte. The final
|
73 |
|
|
<tt>drop</tt> removes the null-terminator from the data stack.<br/>
|
74 |
|
|
<h2>Counted String</h2>
|
75 |
|
|
Sometimes strings to be transmitted over UARTS have null-characters embedded
|
76 |
|
|
within them. In this case a different method is required to
|
77 |
|
|
determine whether or not the end of the string has been reached. Forth's
|
78 |
|
|
concept of a counted string can be used to resolve this.<br/><br/>
|
79 |
|
|
For example, FLIR's Tau 320 camera has the following as an example sequence
|
80 |
|
|
of bytes to send to the camera, which has several null bytes:<br/><br/>
|
81 |
|
|
<tt> 0x6E 0x00 0x00 0x08 0x00 0x02 0x0F 0x08 0x00 0x01 0x10 0x21</tt><br/><br/>
|
82 |
|
|
This sequence of bytes can be sent to the camera's serial port using the
|
83 |
|
|
following code:<br/><br/>
|
84 |
|
|
<tt> C"\x6E\x00\x00\x08\x00\x02\x0F\x08\x00\x01\x10\x21"<br/>
|
85 |
|
|
:loop swap .outport(O_UART_Tx) 1- .jumpc(loop,nop) drop</tt><br/><br/>
|
86 |
|
|
Note that the count must be decremented before the conditional jump.<br/>
|
87 |
|
|
<h2>Lesser-Counted Strings</h2>
|
88 |
|
|
Since the count for a lesser-counted string is effectively pre-decremented,
|
89 |
|
|
the preceding example can be implemented slightly more efficiently
|
90 |
|
|
as:<br/><br/>
|
91 |
|
|
<tt> c"\x6E\x00\x00\x08\x00\x02\x0F\x08\x00\x01\x10\x21"<br/>
|
92 |
|
|
:loop swap .outport(O_UART_Tx) .jumpc(loop,1-) drop</tt><br/><br/>
|
93 |
|
|
</body>
|
94 |
|
|
</html>
|