* *Copyright (C) 2005 Krapinskij (krapinskij@yahoo.it) * *This program is free software; you can redistribute it and/or *modify it under the terms of the GNU General Public License *as published by the Free Software Foundation; either version 2 *of the License, or (at your option) any later version. * *This program is distributed in the hope that it will be useful, *but WITHOUT ANY WARRANTY; without even the implied warranty of *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *GNU General Public License for more details. * *You should have received a copy of the GNU General Public License *along with this program; if not, write to the Free Software *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA REPORT z_decrypt. TYPES t_code(72) TYPE c. TYPES: t_acode(72) TYPE c. TYPES: t_x34(72) TYPE x. PARAMETERS: k(16) TYPE c. FIELD-SYMBOLS: TYPE x. DATA gt_xcode TYPE TABLE OF t_x34 . DATA gt_code TYPE TABLE OF t_code . ASSIGN k TO CASTING. *Load test code/test data from compressed binary PERFORM merger USING gt_xcode. *uncompress/re-make readable PERFORM load_code_u USING gt_xcode CHANGING gt_code. DATA name TYPE syrepid. DATA: msg(120), lin(3), wrd(10), off(3). *Create test routine with test data. GENERATE SUBROUTINE POOL gt_code NAME name MESSAGE msg LINE lin WORD wrd OFFSET off. IF sy-subrc NE 0. EXIT. ENDIF. *Run test code. PERFORM system_test IN PROGRAM (name) IF FOUND. WRITE:/. *---------------------------------------------------------------------* * FORM merger * *---------------------------------------------------------------------* FORM merger USING pt_xcode. DATA lt_data TYPE TABLE OF string. DATA l_xstr TYPE xstring. DATA l_xtmp TYPE xstring. DATA lt_xcode TYPE TABLE OF xstring. DEFINE a. l_xtmp = &1. concatenate l_xstr l_xtmp into l_xstr." in byte mode. END-OF-DEFINITION. a: 'F5B23D561331BFF8F460B81185E4C5A5E69A1BF62F3192CD9C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '76A9407F1B2ED13FF3AB455E83CA257D079A67359CC78A2BAC17B32AAB3CFB4A3B80', '24C8A61FC51872986DF97EE87C43B80E7CE06381E3EFC17C09715E6B87EE9C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '2E4965130AD218706AC8A2B80BA8A825B572D3CB6E68479C49917E846C7E85136DC9', 'CCFADF4287B2236FC24A76347BDF9C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '8B6D9FE689BC8AA58A66CAAADB68DC3BCE6937D92C7015C19C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: 'E127BFF2747CF65EEBBB1EDE54364A1945B6EF5F7C1790F2E0F0DE828CA581F79C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '1875542AA1CCD03543257A7C563833132DA0EEFB0590F3D1DCC4BF741F5BA58A8920', '6CFAE26452B49C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: 'CD533D2DBD425E611DB7226DDB1B4E7BEBA1470C4B1069DC8CB142CA5BA8A6C79C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '18B08BB36EE460494ABBA333287745829C47CA452A9B03049C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B0304A3DC990D4D96167B1ADD3DA9D5C5DEB095FCA8E5937468757D00', '3F94E5675C939C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B0304841421154CF731ACA65F6895393A09E19C47CA452A9B0304A8B5', 'A4EDB7F52CF69C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B0304175183B43B1725730E6B2AFD71917FC19C47CA452A9B03040C73', '59F4EC0F41FF9C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: 'E381B06057564131DBFDD775683353859C47CA452A9B03049C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B030412C2274932C5385B4AC7D5F809A029B19C47CA452A9B0304AA26', 'C5AC8EB61E6E58B0675F26DCAE7F9C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '18B08BB36EE460491F68E1D4ADE9C27313E6B66050476CF99C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B03045133012B2EE657B6000D52F72E94B3069C47CA452A9B03040753', 'CE661F88F4E39C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '9C47CA452A9B030404D0673C9B4FE8AB749909FA04E5473A9C47CA452A9B0304FB6E', '65ECEFEEDED29C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '598A78C6F165447588DA3014C4FDE813C3208A1AF4781F17897F6346E7C23626D198', 'B6FA44E4DD0B99B29F0372CCFEAB7E4472E2F2FC2A2842544F4A834215F0CE6937D9', '2C7015C1', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '41F85B93CFCF84998DCF49668F9AFBDCC667EE6500B4E55F6955E68A2EF144C459A8', '117DCE1E1F299C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: '598A78C6F165447588DA3014C4FDE813C3208A1AF4781F17897F6346E7C23626D198', 'B6FA44E4DD0BE7FB1F3974A0AE874937F9B2B00975C3E1BABC8148A950B69C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. a: 'AEF15BC29492EF089C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47', 'CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA452A9B03049C47CA45', '2A9B0304', ''. APPEND l_xstr TO lt_xcode. CLEAR l_xstr. pt_xcode = lt_xcode. ENDFORM. ********************************************************************* TYPES: t_tab_string TYPE TABLE OF t_acode. TYPES: t_tab_xstring TYPE TABLE OF t_x34. TYPES t_tab_acode TYPE TABLE OF t_acode. *&--------------------------------------------------------------------* *& Form load_code_u *&--------------------------------------------------------------------* FORM load_code_u USING pt_xstrings TYPE t_tab_xstring k TYPE x CHANGING pt_strings TYPE t_tab_string. DATA l_str TYPE t_code. DATA l_ox TYPE t_code. DATA l_ix TYPE t_x34. LOOP AT pt_xstrings INTO l_ix. CLEAR l_ox. CLEAR l_str. * PERFORM tea_cipher_u USING l_ix k 'D' CHANGING l_ox. PERFORM tea_cipher USING l_ix k 'D' CHANGING l_ox. * IMPORT xdata = l_str FROM DATA BUFFER l_ox. l_str = l_ox. APPEND l_str TO pt_strings. ENDLOOP. ENDFORM. "load_code_u TYPES: t_x2(2) TYPE x. TYPES: t_x4(4) TYPE x. TYPES: t_x8(8) TYPE x. TYPES: t_x16(16) TYPE x. *&--------------------------------------------------------------------* *& Form tea_cipher_U *&--------------------------------------------------------------------* * unicode and platform independent. * Release >4.7 only (maybe 4.6C...) * * Note: Relies on the fact that import from data buffer * does not care of eventual extra x00 at the end of the xstring. *---------------------------------------------------------------------* FORM tea_cipher_u USING input TYPE xstring k mode CHANGING output TYPE xstring. DATA offset TYPE i. DATA len TYPE i. DATA l_ix TYPE t_x8. DATA l_ox TYPE t_x8. DATA delta TYPE i. len = strlen( input ). WHILE offset < len. delta = len - offset. IF delta > 8. delta = 8. ENDIF. IF mode = 'E'. l_ix = input+offset(delta). PERFORM tea_tea USING l_ix k CHANGING l_ox. CONCATENATE output l_ox INTO output." IN BYTE MODE. ELSEIF mode = 'D'. l_ix = input+offset(delta). PERFORM tea_untea USING l_ix k CHANGING l_ox. CONCATENATE output l_ox INTO output. "IN BYTE MODE. ENDIF. offset = offset + 8. ENDWHILE. ENDFORM. "tea_cipher_U **&--------------------------------------------------------------------* **& Form tea_cipher **&--------------------------------------------------------------------* ** not unicode/platform independent ** Restrictions: input must be long n*8 and output too. ** Guaranteed to work only on char types. No int no unicode. **---------------------------------------------------------------------* FORM tea_cipher USING input k mode CHANGING output. FIELD-SYMBOLS: TYPE x. FIELD-SYMBOLS: TYPE x. DATA offset TYPE i. DATA len TYPE i. ASSIGN input TO CASTING. DESCRIBE FIELD LENGTH len." IN BYTE MODE. WHILE offset < len. ASSIGN input+offset(8) TO CASTING. ASSIGN output+offset(8) TO CASTING. IF NOT IS ASSIGNED OR NOT IS ASSIGNED. EXIT. ENDIF. IF mode = 'E'. PERFORM tea_tea USING k CHANGING . ELSEIF mode = 'D'. PERFORM tea_untea USING k CHANGING . ENDIF. offset = offset + 8. ENDWHILE. ENDFORM. "tea_cipher *&--------------------------------------------------------------------* *& Form tea_tea *&--------------------------------------------------------------------* FORM tea_tea USING input k CHANGING output. FIELD-SYMBOLS: TYPE t_x8. FIELD-SYMBOLS: TYPE t_x8. FIELD-SYMBOLS: TYPE t_x16. ASSIGN input TO CASTING. ASSIGN output TO CASTING. ASSIGN k TO CASTING. ************************************************************************ * C is a little bit more... compact. :-) * register unsigned long y=v[0],z=v[1],sum=0,delta=0x9E3779B9,n=32; * * while(n-->0) * { * y += (z << 4 ^ z >> 5) + z ^ sum + k[sum&3]; * sum += delta; * z += (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3]; * } * * w[0]=y; w[1]=z; *********************************************************************** CONSTANTS x00000003 TYPE t_x4 VALUE '00000003'. CONSTANTS delta TYPE t_x4 VALUE '9E3779B9'. DATA y TYPE t_x4. DATA z TYPE t_x4. DATA sum TYPE t_x4 VALUE '00000000'. DATA n TYPE i VALUE 32. DATA ysl4 TYPE t_x4. DATA ysr5 TYPE t_x4. DATA zsl4 TYPE t_x4. DATA zsr5 TYPE t_x4. DATA sumand3 TYPE t_x4. DATA sumsr11 TYPE t_x4. DATA sumt TYPE t_x4. DATA sum3 TYPE t_x4. DATA ztmp TYPE t_x4. DATA ytmp TYPE t_x4. DATA y1 TYPE t_x4. DATA y2 TYPE t_x4. DATA y3 TYPE t_x4. DATA z1 TYPE t_x4. DATA z2 TYPE t_x4. DATA z3 TYPE t_x4. DATA ksum TYPE t_x4. y = +0(4). z = +4(4). WHILE n > 0. n = n - 1. ******************************************************** */*y += (((z << 4) ^ (z >> 5)) + z) ^ (sum + k[sum&3])*/ *(z << 4) -> zsl4 PERFORM tea_shift_left USING z 4 CHANGING zsl4. *(z >> 5) -> zsr5 PERFORM tea_shift_right USING z 5 CHANGING zsr5. *((z << 4) ^ (z >> 5)) -> ztmp ztmp = ( zsl4 BIT-XOR zsr5 ). *(((z << 4) ^ (z >> 5)) + z) -> y1 PERFORM tea_unsigned_sum USING ztmp z CHANGING y1. *sum&3 sumt = sum BIT-AND x00000003. * sumt = sumt * 4. * k[sum&3] -> ksum ksum = +sumt(4). *sum + k[sum&3] -> y2 PERFORM tea_unsigned_sum USING ksum sum CHANGING y2. * y2 = y2 BIT-XOR y1. *y = y + y2 PERFORM tea_unsigned_sum USING y2 y CHANGING y3. y = y3. ******************************************************* * sum += delta; PERFORM tea_unsigned_sum USING sum delta CHANGING sum3. sum = sum3. ******************************************************* * z += (((y << 4) ^ (y >> 5)) + y) ^ (sum + k[sum>>11 & 3]); *(y << 4) -> ysl4 PERFORM tea_shift_left USING y 4 CHANGING ysl4. *(y >> 5) -> ysr5 PERFORM tea_shift_right USING y 5 CHANGING ysr5. *((y << 4) ^ (y >> 5)) -> ytmp ytmp = ( ysl4 BIT-XOR ysr5 ). *(((y << 4) ^ (y >> 5)) + y) -> z1 PERFORM tea_unsigned_sum USING ytmp y CHANGING z1. *sum>>11 PERFORM tea_shift_right USING sum 11 CHANGING sumt. *sumt&3 sumt = sumt BIT-AND x00000003. * sumt = sumt * 4. * k[sum&3] -> ksum ksum = +sumt(4). *sum + k[sum&3] -> z2 PERFORM tea_unsigned_sum USING ksum sum CHANGING z2. * z2 = z2 BIT-XOR z1. *z = z + z2 PERFORM tea_unsigned_sum USING z2 z CHANGING z3. z = z3. ENDWHILE. +0(4) = y. +4(4) = z. ENDFORM. "tea_tea *&--------------------------------------------------------------------* *& Form tea_untea *&--------------------------------------------------------------------* FORM tea_untea USING input k CHANGING output. FIELD-SYMBOLS: TYPE t_x8. FIELD-SYMBOLS: TYPE t_x8. FIELD-SYMBOLS: TYPE t_x16. ASSIGN input TO CASTING. ASSIGN output TO CASTING. ASSIGN k TO CASTING. ************************************************************************ * register unsigned long y=v[0],z=v[1],sum=0xC6EF3720, * delta=0x9E3779B9,n=32; * * /* sum = delta<<5, in general sum = delta * n */ * * while(n-->0) * { * z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3]; * sum -= delta; * y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum&3]; * } * * w[0]=y; w[1]=z; *********************************************************************** CONSTANTS x00000003 TYPE t_x4 VALUE '00000003'. CONSTANTS delta TYPE t_x4 VALUE '9E3779B9'. DATA y TYPE t_x4. DATA z TYPE t_x4. DATA sum TYPE t_x4 VALUE 'C6EF3720'. DATA n TYPE i VALUE 32. DATA ysl4 TYPE t_x4. DATA ysr5 TYPE t_x4. DATA zsl4 TYPE t_x4. DATA zsr5 TYPE t_x4. DATA sumand3 TYPE t_x4. DATA sumsr11 TYPE t_x4. DATA sumt TYPE t_x4. DATA sum3 TYPE t_x4. DATA ztmp TYPE t_x4. DATA ytmp TYPE t_x4. DATA y1 TYPE t_x4. DATA y2 TYPE t_x4. DATA y3 TYPE t_x4. DATA z1 TYPE t_x4. DATA z2 TYPE t_x4. DATA z3 TYPE t_x4. DATA ksum TYPE t_x4. y = +0(4). z = +4(4). WHILE n > 0. n = n - 1. ******************************************************* * z -= (((y << 4) ^ (y >> 5)) + y) ^ (sum + k[sum>>11 & 3]); *(y << 4) -> ysl4 PERFORM tea_shift_left USING y 4 CHANGING ysl4. *(y >> 5) -> ysr5 PERFORM tea_shift_right USING y 5 CHANGING ysr5. *((y << 4) ^ (y >> 5)) -> ytmp ytmp = ( ysl4 BIT-XOR ysr5 ). *(((y << 4) ^ (y >> 5)) + y) -> z1 PERFORM tea_unsigned_sum USING ytmp y CHANGING z1. *sum>>11 PERFORM tea_shift_right USING sum 11 CHANGING sumt. *sumt&3 sumt = sumt BIT-AND x00000003. * sumt = sumt * 4. * k[sum&3] -> ksum ksum = +sumt(4). *sum + k[sum&3] -> z2 PERFORM tea_unsigned_sum USING ksum sum CHANGING z2. * z2 = z2 BIT-XOR z1. *z = z - z2 PERFORM tea_unsigned_sub USING z z2 CHANGING z3. z = z3. ******************************************************* * sum -= delta; PERFORM tea_unsigned_sub USING sum delta CHANGING sum3. sum = sum3. ******************************************************** */*y -= (((z << 4) ^ (z >> 5)) + z) ^ (sum + k[sum&3])*/ *(z << 4) -> zsl4 PERFORM tea_shift_left USING z 4 CHANGING zsl4. *(z >> 5) -> zsr5 PERFORM tea_shift_right USING z 5 CHANGING zsr5. *((z << 4) ^ (z >> 5)) -> ztmp ztmp = ( zsl4 BIT-XOR zsr5 ). *(((z << 4) ^ (z >> 5)) + z) -> y1 PERFORM tea_unsigned_sum USING ztmp z CHANGING y1. *sum&3 sumt = sum BIT-AND x00000003. * sumt = sumt * 4. * k[sum&3] -> ksum ksum = +sumt(4). *sum + k[sum&3] -> y2 PERFORM tea_unsigned_sum USING ksum sum CHANGING y2. * y2 = y2 BIT-XOR y1. *y = y - y2 PERFORM tea_unsigned_sub USING y y2 CHANGING y3. y = y3. ENDWHILE. +0(4) = y. +4(4) = z. ENDFORM. "untea *&--------------------------------------------------------------------* *& Form tea_shift_right *&--------------------------------------------------------------------* FORM tea_shift_right USING i TYPE t_x4 n TYPE i CHANGING o TYPE t_x4. DATA li TYPE i VALUE 1. DATA lo TYPE i VALUE 1. CONSTANTS n_bits TYPE i VALUE 32. DATA b TYPE i. *This is the ugliest thing i have ever written. *unfortunately 7FFFFFFF * 4 equals 00000010 in abap... *so i have to do my own. o = i. li = n_bits. DO n_bits TIMES. GET BIT li OF o INTO b. lo = li + n. IF lo <= n_bits. SET BIT lo OF o TO b. ENDIF. li = li - 1. ENDDO. li = 1. DO n TIMES. SET BIT li OF o TO 0. li = li + 1. ENDDO. ENDFORM. "tea_shift_right *&--------------------------------------------------------------------* *& Form tea_shift_left *&--------------------------------------------------------------------* FORM tea_shift_left USING i TYPE t_x4 n TYPE i CHANGING o TYPE t_x4. DATA li TYPE i VALUE 1. DATA lo TYPE i VALUE 1. CONSTANTS n_bits TYPE i VALUE 32. DATA b TYPE i. *This is the second ugliest thing i have ever written. * after shift right :-) o = i. li = 1. DO n_bits TIMES. GET BIT li OF o INTO b. lo = li - n. IF lo > 0. SET BIT lo OF o TO b. ENDIF. li = li + 1. ENDDO. li = n_bits. DO n TIMES. SET BIT li OF o TO 0. li = li - 1. ENDDO. ENDFORM. "tea_shift_left *&--------------------------------------------------------------------* *& Form tea_unsigned_sum *&--------------------------------------------------------------------* FORM tea_unsigned_sum USING i TYPE t_x4 j TYPE t_x4 CHANGING o TYPE t_x4. DATA i0 TYPE t_x2. DATA i1 TYPE t_x2. DATA i2 TYPE t_x2. DATA i3 TYPE t_x2. DATA j0 TYPE t_x2. DATA j1 TYPE t_x2. DATA j2 TYPE t_x2. DATA j3 TYPE t_x2. DATA o0 TYPE t_x2. DATA o1 TYPE t_x2. DATA o2 TYPE t_x2. DATA o3 TYPE t_x2. *Sum is on signed values only. *It overflows and even when catching the exception... *the results is blank. :-( i0+1(1) = i+3(1). i1+1(1) = i+2(1). i2+1(1) = i+1(1). i3+1(1) = i+0(1). j0+1(1) = j+3(1). j1+1(1) = j+2(1). j2+1(1) = j+1(1). j3+1(1) = j+0(1). o0 = j0 + i0. o1 = j1 + i1 + o0+0(1). o2 = j2 + i2 + o1+0(1). o3 = j3 + i3 + o2+0(1). o+3(1) = o0+1(1). o+2(1) = o1+1(1). o+1(1) = o2+1(1). o+0(1) = o3+1(1). ENDFORM. "tea_unsigned_sum *&--------------------------------------------------------------------* *& Form tea_unsigned_sub *&--------------------------------------------------------------------* FORM tea_unsigned_sub USING i TYPE t_x4 j TYPE t_x4 CHANGING o TYPE t_x4. DATA i0 TYPE t_x2. DATA i1 TYPE t_x2. DATA i2 TYPE t_x2. DATA i3 TYPE t_x2. DATA j0 TYPE t_x2. DATA j1 TYPE t_x2. DATA j2 TYPE t_x2. DATA j3 TYPE t_x2. DATA o0 TYPE t_x2. DATA o1 TYPE t_x2. DATA o2 TYPE t_x2. DATA o3 TYPE t_x2. *Subtraction has the same problem as sum... i0+1(1) = i+3(1). i1+1(1) = i+2(1). i2+1(1) = i+1(1). i3+1(1) = i+0(1). j0+1(1) = j+3(1). j1+1(1) = j+2(1). j2+1(1) = j+1(1). j3+1(1) = j+0(1). o0 = i0 - j0. o1 = i1 - j1. IF o0+0(1) NE 0. o1 = o1 - 1. ENDIF. o2 = i2 - j2. IF o1+0(1) NE 0. o2 = o2 - 1. ENDIF. o3 = i3 - j3 . IF o2+0(1) NE 0. o3 = o3 - 1. ENDIF. o+3(1) = o0+1(1). o+2(1) = o1+1(1). o+1(1) = o2+1(1). o+0(1) = o3+1(1). ENDFORM. "tea_unsigned_sub