The result: the destination can get a string that is too long, and contains a part of the 'old' contents of the string.
The problem is only visible if the previous string in was "longer" than the one where the error occurs.
Example code:
Code: Select all
program StringConcat;
{ Declarations section }
var text: string[50];
Str1: string[15];
Siz : word;
const ConstString = 'ghi';
begin
{ Main program }
// --------------------------------------------------------
// usage of constant string at the end of the concatenation
// --------------------------------------------------------
Str1 := 'abcdef';
text := Str1 + ConstString; // text = 'abcdefghi' OK
Siz := strlen(text); // strlen = 9 (as expected)
Str1 := 'abc';
text := Str1 + ConstString; // text = 'abcghighi' <--ERROR (expected = 'abcghi')
Siz := strlen(text); // expected strlen = 6; actual = 9 <--ERROR
// literal string
Str1 := 'abc';
text := Str1 + 'ghi'; // text = 'abcghi' OK
Siz := strlen(text); // expected and actual strlen = 6;
// ------------------------------------------------------------
// usage of constant string not at the end of the concatenation
// ------------------------------------------------------------
Str1 := 'abcdef';
text := ConstString + Str1; // text = 'ghiabcdef' OK
Siz := strlen(text); // strlen = 9 (as expected)
Str1 := 'abc';
text := ConstString + Str1; // text = 'ghiabc' OK
Siz := strlen(text); // strlen = 6 (as expected)
// literal string
Str1 := 'abc';
text := 'ghi' + Str1; // text = 'ghiabc' OK
Siz := strlen(text); // expected and actual strlen = 6;
end.
Code: Select all
CLRF POSTINC1
Code: Select all
RCALL ___CCS2S
1. Concatenation of 2 variable strings (terminating zero OK)
Code: Select all
;StringConcat.mpas,14 :: text := Str1 + Str1;
0x0068 0x0E27 MOVLW _text
0x006A 0x6EE1 MOVWF FSR1L
0x006C 0x0E00 MOVLW hi_addr(_text)
0x006E 0x6EE2 MOVWF FSR1H
0x0070 0x0E17 MOVLW _Str1
0x0072 0x6ED9 MOVWF FSR2L
0x0074 0x0E00 MOVLW hi_addr(_Str1)
0x0076 0x6EDA MOVWF FSR2H
0x0078 0xDFF1 RCALL ___CS2S
0x007A 0x0E17 MOVLW _Str1
0x007C 0x6ED9 MOVWF FSR2L
0x007E 0x0E00 MOVLW hi_addr(_Str1)
0x0080 0x6EDA MOVWF FSR2H
0x0082 0xDFEC RCALL ___CS2S
0x0084 0x6AE6 CLRF POSTINC1; <--- the terminating zero
Code: Select all
;StringConcat.mpas,16 :: text := ConstString + Str1;
0x0074 0x0E27 MOVLW _text
0x0076 0x6EE1 MOVWF FSR1L
0x0078 0x0E00 MOVLW hi_addr(_text)
0x007A 0x6EE2 MOVWF FSR1H
0x007C 0x0E34 MOVLW _ConstString
0x007E 0x6EF6 MOVWF TBLPTR
0x0080 0x0E02 MOVLW hi_addr(_ConstString)
0x0082 0x6EF7 MOVWF TBLPTRH
0x0084 0x0E00 MOVLW higher_addr(_ConstString)
0x0086 0x6EF8 MOVWF TBLPTRU
0x0088 0xDFC9 RCALL ___CCS2S
0x008A 0x0E17 MOVLW _Str1
0x008C 0x6ED9 MOVWF FSR2L
0x008E 0x0E00 MOVLW hi_addr(_Str1)
0x0090 0x6EDA MOVWF FSR2H
0x0092 0xDFDC RCALL ___CS2S
0x0094 0x6AE6 CLRF POSTINC1; <--- the terminating zero
Code: Select all
;StringConcat.mpas,20 :: text := Str1 + ConstString; // text = 'abcdefghi' OK
0x00A0 0x0E27 MOVLW _text
0x00A2 0x6EE1 MOVWF FSR1L
0x00A4 0x0E00 MOVLW hi_addr(_text)
0x00A6 0x6EE2 MOVWF FSR1H
0x00A8 0x0E17 MOVLW _Str1
0x00AA 0x6ED9 MOVWF FSR2L
0x00AC 0x0E00 MOVLW hi_addr(_Str1)
0x00AE 0x6EDA MOVWF FSR2H
0x00B0 0xDFD5 RCALL ___CS2S
0x00B2 0x0E24 MOVLW _ConstString
0x00B4 0x6EF6 MOVWF TBLPTR
0x00B6 0x0E02 MOVLW hi_addr(_ConstString)
0x00B8 0x6EF7 MOVWF TBLPTRH
0x00BA 0x0E00 MOVLW higher_addr(_ConstString)
0x00BC 0x6EF8 MOVWF TBLPTRU
0x00BE 0xDFAE RCALL ___CCS2S
; <--- no terminating zero: missing "CLRF POSTINC1"