3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
1

Компиляция Inline assembler (вставки ассемблера)

13.09.2011, 10:37. Показов 5663. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток!
Уважаемые кодеры!
Помогите с компиляцией С++ со вставками ассемблера.

g++ или gcc выдает ошибку:
InsertToCsvString.cpp: Assembler messages:
InsertToCsvString.cpp:47: Error: suffix or operands invalid for `lea'
InsertToCsvString.cpp:57: Error: suffix or operands invalid for `lea'
InsertToCsvString.cpp:240: Error: suffix or operands invalid for `mov'

Пробовал на Crunchbang 10 Statler (Intel(R) Celeron(R) CPU U3600 @ 1.20GHz)
2.6.39-bpo.2-686-pae (Debian GNU/Linux 6.0.2 (squeeze))
с помощью Codelite, Geany.
Добавлял switch -m32 - не помогает.
Думал проблема в железе, хотя стоит не 64 битная ОС, попробовал скомпилировать
на Windows XP 32 бит (AMD 2500+) CygWin 2.0 с помощью g++ или gcc:
g++ -save-temps -m32 -g InsertToCsvString.cpp -o InsertToCsvString -lm
g++ -save-temps -Wall -g InsertToCsvString.cpp -o InsertToCsvString -lm

Результат такой же отрицательный .

Вот код, по которому получаем выше приведенные ошибки. Код является частью всей программы, поэтому в целом таких ошибок много.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#include <stdio.h>
#include <././sys/stat.h>
 
#include <fcntl.h>
#include <streambuf>
 
#include <dirent.h>
 
#include <vector>
#include <string>
 
 
#include <cstdlib>
 
#include "Unit1.h"
 
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0;
 
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input)
{
 int length;
 __asm__ (
     "leal $input, %edi           \n\t"
     "xorl %ecx,%ecx              \n\t"
     "movl (%edi), %edi           \n\t" 
"nexch2:                          \n\t"
     "movb (%edi), %al            \n\t"
     "incl %edi                   \n\t"
     "incl %ecx                   \n\t" // длина
     "testb %al,%al               \n\t"
     "jnz nexch2                  \n\t"
     
     "decl %ecx                   \n\t" // длина найдена
     "leal $length, %edx          \n\t"
     "movl %ecx, (%edx)           \n\t" 
  );
 return length;    // в eax 
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
int char2int(char* input)
{
 int output, ilength;
 ilength = find_length(input);
  __asm__ (
  " movl ($input), %edi           \n\t"
  "movl ($ilength), %ecx       \n\t"
 
  "xorl %eax,%eax              \n\t"
  "incl %eax                   \n\t" // al =1
  "xorl %esi,%esi              \n\t" // esi =0 , [edi-ecx] = input
  "addl %ecx,%edi              \n\t"
  "decl %edi                   \n\t" // [edi] = last char in string input = "1048576"
  "movb (%edi), %dl            \n\t"
  "andl $0x0f,%edx             \n\t" // edx = last char of input without fist semibyte of ASCII
  "addl %edx,%esi              \n\t" // esi = ------"---------"--------
  "decl %edi                   \n\t" //  [edi] = next char begining from end of input
  "decl %ecx                   \n\t"
 
"begint:                     \n\t"
 
  "movb (%edi), %bl       \n\t"
  "andl $0x0f,%ebx             \n\t" // ebx = next char begining from end of input without first semibyte
  "imull $10,%eax              \n\t" // eax = eax * 10
  "imull %eax,%ebx             \n\t" // ebx = ebx * eax
  "addl %ebx,%esi              \n\t" // esi = esi + ebx * eax
  "decl %edi                   \n\t" // [edi] = next char begining from end of input
  "decl %ecx                   \n\t" // ecx = number of char in input begining from start
  "jnz begint                  \n\t" // number != 0 ?
 
//!!!"leal $output, %edx          \n\t"
  "movl %esi, (%edx)           \n\t"
    );
  return output;
}
 
//------ ф-ция преобразования ASCII строки из цифр в TBCD строку ------
// например, ASCII код 32 36 35 38 30 33 = TBCD код 26 58 03
void char2tbcd(char* input, int &ilength, void *SubNBuf)
{
 ilength = find_length(input); 
 __asm__ (
  "movl $ilength, %eax         \n\t"
 
  "movl (%eax), %ecx           \n\t"
  "movl $input, %eax           \n\t"
  "movl $SubNBuf, %edi         \n\t"
  "xorl %ebx,%ebx              \n\t"
 
"begin1:                     \n\t"
 
  "movb (%eax), %bl           \n\t"
  "shlb $4,%bl                 \n\t"
 
  "movb (%eax,1), %bh          \n\t"
  "andb $0x0f,%bh              \n\t"
  "orb %bh,%bl                 \n\t"
 
  "movb %bl, (%edi)            \n\t"
 
  "incl %eax                   \n\t"
  "incl %eax                   \n\t"
  "incl %edi                   \n\t"
  "decl %ecx                   \n\t"
  "decl %ecx                   \n\t"
  "jnle begin1                 \n\t" // если не меньше или равно 0, т.е. >  =0
 );
 
 if(ilength>0) {
  ilength = ilength+1;
  ilength = ilength-1;
 } 
}
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) 
{
 const char *cp, *mp;
 while ((*string) && (*wild != '*'))    {
  if ((*wild != *string) && (*wild != '?')) return 0;
  wild++;
  string++;
 }
 while (*string)        {
  if (*wild == '*')  {
   if (!*++wild) return 1;
   mp = wild;
   cp = string+1;
  }
  else if ((*wild == *string) || (*wild == '?'))        {
   wild++;
   string++;
  }
  else  {
   wild = mp;
   string = cp++;
  }
 }
 while (*wild == '*')  wild++;
 return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
 int handle, handle2, bytes, iTBCDlen; //, endig, numparts;
 
 int ic_blength, ic_Nlength;
 void *xNsubsc, *xNsubsc2;
 char cTimebuf[32];  // для показа времени
 long iTimeValue;    // для показа времени
 
 int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи 
 
 
 
 bool bOdd;  // признак нечетного номера - другой способ поиска
 bool bNsub, bAsub;
 bool bMultyFiles = false, bFileNamesMatch = false;
 char *arg, *cbufsize = "1048576", *cSubsc, *cNsubsc, *cOddEven;
 char *sTime = " ";
 char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
 struct stat statbuf;
 int bufsize=0;
 
 void *buf;  // буфер для файла размером bufsize
 
 char *path = NULL;
 size_t size;
 DIR *dir;
 struct dirent *ent;
 using namespace std;
 
  vector<string> FileNameList;
 
 if(argc==1) {
  printf(         //ShowHelp:
  "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
  return 1;
 }
 printf("Input parameters are:\n");
 for(int i=1;i<argc;i++)  {    // цикл введенных параметров
  arg = argv[i];
  if(arg[0]=='-') {  // если начинается на '-'
  switch (arg[1]) {
   case 'f':
        cInputFileName = argv[i+1];
           // поиск и подсчет символа * внутри строки
          __asm__ (
           "movb $'*', %al              \n\t" // 0x2A
           "xorl %ecx,%ecx              \n\t"
           "movl ($cInputFileName), %edi   \n\t"
 
"scasbInputFileName:         \n\t"
           "incl %ecx                   \n\t" // счетчик символов внутри cInputFileName
           "scasb                       \n\t"          
           "jz SymbolFound              \n\t"
           "cmpb $0, (%edi)   \n\t"
           "jz EndSearchSymbolInFileName \n\t"
           "jmp ScasbInputFileName      \n\t"
 
"SymbolFound:                \n\t"
           "movb $1, $bMultyFiles   \n\t"
           "movl %ecx,%ebx              \n\t" // сохраним позицию '*' внутри cInputFileName
 
"EndSearchSymbolInFileName:   \n\t" // ecx - позиция '*' внутри cInputFileName
       );
                     
        if(bMultyFiles) {   // если много входных файлов
         path = getcwd(path, size);
         if ((dir = opendir(path)) == NULL) {
         perror("Unable to open directory");
     exit(1);
         }
         printf(" input files:\n");
         while ((ent = readdir(dir)) != NULL) {
           if(wildcmp(cInputFileName, ent->d_name)) {
           printf("  %s\n",ent->d_name);
           FileNameList.insert(FileNameList.end(),ent->d_name);
           bFileNamesMatch = 1;
          }
         }
         if(!bFileNamesMatch) {
          printf("  no match.\n");
          return 1;
         }
 
         if (closedir(dir) != 0) {
          perror("Unable to close directory");
          return 1;
         }
        }
        else     // если один входной файл
         if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
          printf(" input file - %s\n", cInputFileName);
          FileNameList.insert(FileNameList.end(),cInputFileName);
         }
         else {
          perror("open input file failed, error");
          return 1;
         }
   break;
 
   case 'o':
    handle2 = open(argv[i+1], O_CREAT |O_APPEND);
    if (handle2 != -1)  {       // argv[i+1] - выходной файл
     printf(" output file - %s\n", argv[i+1]);
    }
    else {
     perror("create output file failed, error");
     return 1;
    }
   break;
   case 'b':
    cbufsize = argv[i+1];   // argv[i+1] - размер буфера
   break;
   case 'A':   // фильтр поиска аб-та А
        bFilter = 1;
        cSubsc = "A";
        bAsub = true;
        bNsub = false;
        cNsubsc = argv[i+1];
        break;
   case 'B':  // фильтр поиска аб-та Б
        bFilter = 1;
        cSubsc = "B";
        bAsub = false;
        bNsub = false;
        cNsubsc = argv[i+1];
   break;
   case 'N':  // фильтр поиска номера любого аб-та
    bFilter = 1;
        cSubsc = "N";
        bAsub = false;
        bNsub = true;
        cNsubsc = argv[i+1];
        break;
   case 'c':
    bCsv = true;
   break;
  } // конец если начинается на '-'
  } // конец switch
 }  // конец цикла
 
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.09.2011, 10:37
Ответы с готовыми решениями:

inline assembler VS чтение по указателю
Доброе время суток. Задача состоит в чтении 1 байта по адресу указателя. Проблема с пониманием,...

GCC Inline Assembly перевести в Visual Studio Inline Assembler
Здравствуйте. Есть код на GCC Inline Assembly и его нужно перевести в Visual Studio Inline...

inline assembler в СИ
Доброго! каким образом можно связать внешную переменную и встроенный ассмблер в Си? чтоб было...

Inline Assembler & C++
int main(int argc, char *argv) { perevod(); cout&lt;&lt;&quot;Type Esc to Escape \n&quot;; __asm ...

15
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.09.2011, 18:12 2
Проблема в 45-й строке твоего выложенного исходника: "leal $length, %edx \n\t"
Я так понимаю, что ты в gcc пытаешься скормить ассемблерную вставку, написанную по правилам виндузовых компиляторов

По части gnu'тых ассемблерных вставок несколько раз на форуме обсуждалось, с ходу нашёл только две ссылки. По этим ссылкам лучше темы целиком почитай
Ошибка компиляции ассемблерной вставки
Встроенный asm не понимает метки (GCC).
1
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
14.09.2011, 01:44  [ТС] 3
Почитал, подумал, посмторел еще раз InsertToCsvString.s и GCC-Inline-Assembly-HOWTO.
Поменял:
Assembler
1
leal $input, %edi
на
Assembler
1
2
movl $input, %eax          
     leal 1(%eax), %edi
Кстати, пробовал до этого менять на регистр, только без 1(. AT&T постарались на славу.
Аналогично другой leal.
А также
Assembler
1
movb $1, $bMultyFiles
на
Assembler
1
2
movl $bMultyFiles, %eax   
           movb $1, (%eax)
Компилируется и строится без ошибок. Идем дальше. Спасибо всем.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
14.09.2011, 08:15 4
А покажи-ка весь исходник. А то удивительно, что такое у тебя gcc съел - не должен бы. Либо съел, но код неверный получился

Добавлено через 1 минуту
Опция -save-temps - отладочная. Регулярно её незачем использовать. Если хочешь ассемблерный текст посмотреть, то надо компилять с опцией -S. "gcc t.c -S" создаст файл t.s. Можно добавить опцию "-o trampampam.s", чтобы задать имя выходного файла
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
14.09.2011, 11:44  [ТС] 5
Компилируемый код весь такой же, как приводил выше, только с изменениями:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#include <stdio.h>
#include <././sys/stat.h> 
#include <fcntl.h>
#include <streambuf> 
#include <dirent.h> 
#include <vector>
#include <string> 
#include <cstdlib> 
#include "Unit1.h" 
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0; 
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input)
{
 int length;
 __asm__ (
     //"leal $input, %edi           \n\t"      
     "movl $input, %eax           \n\t"
     "leal 1(%eax), %edi          \n\t"
     "xorl %ecx,%ecx              \n\t"
     "movl (%edi), %edi           \n\t" 
"nexch2:                          \n\t"
     "movb (%edi), %al            \n\t"
     "incl %edi                   \n\t"
     "incl %ecx                   \n\t" // длина
     "testb %al,%al               \n\t"
     "jnz nexch2                  \n\t"
     
     "decl %ecx                   \n\t" // длина найдена
     //"leal $length, %edx          \n\t"
     "movl $length, %eax          \n\t"
     "leal 1(%eax), %edx          \n\t"
     "movl %ecx, (%edx)           \n\t" 
  );
 return length;    // в eax 
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
int char2int(char* input)
{
 int output, ilength;
 ilength = find_length(input);
  __asm__ (
  " movl ($input), %edi           \n\t"
  "movl ($ilength), %ecx       \n\t"
 
  "xorl %eax,%eax              \n\t"
  "incl %eax                   \n\t" // al =1
  "xorl %esi,%esi              \n\t" // esi =0 , [edi-ecx] = input
  "addl %ecx,%edi              \n\t"
  "decl %edi                   \n\t" // [edi] = last char in string input = "1048576"
  "movb (%edi), %dl            \n\t"
  "andl $0x0f,%edx             \n\t" // edx = last char of input without fist semibyte of ASCII
  "addl %edx,%esi              \n\t" // esi = ------"---------"--------
  "decl %edi                   \n\t" //  [edi] = next char begining from end of input
  "decl %ecx                   \n\t"
 
"begint:                     \n\t"
 
  "movb (%edi), %bl       \n\t"
  "andl $0x0f,%ebx             \n\t" // ebx = next char begining from end of input without first semibyte
  "imull $10,%eax              \n\t" // eax = eax * 10
  "imull %eax,%ebx             \n\t" // ebx = ebx * eax
  "addl %ebx,%esi              \n\t" // esi = esi + ebx * eax
  "decl %edi                   \n\t" // [edi] = next char begining from end of input
  "decl %ecx                   \n\t" // ecx = number of char in input begining from start
  "jnz begint                  \n\t" // number != 0 ?
 
  //"leal $output, %edx        \n\t"
  "movl $output, %eax           \n\t"
  "leal 1(%eax), %edi          \n\t"
  "movl %esi, (%edx)           \n\t"
    );
  return output;
}
 
//------ ф-ция преобразования ASCII строки из цифр в TBCD строку ------
// например, ASCII код 32 36 35 38 30 33 = TBCD код 26 58 03
void char2tbcd(char* input, int &ilength, void *SubNBuf)
{
 ilength = find_length(input); 
 __asm__ (
  "movl $ilength, %eax         \n\t"
 
  "movl (%eax), %ecx           \n\t"
  "movl $input, %eax           \n\t"
  "movl $SubNBuf, %edi         \n\t"
  "xorl %ebx,%ebx              \n\t"
 
"begin1:                     \n\t"
 
  "movb (%eax), %bl           \n\t"
  "shlb $4,%bl                 \n\t"
 
  "movb (%eax,1), %bh          \n\t"
  "andb $0x0f,%bh              \n\t"
  "orb %bh,%bl                 \n\t"
 
  "movb %bl, (%edi)            \n\t"
 
  "incl %eax                   \n\t"
  "incl %eax                   \n\t"
  "incl %edi                   \n\t"
  "decl %ecx                   \n\t"
  "decl %ecx                   \n\t"
  "jnle begin1                 \n\t" // если не меньше или равно 0, т.е. >  =0
 );
 
 if(ilength>0) {
  ilength = ilength+1;
  ilength = ilength-1;
 } 
}
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) 
{
 const char *cp, *mp;
 while ((*string) && (*wild != '*'))    {
  if ((*wild != *string) && (*wild != '?')) return 0;
  wild++;
  string++;
 }
 while (*string)        {
  if (*wild == '*')  {
   if (!*++wild) return 1;
   mp = wild;
   cp = string+1;
  }
  else if ((*wild == *string) || (*wild == '?'))        {
   wild++;
   string++;
  }
  else  {
   wild = mp;
   string = cp++;
  }
 }
 while (*wild == '*')  wild++;
 return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
 int handle, handle2, bytes, iTBCDlen; 
 
 int ic_blength, ic_Nlength;
 void *xNsubsc, *xNsubsc2;
 char cTimebuf[32];  // для показа времени
 long iTimeValue;    // для показа времени
 
 int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи 
 
 
 
 bool bOdd;  // признак нечетного номера - другой способ поиска
 bool bNsub, bAsub;
 bool bMultyFiles = false, bFileNamesMatch = false;
 char *arg, *cbufsize = "1048576", *cSubsc, *cNsubsc, *cOddEven;
 char *sTime = " ";
 char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
 struct stat statbuf;
 int bufsize=0;
 
 void *buf;  // буфер для файла размером bufsize
 
 char *path = NULL;
 size_t size;
 DIR *dir;
 struct dirent *ent;
 using namespace std;
 
  vector<string> FileNameList;
 
 if(argc==1) {
  printf(         //ShowHelp:
  "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
  return 1;
 }
 printf("Input parameters are:\n");
 for(int i=1;i<argc;i++)  {    // цикл введенных параметров
  arg = argv[i];
  if(arg[0]=='-') {  // если начинается на '-'
  switch (arg[1]) {
   case 'f':
        cInputFileName = argv[i+1];
           // поиск и подсчет символа * внутри строки
          __asm__ (
           "movb $'*', %al              \n\t" // 0x2A
           "xorl %ecx,%ecx              \n\t"
           "movl ($cInputFileName), %edi   \n\t"
 
"scasbInputFileName:         \n\t"
           "incl %ecx                   \n\t" // счетчик символов внутри cInputFileName
           "scasb                       \n\t"          
           "jz SymbolFound              \n\t"
           "cmpb $0, (%edi)   \n\t"
           "jz EndSearchSymbolInFileName \n\t"
           "jmp ScasbInputFileName      \n\t"
 
"SymbolFound:                \n\t"
           //"movb $1, $bMultyFiles   \n\t"
           "movl $bMultyFiles, %eax   \n\t"
           "movb $1, (%eax)   \n\t"
           "movl %ecx,%ebx              \n\t" // сохраним позицию '*' внутри cInputFileName
 
"EndSearchSymbolInFileName:   \n\t" // ecx - позиция '*' внутри cInputFileName
       );
                     
        if(bMultyFiles) {   // если много входных файлов
         path = getcwd(path, size);
         if ((dir = opendir(path)) == NULL) {
         perror("Unable to open directory");
     exit(1);
         }
         printf(" input files:\n");
         while ((ent = readdir(dir)) != NULL) {
           if(wildcmp(cInputFileName, ent->d_name)) {
           printf("  %s\n",ent->d_name);
                   FileNameList.insert(FileNameList.end(),ent->d_name);
           bFileNamesMatch = 1;
          }
         }
         if(!bFileNamesMatch) {
          printf("  no match.\n");
          return 1;
         }
 
         if (closedir(dir) != 0) {
          perror("Unable to close directory");
          return 1;
         }
        }
        else     // если один входной файл
                 if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
          printf(" input file - %s\n", cInputFileName);
                  FileNameList.insert(FileNameList.end(),cInputFileName);
         }
         else {
          perror("open input file failed, error");
          return 1;
         }
   break;
 
   case 'o':
        handle2 = open(argv[i+1], O_CREAT |O_APPEND);
    if (handle2 != -1)  {       // argv[i+1] - выходной файл
     printf(" output file - %s\n", argv[i+1]);
    }
    else {
     perror("create output file failed, error");
     return 1;
    }
   break;
   case 'b':
    cbufsize = argv[i+1];   // argv[i+1] - размер буфера
   break;
   case 'A':   // фильтр поиска аб-та А
        bFilter = 1;
        cSubsc = "A";
        bAsub = true;
        bNsub = false;
        cNsubsc = argv[i+1];
        break;
   case 'B':  // фильтр поиска аб-та Б
        bFilter = 1;
        cSubsc = "B";
        bAsub = false;
        bNsub = false;
        cNsubsc = argv[i+1];
   break;
   case 'N':  // фильтр поиска номера любого аб-та
    bFilter = 1;
        cSubsc = "N";
        bAsub = false;
        bNsub = true;
        cNsubsc = argv[i+1];
        break;
   case 'c':
    bCsv = true;
   break;
  } // конец если начинается на '-'
  } // конец switch
 }  // конец цикла
 
}
Да, на счет успешной компиляции поторопился:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
g++ -Wall -c "InsertToCsvString.cpp" (in directory: /home/avatar/projects/InsertToCsvString)
In file included from InsertToCsvString.cpp:15:
Unit1.h:20: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:21: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:23: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:25: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:34: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp: In function ‘int main(int, char**)’:
InsertToCsvString.cpp:179: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:180: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:181: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:287: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:294: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:301: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:165: warning: unused variable ‘bytes’
InsertToCsvString.cpp:165: warning: unused variable ‘iTBCDlen’
InsertToCsvString.cpp:167: warning: unused variable ‘ic_blength’
InsertToCsvString.cpp:167: warning: unused variable ‘ic_Nlength’
InsertToCsvString.cpp:168: warning: unused variable ‘xNsubsc’
InsertToCsvString.cpp:168: warning: unused variable ‘xNsubsc2’
InsertToCsvString.cpp:169: warning: unused variable ‘cTimebuf’
InsertToCsvString.cpp:170: warning: unused variable ‘iTimeValue’
InsertToCsvString.cpp:172: warning: unused variable ‘recordsize’
InsertToCsvString.cpp:176: warning: unused variable ‘bOdd’
InsertToCsvString.cpp:179: warning: unused variable ‘cOddEven’
InsertToCsvString.cpp:180: warning: unused variable ‘sTime’
InsertToCsvString.cpp:186: warning: unused variable ‘statbuf’
InsertToCsvString.cpp:187: warning: unused variable ‘bufsize’
InsertToCsvString.cpp:189: warning: unused variable ‘buf’
InsertToCsvString.cpp: In function ‘int find_length(char*)’:
InsertToCsvString.cpp:52: warning: ‘length’ is used uninitialized in this function
InsertToCsvString.cpp: In function ‘int char2int(char*)’:
InsertToCsvString.cpp:90: warning: ‘output’ is used uninitialized in this function
InsertToCsvString.cpp: In function ‘int main(int, char**)’:
InsertToCsvString.cpp:238: warning: ‘size’ may be used uninitialized in this function
Compilation finished successfully.
И
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
g++ -Wall -o "InsertToCsvString" "InsertToCsvString.cpp" (in directory: /home/avatar/projects/InsertToCsvString)
In file included from InsertToCsvString.cpp:15:
Unit1.h:20: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:21: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:23: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:25: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:34: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp: In function ‘int main(int, char**)’:
InsertToCsvString.cpp:179: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:180: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:181: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:287: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:294: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:301: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:165: warning: unused variable ‘bytes’
InsertToCsvString.cpp:165: warning: unused variable ‘iTBCDlen’
InsertToCsvString.cpp:167: warning: unused variable ‘ic_blength’
InsertToCsvString.cpp:167: warning: unused variable ‘ic_Nlength’
InsertToCsvString.cpp:168: warning: unused variable ‘xNsubsc’
InsertToCsvString.cpp:168: warning: unused variable ‘xNsubsc2’
InsertToCsvString.cpp:169: warning: unused variable ‘cTimebuf’
InsertToCsvString.cpp:170: warning: unused variable ‘iTimeValue’
InsertToCsvString.cpp:172: warning: unused variable ‘recordsize’
InsertToCsvString.cpp:176: warning: unused variable ‘bOdd’
InsertToCsvString.cpp:179: warning: unused variable ‘cOddEven’
InsertToCsvString.cpp:180: warning: unused variable ‘sTime’
InsertToCsvString.cpp:186: warning: unused variable ‘statbuf’
InsertToCsvString.cpp:187: warning: unused variable ‘bufsize’
InsertToCsvString.cpp:189: warning: unused variable ‘buf’
InsertToCsvString.cpp: In function ‘int find_length(char*)’:
InsertToCsvString.cpp:52: warning: ‘length’ is used uninitialized in this function
InsertToCsvString.cpp: In function ‘int char2int(char*)’:
InsertToCsvString.cpp:90: warning: ‘output’ is used uninitialized in this function
InsertToCsvString.cpp: In function ‘int main(int, char**)’:
InsertToCsvString.cpp:238: warning: ‘size’ may be used uninitialized in this function
/tmp/cc8WeG5B.o: In function `find_length(char*)':
InsertToCsvString.cpp:(.text+0x7): undefined reference to `input'
/tmp/cc8WeG5B.o: In function `nexch2':
InsertToCsvString.cpp:(.text+0x1c): undefined reference to `length'
/tmp/cc8WeG5B.o: In function `char2int(char*)':
InsertToCsvString.cpp:(.text+0x40): undefined reference to `$input'
InsertToCsvString.cpp:(.text+0x46): undefined reference to `$ilength'
/tmp/cc8WeG5B.o: In function `char2tbcd(char*, int&, void*)':
InsertToCsvString.cpp:(.text+0x8a): undefined reference to `ilength'
InsertToCsvString.cpp:(.text+0x91): undefined reference to `input'
InsertToCsvString.cpp:(.text+0x96): undefined reference to `SubNBuf'
/tmp/cc8WeG5B.o: In function `main':
InsertToCsvString.cpp:(.text+0x2b1): undefined reference to `$cInputFileName'
/tmp/cc8WeG5B.o: In function `SymbolFound':
InsertToCsvString.cpp:(.text+0x2c4): undefined reference to `bMultyFiles'
/tmp/cc8WeG5B.o: In function `scasbInputFileName':
InsertToCsvString.cpp:(.text+0x2bf): undefined reference to `ScasbInputFileName'
collect2: ld returned 1 exit status
Compilation failed.
На счет "undefined reference to `input' " буду думать.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
14.09.2011, 12:07 6
Цитата Сообщение от Remontik Посмотреть сообщение
На счет "undefined reference to `input' " буду думать
А что тут думать? $input в ассемблерном тексте будет восприниматься как глобальная метка, а не как локальная переменная с именем input. То же касается и остальных переменных. В gnu'тые вставки переменные надо через параметры вставки передавать, а не по именам Си'шных переменных

Добавлено через 4 минуты
Проблема с gnu'тыми вставками такая, что нигде нет внятного описания. Вот, например, родное описание, но оно довольно убогое: http://gcc.gnu.org/onlinedocs/... tended-Asm

Добавлено через 31 секунду
По ссылкам из поста #2 можешь посмотреть примеры вставок
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
16.09.2011, 13:08  [ТС] 7
Компиляция и построение прошли успешно.
Исправил код с использованием extended assembler (двойной % - это что-то):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#include <stdio.h>
#include <././sys/stat.h>
#include <fcntl.h>
#include <streambuf>
#include <dirent.h>
#include <vector>
#include <string>
#include <cstdlib>
#include "Unit1.h"
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0;
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input) {
    int length;
    __asm__  (
        //"leal $input, %edi           \n\t"
        //"movl $input, %eax           \n\t"
        //"leal 1(%eax), %edi          \n\t"
        "xorl %%ecx, %%ecx              \n\t"
        "movl (%%edi), %%esi           \n\t"
        "nexch2:                          \n\t"
        "movb (%%esi), %%al            \n\t"
        "incl %%esi                   \n\t"
        "incl %%ecx                   \n\t" // длина
        "testb %%al, %%al               \n\t"
        "jnz nexch2                  \n\t"
 
        "decl %%ecx                   \n\t" // длина найдена
        //"leal $length, %edx          \n\t"
        //"movl $length, %eax          \n\t"
        //"leal 1(%eax), %edx          \n\t"
        "movl %%ecx, (%%edx)           \n\t"
        : "=d"(length)     // output
        : "D"(input)      // input
        :              // modified
    );
    return length;    // в eax
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
int char2int(char* input) {
    int output, ilength;
    ilength = find_length(input);
    __asm__ (
        //"movl ($input), %edi           \n\t"
        //"movl ($ilength), %ecx       \n\t"
 
        "xorl %%eax, %%eax              \n\t"
        "incl %%eax                   \n\t" // al =1
        "xorl %%esi, %%esi              \n\t" // esi =0 , [edi-ecx] = input
        "addl %%ecx, %%edi              \n\t"
        "decl %%edi                   \n\t" // [edi] = last char in string input = "1048576"
        "movb (%%edi), %%dl            \n\t"
        "andl $0x0f, %%edx             \n\t" // edx = last char of input without fist semibyte of ASCII
        "addl %%edx, %%esi              \n\t" // esi = ------"---------"--------
        "decl %%edi                   \n\t" //  [edi] = next char begining from end of input
        "decl %%ecx                   \n\t"
 
        "begint:                     \n\t"
 
        "movb (%%edi), %%bl       \n\t"
        "andl $0x0f, %%ebx             \n\t" // ebx = next char begining from end of input without first semibyte
        "imull $10, %%eax              \n\t" // eax = eax * 10
        "imull %%eax, %%ebx             \n\t" // ebx = ebx * eax
        "addl %%ebx, %%esi              \n\t" // esi = esi + ebx * eax
        "decl %%edi                   \n\t" // [edi] = next char begining from end of input
        "decl %%ecx                   \n\t" // ecx = number of char in input begining from start
        "jnz begint                  \n\t" // number != 0 ?
 
        //"leal $output, %edx        \n\t"
        //"movl $output, %eax           \n\t"
        //"leal 1(%eax), %edi          \n\t"
        "movl %%esi, (%%edx)           \n\t"
        : "=d" (output)     // output
        : "D" (input), "c" (ilength)   // input
        :    // modify
    );
}
 
//------ ф-ция преобразования ASCII строки из цифр в TBCD строку ------
// например, ASCII код 32 36 35 38 30 33 = TBCD код 26 58 03
void char2tbcd(char* input, int &ilength, void *SubNBuf) {
    ilength = find_length(input);
    __asm__ (
        //"movl $ilength, %eax         \n\t"
 
        //"movl (%eax), %ecx           \n\t"
        //"movl $input, %eax           \n\t"
        //"movl $SubNBuf, %edi         \n\t"
        "xorl %%ebx, %%ebx              \n\t"
 
        "begin1:                     \n\t"
 
        "movb (%%eax), %%bl           \n\t"
        "shlb $4, %%bl                 \n\t"
 
        "movb (%%eax,1), %%bh          \n\t"
        "andb $0x0f, %%bh              \n\t"
        "orb %%bh, %%bl                 \n\t"
 
        "movb %%bl, (%%edi)            \n\t"
 
        "incl %%eax                   \n\t"
        "incl %%eax                   \n\t"
        "incl %%edi                   \n\t"
        "decl %%ecx                   \n\t"
        "decl %%ecx                   \n\t"
        "jnle begin1                 \n\t" // если не меньше или равно 0, т.е. >  =0
        : "=D" (SubNBuf)   // output
        : "a" (ilength), "c" (input)      // input
        :         // modify
    );
 
    if(ilength>0) {
        ilength = ilength+1;
        ilength = ilength-1;
    }
}
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) {
    const char *cp, *mp;
    while ((*string) && (*wild != '*'))    {
        if ((*wild != *string) && (*wild != '?')) return 0;
        wild++;
        string++;
    }
    while (*string)        {
        if (*wild == '*')  {
            if (!*++wild) return 1;
            mp = wild;
            cp = string+1;
        } else if ((*wild == *string) || (*wild == '?'))        {
            wild++;
            string++;
        } else  {
            wild = mp;
            string = cp++;
        }
    }
    while (*wild == '*')  wild++;
    return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
    int handle, handle2, bytes, iTBCDlen;
 
    int ic_blength, ic_Nlength;
    void *xNsubsc, *xNsubsc2;
    char cTimebuf[32];  // для показа времени
    long iTimeValue;    // для показа времени
 
    int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи
 
 
 
    bool bOdd;  // признак нечетного номера - другой способ поиска
    bool bNsub, bAsub;
    bool bMultyFiles = false, bFileNamesMatch = false;
    char *arg, *cbufsize = "1048576", *cSubsc, *cNsubsc, *cOddEven;
    char *sTime = " ";
    char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
    struct stat statbuf;
    int bufsize=0;
 
    void *buf;  // буфер для файла размером bufsize
 
    char *path = NULL;
    size_t size;
    DIR *dir;
    struct dirent *ent;
    using namespace std;
 
    vector<string> FileNameList;
 
    if(argc==1) {
        printf(         //ShowHelp:
            "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
        return 1;
    }
    printf("Input parameters are:\n");
    for(int i=1; i<argc; i++)  {  // цикл введенных параметров
        arg = argv[i];
        if(arg[0]=='-') {  // если начинается на '-'
            switch (arg[1]) {
            case 'f':
                cInputFileName = argv[i+1];
                // поиск и подсчет символа * внутри строки
                __asm__ (
                    "movb $'*', %%al              \n\t" // 0x2A
                    "xorl %%ecx, %%ecx              \n\t"
                    //"movl ($cInputFileName), %edi   \n\t"
 
                    "ScasbInputFileName:         \n\t"
                    "incl %%ecx                   \n\t" // счетчик символов внутри cInputFileName
                    "scasb                       \n\t"
                    "jz SymbolFound              \n\t"
                    "cmpb $0, (%%edi)   \n\t"
                    "jz EndSearchSymbolInFileName \n\t"
                    "jmp ScasbInputFileName      \n\t"
 
                    "SymbolFound:                \n\t"
                    //"movb $1, $bMultyFiles   \n\t"
                    //"movl $bMultyFiles, %eax   \n\t"
                    "movb $1, (%%eax)   \n\t"
                    "movl %%ecx, %%ebx              \n\t" // сохраним позицию '*' внутри cInputFileName
 
                    "EndSearchSymbolInFileName:   \n\t" // ecx - позиция '*' внутри cInputFileName
                    : "=a" (bMultyFiles)   // output
                    : "D" (cInputFileName)   // input
                    :
                );
 
                if(bMultyFiles) {   // если много входных файлов
                    path = getcwd(path, size);
                    if ((dir = opendir(path)) == NULL) {
                        perror("Unable to open directory");
                        exit(1);
                    }
                    printf(" input files:\n");
                    while ((ent = readdir(dir)) != NULL) {
                        if(wildcmp(cInputFileName, ent->d_name)) {
                            printf("  %s\n",ent->d_name);
                            FileNameList.insert(FileNameList.end(),ent->d_name);
                            bFileNamesMatch = 1;
                        }
                    }
                    if(!bFileNamesMatch) {
                        printf("  no match.\n");
                        return 1;
                    }
 
                    if (closedir(dir) != 0) {
                        perror("Unable to close directory");
                        return 1;
                    }
                } else   // если один входной файл
                    if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
                        printf(" input file - %s\n", cInputFileName);
                        FileNameList.insert(FileNameList.end(),cInputFileName);
                    } else {
                        perror("open input file failed, error");
                        return 1;
                    }
                break;
 
            case 'o':
                handle2 = open(argv[i+1], O_CREAT |O_APPEND);
                if (handle2 != -1)  {       // argv[i+1] - выходной файл
                    printf(" output file - %s\n", argv[i+1]);
                } else {
                    perror("create output file failed, error");
                    return 1;
                }
                break;
            case 'b':
                cbufsize = argv[i+1];   // argv[i+1] - размер буфера
                break;
            case 'A':   // фильтр поиска аб-та А
                bFilter = 1;
                cSubsc = "A";
                bAsub = true;
                bNsub = false;
                cNsubsc = argv[i+1];
                break;
            case 'B':  // фильтр поиска аб-та Б
                bFilter = 1;
                cSubsc = "B";
                bAsub = false;
                bNsub = false;
                cNsubsc = argv[i+1];
                break;
            case 'N':  // фильтр поиска номера любого аб-та
                bFilter = 1;
                cSubsc = "N";
                bAsub = false;
                bNsub = true;
                cNsubsc = argv[i+1];
                break;
            case 'c':
                bCsv = true;
                break;
            } // конец если начинается на '-'
        } // конец switch
    }  // конец цикла
 
}
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
g++ -Wall -o "InsertToCsvString" "InsertToCsvString.cpp" (in directory: /home/avatar/projects/InsertToCsvString)
In file included from InsertToCsvString.cpp:9:
Unit1.h:20: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:21: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:23: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:25: warning: deprecated conversion from string constant to ‘char*’
Unit1.h:34: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp: In function ‘int char2int(char*)’:
InsertToCsvString.cpp:90: warning: no return statement in function returning non-void
InsertToCsvString.cpp: In function ‘int main(int, char**)’:
InsertToCsvString.cpp:181: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:182: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:183: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:292: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:299: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:306: warning: deprecated conversion from string constant to ‘char*’
InsertToCsvString.cpp:167: warning: unused variable ‘bytes’
InsertToCsvString.cpp:167: warning: unused variable ‘iTBCDlen’
InsertToCsvString.cpp:169: warning: unused variable ‘ic_blength’
InsertToCsvString.cpp:169: warning: unused variable ‘ic_Nlength’
InsertToCsvString.cpp:170: warning: unused variable ‘xNsubsc’
InsertToCsvString.cpp:170: warning: unused variable ‘xNsubsc2’
InsertToCsvString.cpp:171: warning: unused variable ‘cTimebuf’
InsertToCsvString.cpp:172: warning: unused variable ‘iTimeValue’
InsertToCsvString.cpp:174: warning: unused variable ‘recordsize’
InsertToCsvString.cpp:178: warning: unused variable ‘bOdd’
InsertToCsvString.cpp:181: warning: unused variable ‘cOddEven’
InsertToCsvString.cpp:182: warning: unused variable ‘sTime’
InsertToCsvString.cpp:188: warning: unused variable ‘statbuf’
InsertToCsvString.cpp:189: warning: unused variable ‘bufsize’
InsertToCsvString.cpp:191: warning: unused variable ‘buf’
InsertToCsvString.cpp:243: warning: ‘size’ may be used uninitialized in this function
Compilation finished successfully.
Конечный файл запускается.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
16.09.2011, 13:52 8
Цитата Сообщение от Remontik Посмотреть сообщение
Компиляция и построение прошли успешно.
Исправил код с использованием extended assembler (двойной % - это что-то):
Ты кое-что закомментировал в ассемблерной вставке, потому и компиляется. Сивол % в gnu'той вставке - это управляющий символ (как в printf'е), поэтому для рисования знака процента его нужно два раза писать

В первой вставке "$length" надо заменить на "%0" (нулевой параметр вставки), а "$input" - на "%1" (1-й параметр вставки). Вместо "=d" лучше написать "=&d". В остальных вставках аналогично. Разумеется, надо раскомментировать то, что ты закомментировал

Если твой код работает - то скорее всего в процедуры с ассемблерными вставками он и не попадает. Потому как то, что у тебя написано - это вряд ли рабочий код
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
17.09.2011, 13:07  [ТС] 9
Поменял... Компиляция, построение успешны.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#include <stdio.h>
#include <././sys/stat.h> 
#include <fcntl.h>
#include <streambuf> 
#include <dirent.h> 
#include <vector>
#include <string> 
#include <cstdlib> 
#include "Unit1.h" 
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0; 
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input)
{
 int length;
 __asm__  volatile ( 
     //"leal $input, %edi           \n\t"
     //"movl $input, %eax           \n\t"
     //"leal 1(%eax), %edi          \n\t"
     "movl %1, %%eax                 \n\t"
     "leal 1(%%eax), %%edi            \n\t"
     "xorl %%ecx, %%ecx              \n\t"
     "movl (%%edi), %%esi           \n\t" 
"nexch2:                          \n\t"
     "movb (%%esi), %%al            \n\t"
     "incl %%esi                   \n\t"
     "incl %%ecx                   \n\t" // длина
     "testb %%al, %%al               \n\t"
     "jnz nexch2                  \n\t"
     
     "decl %%ecx                   \n\t" // длина найдена
     //"leal $length, %edx          \n\t"
     //"movl $length, %eax          \n\t"
     //"leal 1(%eax), %edx          \n\t"
     "movl %0, %%eax         \n\t"
     "leal 1(%%eax), %%edx          \n\t"
     "movl %%ecx, (%%edx)           \n\t"
     : "=&d"(length)     // output
     : "D"(input)      // input
     :              // modified
  );
 return length;    // в eax 
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
int char2int  (char* input)
{
 int output, ilength;
 ilength = find_length(input);
  __asm__ (
  //"movl ($input), %edi           \n\t"
  //"movl ($ilength), %ecx       \n\t"
  "movl (%1), %%edi           \n\t"
  "movl (%2), %%ecx           \n\t"
 
  "xorl %%eax, %%eax              \n\t"
  "incl %%eax                   \n\t" // al =1
  "xorl %%esi, %%esi              \n\t" // esi =0 , [edi-ecx] = input
  "addl %%ecx, %%edi              \n\t"
  "decl %%edi                   \n\t" // [edi] = last char in string input = "1048576"
  "movb (%%edi), %%dl            \n\t"
  "andl $0x0f, %%edx             \n\t" // edx = last char of input without fist semibyte of ASCII
  "addl %%edx, %%esi              \n\t" // esi = ------"---------"--------
  "decl %%edi                   \n\t" //  [edi] = next char begining from end of input
  "decl %%ecx                   \n\t"
 
"begint:                     \n\t"
 
  "movb (%%edi), %%bl       \n\t"
  "andl $0x0f, %%ebx             \n\t" // ebx = next char begining from end of input without first semibyte
  "imull $10, %%eax              \n\t" // eax = eax * 10
  "imull %%eax, %%ebx             \n\t" // ebx = ebx * eax
  "addl %%ebx, %%esi              \n\t" // esi = esi + ebx * eax
  "decl %%edi                   \n\t" // [edi] = next char begining from end of input
  "decl %%ecx                   \n\t" // ecx = number of char in input begining from start
  "jnz begint                  \n\t" // number != 0 ?
 
  //"leal $output, %edx        \n\t"
  //"movl $output, %eax           \n\t"
  //"leal 1(%eax), %edi          \n\t"
  "movl %0, %%eax           \n\t"
  "leal 1(%%eax), %%edi          \n\t"
  "movl %%esi, (%%edx)           \n\t"
  : "=&d" (output)     // output
  : "D" (input), "c" (ilength)   // input
  :    // modify
  );
}
 
//------ ф-ция преобразования ASCII строки из цифр в TBCD строку ------
// например, ASCII код 32 36 35 38 30 33 = TBCD код 26 58 03
void char2tbcd(char* input, int &ilength, void *SubNBuf)
{
 ilength = find_length(input); 
 __asm__ volatile (
  //"movl $ilength, %eax         \n\t" 
  //"movl (%eax), %ecx           \n\t"
  "movl %1, %%eax              \n\t" 
  "movl (%%eax), %%ecx         \n\t"
  
  //"movl $input, %eax           \n\t"
  "movl %2, %%eax              \n\t"
  
  //"movl $SubNBuf, %edi         \n\t"  
  "movl %0, %%edi              \n\t"
  
  "xorl %%ebx, %%ebx           \n\t"
 
"begin1:                       \n\t"
 
  "movb (%%eax), %%bl          \n\t"
  "shlb $4, %%bl               \n\t"
 
  "movb (%%eax,1), %%bh        \n\t"
  "andb $0x0f, %%bh            \n\t"
  "orb %%bh, %%bl              \n\t"
 
  "movb %%bl, (%%edi)          \n\t"
 
  "incl %%eax                  \n\t"
  "incl %%eax                  \n\t"
  "incl %%edi                  \n\t"
  "decl %%ecx                  \n\t"
  "decl %%ecx                  \n\t"
  "jnle begin1                 \n\t" // если не меньше или равно 0, т.е. >  =0
  : "=&D" (SubNBuf)   // output
  : "a" (ilength), "c" (input)      // input
  :         // modify
 );
 
 if(ilength>0) {
  ilength = ilength+1;
  ilength = ilength-1;
 } 
}
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) 
{
 const char *cp, *mp;
 while ((*string) && (*wild != '*'))    {
  if ((*wild != *string) && (*wild != '?')) return 0;
  wild++;
  string++;
 }
 while (*string)        {
  if (*wild == '*')  {
   if (!*++wild) return 1;
   mp = wild;
   cp = string+1;
  }
  else if ((*wild == *string) || (*wild == '?'))        {
   wild++;
   string++;
  }
  else  {
   wild = mp;
   string = cp++;
  }
 }
 while (*wild == '*')  wild++;
 return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
 int handle, handle2, bytes, iTBCDlen, iLength; 
 
 int ic_blength, ic_Nlength;
 void *xNsubsc, *xNsubsc2;
 char cTimebuf[32];  // для показа времени
 long iTimeValue;    // для показа времени
 
 int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи 
 
 
 
 bool bOdd;  // признак нечетного номера - другой способ поиска
 bool bNsub, bAsub;
 bool bMultyFiles = false, bFileNamesMatch = false;
 char *arg, *cbufsize = "1048576", *cSubsc, *cNsubsc, *cOddEven;
 char *sTime = " ";
 char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
 struct stat statbuf;
 int bufsize=0;
 
 void *buf;  // буфер для файла размером bufsize
 
 char *path = NULL;
 size_t size;
 DIR *dir;
 struct dirent *ent;
 using namespace std;
 
  vector<string> FileNameList;
 
 if(argc==1) {
  printf(         //ShowHelp:
  "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
  return 1;
 }
 printf("Input parameters are:\n");
 for(int i=1;i<argc;i++)  {    // цикл введенных параметров
  arg = argv[i];
  if(arg[0]=='-') {  // если начинается на '-'
  switch (arg[1]) {
   case 'f':
        cInputFileName = argv[i+1];
    iLength = find_length(cInputFileName);  
           // поиск и подсчет символа * внутри строки
          __asm__  volatile (
           "movb $'*', %%al                \n\t" // 0x2A
           "xorl %%ecx, %%ecx              \n\t"
           //"movl ($cInputFileName), %edi   \n\t"
           "movl (%1), %%edi   \n\t"
 
"ScasbInputFileName:                       \n\t"
           "incl %%ecx                     \n\t" // счетчик символов внутри cInputFileName
           "scasb                          \n\t"          
           "jz SymbolFound                 \n\t"
           "cmpb $0, (%%edi)   \n\t"
           "jz EndSearchSymbolInFileName   \n\t"
           "jmp ScasbInputFileName         \n\t"
 
"SymbolFound:                              \n\t"
           //"movb $1, $bMultyFiles          \n\t"
           //"movl $bMultyFiles, %eax        \n\t"
           
           //"movl %0, %%eax                 \n\t"                      
           //"movb $1, (%%eax)               \n\t"
           
           "movb $1, %0               \n\t"
           
           "movl %%ecx, %%ebx              \n\t" // сохраним позицию '*' внутри cInputFileName
 
"EndSearchSymbolInFileName:                \n\t" // ecx - позиция '*' внутри cInputFileName
       : "=&a" (bMultyFiles)   // output
       : "D" (cInputFileName)   // input
       : 
       );
                     
        if(bMultyFiles) {   // если много входных файлов
         path = getcwd(path, size);
         if ((dir = opendir(path)) == NULL) {
         perror("Unable to open directory");
     exit(1);
         }
         printf(" input files:\n");
         while ((ent = readdir(dir)) != NULL) {
           if(wildcmp(cInputFileName, ent->d_name)) {
           printf("  %s\n",ent->d_name);
                   FileNameList.insert(FileNameList.end(),ent->d_name);
           bFileNamesMatch = 1;
          }
         }
         if(!bFileNamesMatch) {
          printf("  no match.\n");
          return 1;
         }
 
         if (closedir(dir) != 0) {
          perror("Unable to close directory");
          return 1;
         }
        }
        else     // если один входной файл
                 if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
          printf(" input file - %s\n", cInputFileName);
                  FileNameList.insert(FileNameList.end(),cInputFileName);
         }
         else {
          perror("open input file failed, error");
          return 1;
         }
   break;
 
   case 'o':
        handle2 = open(argv[i+1], O_CREAT |O_APPEND);
    if (handle2 != -1)  {       // argv[i+1] - выходной файл
     printf(" output file - %s\n", argv[i+1]);
    }
    else {
     perror("create output file failed, error");
     return 1;
    }
   break;
   case 'b':
    cbufsize = argv[i+1];   // argv[i+1] - размер буфера
   break;
   case 'A':   // фильтр поиска аб-та А
        bFilter = 1;
        cSubsc = "A";
        bAsub = true;
        bNsub = false;
        cNsubsc = argv[i+1];
        break;
   case 'B':  // фильтр поиска аб-та Б
        bFilter = 1;
        cSubsc = "B";
        bAsub = false;
        bNsub = false;
        cNsubsc = argv[i+1];
   break;
   case 'N':  // фильтр поиска номера любого аб-та
    bFilter = 1;
        cSubsc = "N";
        bAsub = false;
        bNsub = true;
        cNsubsc = argv[i+1];
        break;
   case 'c':
    bCsv = true;
   break;
  } // конец если начинается на '-'
  } // конец switch
 }  // конец цикла
 
}
Только при пошаговом исполнении после 230 строки, где стоит Breakpoint, Codelite сразу переходит на 50, т.е.
по ассемблерным вставкам он не проходит. Другого графического debugger-а у меня нет. Но дело в том, что при запуске с параметрами -f filename* в терминале выходит "Input parameters are:
Segmentation fault", что значит, вероятно, программа скомпилирована без ассемблерных вставок. Или ошибка в другом, но проследить ее я не могу, т.к. Codelite после 50 строки выдает MessageBox
"Program Received signal SIGDEV
Stack trace is available in the Call Stack tab"
Вот данные из Call Stack tab:
Bash
1
2
0  0x08048a59  find_length  /home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp  50
1  0x08048d21  main  /home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp  230
Вот лог debugger-а после MessageBox:
Bash
1
2
3
4
5
6
7
8
9
10
11
DEBUG>>*stopped,reason="exited-signalled",signal-name="SIGSEGV",signal-meaning="Segmentation fault"
DEBUG>>00000571-file-list-exec-source-file
DEBUG>>00000572-break-list
DEBUG>>00000571^done,line="50",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",macro-info="0"
DEBUG>>00000573-stack-list-frames
DEBUG>>00000572^done,BreakpointTable={nr_rows="3",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x08048d16",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="230",times="1",original-location="\"/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp:230"},bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="0x08048c50",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="188",times="1",original-location="\"/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp:188"},bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0x08048c50",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="188",times="1",original-location="main"}]}
DEBUG>>00000573^error,msg="No registers."
No registers.
DEBUG>>00000574-exec-step
DEBUG>>00000574^error,msg="The program is not being run."
The program is not being run.
Ничего пока не ясно. Буду думать.

Добавлено через 3 минуты
Поменял... Компиляция, построение успешны.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#include <stdio.h>
#include <././sys/stat.h> 
#include <fcntl.h>
#include <streambuf> 
#include <dirent.h> 
#include <vector>
#include <string> 
#include <cstdlib> 
#include "Unit1.h" 
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0; 
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input)
{
 int length;
 __asm__  volatile ( 
     //"leal $input, %edi           \n\t"
     //"movl $input, %eax           \n\t"
     //"leal 1(%eax), %edi          \n\t"
     "movl %1, %%eax                 \n\t"
     "leal 1(%%eax), %%edi            \n\t"
     "xorl %%ecx, %%ecx              \n\t"
     "movl (%%edi), %%esi           \n\t" 
"nexch2:                          \n\t"
     "movb (%%esi), %%al            \n\t"
     "incl %%esi                   \n\t"
     "incl %%ecx                   \n\t" // длина
     "testb %%al, %%al               \n\t"
     "jnz nexch2                  \n\t"
     
     "decl %%ecx                   \n\t" // длина найдена
     //"leal $length, %edx          \n\t"
     //"movl $length, %eax          \n\t"
     //"leal 1(%eax), %edx          \n\t"
     "movl %0, %%eax         \n\t"
     "leal 1(%%eax), %%edx          \n\t"
     "movl %%ecx, (%%edx)           \n\t"
     : "=&d"(length)     // output
     : "D"(input)      // input
     :              // modified
  );
 return length;    // в eax 
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
int char2int  (char* input)
{
 int output, ilength;
 ilength = find_length(input);
  __asm__ (
  //"movl ($input), %edi           \n\t"
  //"movl ($ilength), %ecx       \n\t"
  "movl (%1), %%edi           \n\t"
  "movl (%2), %%ecx           \n\t"
 
  "xorl %%eax, %%eax              \n\t"
  "incl %%eax                   \n\t" // al =1
  "xorl %%esi, %%esi              \n\t" // esi =0 , [edi-ecx] = input
  "addl %%ecx, %%edi              \n\t"
  "decl %%edi                   \n\t" // [edi] = last char in string input = "1048576"
  "movb (%%edi), %%dl            \n\t"
  "andl $0x0f, %%edx             \n\t" // edx = last char of input without fist semibyte of ASCII
  "addl %%edx, %%esi              \n\t" // esi = ------"---------"--------
  "decl %%edi                   \n\t" //  [edi] = next char begining from end of input
  "decl %%ecx                   \n\t"
 
"begint:                     \n\t"
 
  "movb (%%edi), %%bl       \n\t"
  "andl $0x0f, %%ebx             \n\t" // ebx = next char begining from end of input without first semibyte
  "imull $10, %%eax              \n\t" // eax = eax * 10
  "imull %%eax, %%ebx             \n\t" // ebx = ebx * eax
  "addl %%ebx, %%esi              \n\t" // esi = esi + ebx * eax
  "decl %%edi                   \n\t" // [edi] = next char begining from end of input
  "decl %%ecx                   \n\t" // ecx = number of char in input begining from start
  "jnz begint                  \n\t" // number != 0 ?
 
  //"leal $output, %edx        \n\t"
  //"movl $output, %eax           \n\t"
  //"leal 1(%eax), %edi          \n\t"
  "movl %0, %%eax           \n\t"
  "leal 1(%%eax), %%edi          \n\t"
  "movl %%esi, (%%edx)           \n\t"
  : "=&d" (output)     // output
  : "D" (input), "c" (ilength)   // input
  :    // modify
  );
}
 
//------ ф-ция преобразования ASCII строки из цифр в TBCD строку ------
// например, ASCII код 32 36 35 38 30 33 = TBCD код 26 58 03
void char2tbcd(char* input, int &ilength, void *SubNBuf)
{
 ilength = find_length(input); 
 __asm__ volatile (
  //"movl $ilength, %eax         \n\t" 
  //"movl (%eax), %ecx           \n\t"
  "movl %1, %%eax              \n\t" 
  "movl (%%eax), %%ecx         \n\t"
  
  //"movl $input, %eax           \n\t"
  "movl %2, %%eax              \n\t"
  
  //"movl $SubNBuf, %edi         \n\t"  
  "movl %0, %%edi              \n\t"
  
  "xorl %%ebx, %%ebx           \n\t"
 
"begin1:                       \n\t"
 
  "movb (%%eax), %%bl          \n\t"
  "shlb $4, %%bl               \n\t"
 
  "movb (%%eax,1), %%bh        \n\t"
  "andb $0x0f, %%bh            \n\t"
  "orb %%bh, %%bl              \n\t"
 
  "movb %%bl, (%%edi)          \n\t"
 
  "incl %%eax                  \n\t"
  "incl %%eax                  \n\t"
  "incl %%edi                  \n\t"
  "decl %%ecx                  \n\t"
  "decl %%ecx                  \n\t"
  "jnle begin1                 \n\t" // если не меньше или равно 0, т.е. >  =0
  : "=&D" (SubNBuf)   // output
  : "a" (ilength), "c" (input)      // input
  :         // modify
 );
 
 if(ilength>0) {
  ilength = ilength+1;
  ilength = ilength-1;
 } 
}
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) 
{
 const char *cp, *mp;
 while ((*string) && (*wild != '*'))    {
  if ((*wild != *string) && (*wild != '?')) return 0;
  wild++;
  string++;
 }
 while (*string)        {
  if (*wild == '*')  {
   if (!*++wild) return 1;
   mp = wild;
   cp = string+1;
  }
  else if ((*wild == *string) || (*wild == '?'))        {
   wild++;
   string++;
  }
  else  {
   wild = mp;
   string = cp++;
  }
 }
 while (*wild == '*')  wild++;
 return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
 int handle, handle2, bytes, iTBCDlen, iLength; 
 
 int ic_blength, ic_Nlength;
 void *xNsubsc, *xNsubsc2;
 char cTimebuf[32];  // для показа времени
 long iTimeValue;    // для показа времени
 
 int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи 
 
 
 
 bool bOdd;  // признак нечетного номера - другой способ поиска
 bool bNsub, bAsub;
 bool bMultyFiles = false, bFileNamesMatch = false;
 char *arg, *cbufsize = "1048576", *cSubsc, *cNsubsc, *cOddEven;
 char *sTime = " ";
 char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
 struct stat statbuf;
 int bufsize=0;
 
 void *buf;  // буфер для файла размером bufsize
 
 char *path = NULL;
 size_t size;
 DIR *dir;
 struct dirent *ent;
 using namespace std;
 
  vector<string> FileNameList;
 
 if(argc==1) {
  printf(         //ShowHelp:
  "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
  return 1;
 }
 printf("Input parameters are:\n");
 for(int i=1;i<argc;i++)  {    // цикл введенных параметров
  arg = argv[i];
  if(arg[0]=='-') {  // если начинается на '-'
  switch (arg[1]) {
   case 'f':
        cInputFileName = argv[i+1];
    iLength = find_length(cInputFileName);  
           // поиск и подсчет символа * внутри строки
          __asm__  volatile (
           "movb $'*', %%al                \n\t" // 0x2A
           "xorl %%ecx, %%ecx              \n\t"
           //"movl ($cInputFileName), %edi   \n\t"
           "movl (%1), %%edi   \n\t"
 
"ScasbInputFileName:                       \n\t"
           "incl %%ecx                     \n\t" // счетчик символов внутри cInputFileName
           "scasb                          \n\t"          
           "jz SymbolFound                 \n\t"
           "cmpb $0, (%%edi)   \n\t"
           "jz EndSearchSymbolInFileName   \n\t"
           "jmp ScasbInputFileName         \n\t"
 
"SymbolFound:                              \n\t"
           //"movb $1, $bMultyFiles          \n\t"
           //"movl $bMultyFiles, %eax        \n\t"
           
           //"movl %0, %%eax                 \n\t"                      
           //"movb $1, (%%eax)               \n\t"
           
           "movb $1, %0               \n\t"
           
           "movl %%ecx, %%ebx              \n\t" // сохраним позицию '*' внутри cInputFileName
 
"EndSearchSymbolInFileName:                \n\t" // ecx - позиция '*' внутри cInputFileName
       : "=&a" (bMultyFiles)   // output
       : "D" (cInputFileName)   // input
       : 
       );
                     
        if(bMultyFiles) {   // если много входных файлов
         path = getcwd(path, size);
         if ((dir = opendir(path)) == NULL) {
         perror("Unable to open directory");
     exit(1);
         }
         printf(" input files:\n");
         while ((ent = readdir(dir)) != NULL) {
           if(wildcmp(cInputFileName, ent->d_name)) {
           printf("  %s\n",ent->d_name);
                   FileNameList.insert(FileNameList.end(),ent->d_name);
           bFileNamesMatch = 1;
          }
         }
         if(!bFileNamesMatch) {
          printf("  no match.\n");
          return 1;
         }
 
         if (closedir(dir) != 0) {
          perror("Unable to close directory");
          return 1;
         }
        }
        else     // если один входной файл
                 if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
          printf(" input file - %s\n", cInputFileName);
                  FileNameList.insert(FileNameList.end(),cInputFileName);
         }
         else {
          perror("open input file failed, error");
          return 1;
         }
   break;
 
   case 'o':
        handle2 = open(argv[i+1], O_CREAT |O_APPEND);
    if (handle2 != -1)  {       // argv[i+1] - выходной файл
     printf(" output file - %s\n", argv[i+1]);
    }
    else {
     perror("create output file failed, error");
     return 1;
    }
   break;
   case 'b':
    cbufsize = argv[i+1];   // argv[i+1] - размер буфера
   break;
   case 'A':   // фильтр поиска аб-та А
        bFilter = 1;
        cSubsc = "A";
        bAsub = true;
        bNsub = false;
        cNsubsc = argv[i+1];
        break;
   case 'B':  // фильтр поиска аб-та Б
        bFilter = 1;
        cSubsc = "B";
        bAsub = false;
        bNsub = false;
        cNsubsc = argv[i+1];
   break;
   case 'N':  // фильтр поиска номера любого аб-та
    bFilter = 1;
        cSubsc = "N";
        bAsub = false;
        bNsub = true;
        cNsubsc = argv[i+1];
        break;
   case 'c':
    bCsv = true;
   break;
  } // конец если начинается на '-'
  } // конец switch
 }  // конец цикла
 
}
Без параметров работает.
При запуске с параметрами -f filename* в терминале выходит "Input parameters are:
Segmentation fault", что значит, вероятно, программа скомпилирована без ассемблерных вставок. Или ошибка в другом, но проследить ее я не могу.
При пошаговом исполнении с параметрами -f filename* после 230 строки, где стоит Breakpoint, Codelite сразу переходит на 50, т.е.
по ассемблерным вставкам он не проходит. Другого графического debugger-а у меня нет, Codelite после 50 строки выдает MessageBox:
Bash
1
2
 "Program Received signal SIGDEV
  Stack trace is available in the Call Stack tab"
Вот данные из Call Stack tab:
Bash
1
2
0  0x08048a59  find_length  /home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp  50
1  0x08048d21  main  /home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp  230
Вот лог debugger-а после MessageBox:
Bash
1
2
3
4
5
6
7
8
9
10
11
DEBUG>>*stopped,reason="exited-signalled",signal-name="SIGSEGV",signal-meaning="Segmentation fault"
DEBUG>>00000571-file-list-exec-source-file
DEBUG>>00000572-break-list
DEBUG>>00000571^done,line="50",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",macro-info="0"
DEBUG>>00000573-stack-list-frames
DEBUG>>00000572^done,BreakpointTable={nr_rows="3",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x08048d16",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="230",times="1",original-location="\"/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp:230"},bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="0x08048c50",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="188",times="1",original-location="\"/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp:188"},bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0x08048c50",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="188",times="1",original-location="main"}]}
DEBUG>>00000573^error,msg="No registers."
No registers.
DEBUG>>00000574-exec-step
DEBUG>>00000574^error,msg="The program is not being run."
The program is not being run.
Пока не ясно, копимлируются ассемблерные вставки или нет, скорее нет. Буду думать.

Добавлено через 33 секунды
Поменял... Компиляция, построение успешны.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#include <stdio.h>
#include <././sys/stat.h> 
#include <fcntl.h>
#include <streambuf> 
#include <dirent.h> 
#include <vector>
#include <string> 
#include <cstdlib> 
#include "Unit1.h" 
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0; 
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input)
{
 int length;
 __asm__  volatile ( 
     //"leal $input, %edi           \n\t"
     //"movl $input, %eax           \n\t"
     //"leal 1(%eax), %edi          \n\t"
     "movl %1, %%eax                 \n\t"
     "leal 1(%%eax), %%edi            \n\t"
     "xorl %%ecx, %%ecx              \n\t"
     "movl (%%edi), %%esi           \n\t" 
"nexch2:                          \n\t"
     "movb (%%esi), %%al            \n\t"
     "incl %%esi                   \n\t"
     "incl %%ecx                   \n\t" // длина
     "testb %%al, %%al               \n\t"
     "jnz nexch2                  \n\t"
     
     "decl %%ecx                   \n\t" // длина найдена
     //"leal $length, %edx          \n\t"
     //"movl $length, %eax          \n\t"
     //"leal 1(%eax), %edx          \n\t"
     "movl %0, %%eax         \n\t"
     "leal 1(%%eax), %%edx          \n\t"
     "movl %%ecx, (%%edx)           \n\t"
     : "=&d"(length)     // output
     : "D"(input)      // input
     :              // modified
  );
 return length;    // в eax 
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
int char2int  (char* input)
{
 int output, ilength;
 ilength = find_length(input);
  __asm__ (
  //"movl ($input), %edi           \n\t"
  //"movl ($ilength), %ecx       \n\t"
  "movl (%1), %%edi           \n\t"
  "movl (%2), %%ecx           \n\t"
 
  "xorl %%eax, %%eax              \n\t"
  "incl %%eax                   \n\t" // al =1
  "xorl %%esi, %%esi              \n\t" // esi =0 , [edi-ecx] = input
  "addl %%ecx, %%edi              \n\t"
  "decl %%edi                   \n\t" // [edi] = last char in string input = "1048576"
  "movb (%%edi), %%dl            \n\t"
  "andl $0x0f, %%edx             \n\t" // edx = last char of input without fist semibyte of ASCII
  "addl %%edx, %%esi              \n\t" // esi = ------"---------"--------
  "decl %%edi                   \n\t" //  [edi] = next char begining from end of input
  "decl %%ecx                   \n\t"
 
"begint:                     \n\t"
 
  "movb (%%edi), %%bl       \n\t"
  "andl $0x0f, %%ebx             \n\t" // ebx = next char begining from end of input without first semibyte
  "imull $10, %%eax              \n\t" // eax = eax * 10
  "imull %%eax, %%ebx             \n\t" // ebx = ebx * eax
  "addl %%ebx, %%esi              \n\t" // esi = esi + ebx * eax
  "decl %%edi                   \n\t" // [edi] = next char begining from end of input
  "decl %%ecx                   \n\t" // ecx = number of char in input begining from start
  "jnz begint                  \n\t" // number != 0 ?
 
  //"leal $output, %edx        \n\t"
  //"movl $output, %eax           \n\t"
  //"leal 1(%eax), %edi          \n\t"
  "movl %0, %%eax           \n\t"
  "leal 1(%%eax), %%edi          \n\t"
  "movl %%esi, (%%edx)           \n\t"
  : "=&d" (output)     // output
  : "D" (input), "c" (ilength)   // input
  :    // modify
  );
}
 
//------ ф-ция преобразования ASCII строки из цифр в TBCD строку ------
// например, ASCII код 32 36 35 38 30 33 = TBCD код 26 58 03
void char2tbcd(char* input, int &ilength, void *SubNBuf)
{
 ilength = find_length(input); 
 __asm__ volatile (
  //"movl $ilength, %eax         \n\t" 
  //"movl (%eax), %ecx           \n\t"
  "movl %1, %%eax              \n\t" 
  "movl (%%eax), %%ecx         \n\t"
  
  //"movl $input, %eax           \n\t"
  "movl %2, %%eax              \n\t"
  
  //"movl $SubNBuf, %edi         \n\t"  
  "movl %0, %%edi              \n\t"
  
  "xorl %%ebx, %%ebx           \n\t"
 
"begin1:                       \n\t"
 
  "movb (%%eax), %%bl          \n\t"
  "shlb $4, %%bl               \n\t"
 
  "movb (%%eax,1), %%bh        \n\t"
  "andb $0x0f, %%bh            \n\t"
  "orb %%bh, %%bl              \n\t"
 
  "movb %%bl, (%%edi)          \n\t"
 
  "incl %%eax                  \n\t"
  "incl %%eax                  \n\t"
  "incl %%edi                  \n\t"
  "decl %%ecx                  \n\t"
  "decl %%ecx                  \n\t"
  "jnle begin1                 \n\t" // если не меньше или равно 0, т.е. >  =0
  : "=&D" (SubNBuf)   // output
  : "a" (ilength), "c" (input)      // input
  :         // modify
 );
 
 if(ilength>0) {
  ilength = ilength+1;
  ilength = ilength-1;
 } 
}
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) 
{
 const char *cp, *mp;
 while ((*string) && (*wild != '*'))    {
  if ((*wild != *string) && (*wild != '?')) return 0;
  wild++;
  string++;
 }
 while (*string)        {
  if (*wild == '*')  {
   if (!*++wild) return 1;
   mp = wild;
   cp = string+1;
  }
  else if ((*wild == *string) || (*wild == '?'))        {
   wild++;
   string++;
  }
  else  {
   wild = mp;
   string = cp++;
  }
 }
 while (*wild == '*')  wild++;
 return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
 int handle, handle2, bytes, iTBCDlen, iLength; 
 
 int ic_blength, ic_Nlength;
 void *xNsubsc, *xNsubsc2;
 char cTimebuf[32];  // для показа времени
 long iTimeValue;    // для показа времени
 
 int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи 
 
 
 
 bool bOdd;  // признак нечетного номера - другой способ поиска
 bool bNsub, bAsub;
 bool bMultyFiles = false, bFileNamesMatch = false;
 char *arg, *cbufsize = "1048576", *cSubsc, *cNsubsc, *cOddEven;
 char *sTime = " ";
 char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
 struct stat statbuf;
 int bufsize=0;
 
 void *buf;  // буфер для файла размером bufsize
 
 char *path = NULL;
 size_t size;
 DIR *dir;
 struct dirent *ent;
 using namespace std;
 
  vector<string> FileNameList;
 
 if(argc==1) {
  printf(         //ShowHelp:
  "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
  return 1;
 }
 printf("Input parameters are:\n");
 for(int i=1;i<argc;i++)  {    // цикл введенных параметров
  arg = argv[i];
  if(arg[0]=='-') {  // если начинается на '-'
  switch (arg[1]) {
   case 'f':
        cInputFileName = argv[i+1];
    iLength = find_length(cInputFileName);  
           // поиск и подсчет символа * внутри строки
          __asm__  volatile (
           "movb $'*', %%al                \n\t" // 0x2A
           "xorl %%ecx, %%ecx              \n\t"
           //"movl ($cInputFileName), %edi   \n\t"
           "movl (%1), %%edi   \n\t"
 
"ScasbInputFileName:                       \n\t"
           "incl %%ecx                     \n\t" // счетчик символов внутри cInputFileName
           "scasb                          \n\t"          
           "jz SymbolFound                 \n\t"
           "cmpb $0, (%%edi)   \n\t"
           "jz EndSearchSymbolInFileName   \n\t"
           "jmp ScasbInputFileName         \n\t"
 
"SymbolFound:                              \n\t"
           //"movb $1, $bMultyFiles          \n\t"
           //"movl $bMultyFiles, %eax        \n\t"
           
           //"movl %0, %%eax                 \n\t"                      
           //"movb $1, (%%eax)               \n\t"
           
           "movb $1, %0               \n\t"
           
           "movl %%ecx, %%ebx              \n\t" // сохраним позицию '*' внутри cInputFileName
 
"EndSearchSymbolInFileName:                \n\t" // ecx - позиция '*' внутри cInputFileName
       : "=&a" (bMultyFiles)   // output
       : "D" (cInputFileName)   // input
       : 
       );
                     
        if(bMultyFiles) {   // если много входных файлов
         path = getcwd(path, size);
         if ((dir = opendir(path)) == NULL) {
         perror("Unable to open directory");
     exit(1);
         }
         printf(" input files:\n");
         while ((ent = readdir(dir)) != NULL) {
           if(wildcmp(cInputFileName, ent->d_name)) {
           printf("  %s\n",ent->d_name);
                   FileNameList.insert(FileNameList.end(),ent->d_name);
           bFileNamesMatch = 1;
          }
         }
         if(!bFileNamesMatch) {
          printf("  no match.\n");
          return 1;
         }
 
         if (closedir(dir) != 0) {
          perror("Unable to close directory");
          return 1;
         }
        }
        else     // если один входной файл
                 if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
          printf(" input file - %s\n", cInputFileName);
                  FileNameList.insert(FileNameList.end(),cInputFileName);
         }
         else {
          perror("open input file failed, error");
          return 1;
         }
   break;
 
   case 'o':
        handle2 = open(argv[i+1], O_CREAT |O_APPEND);
    if (handle2 != -1)  {       // argv[i+1] - выходной файл
     printf(" output file - %s\n", argv[i+1]);
    }
    else {
     perror("create output file failed, error");
     return 1;
    }
   break;
   case 'b':
    cbufsize = argv[i+1];   // argv[i+1] - размер буфера
   break;
   case 'A':   // фильтр поиска аб-та А
        bFilter = 1;
        cSubsc = "A";
        bAsub = true;
        bNsub = false;
        cNsubsc = argv[i+1];
        break;
   case 'B':  // фильтр поиска аб-та Б
        bFilter = 1;
        cSubsc = "B";
        bAsub = false;
        bNsub = false;
        cNsubsc = argv[i+1];
   break;
   case 'N':  // фильтр поиска номера любого аб-та
    bFilter = 1;
        cSubsc = "N";
        bAsub = false;
        bNsub = true;
        cNsubsc = argv[i+1];
        break;
   case 'c':
    bCsv = true;
   break;
  } // конец если начинается на '-'
  } // конец switch
 }  // конец цикла
 
}
Без параметров работает.
При запуске с параметрами -f filename* в терминале выходит "Input parameters are:
Segmentation fault", что значит, вероятно, программа скомпилирована без ассемблерных вставок. Или ошибка в другом, но проследить ее я не могу.
При пошаговом исполнении с параметрами -f filename* после 230 строки, где стоит Breakpoint, Codelite сразу переходит на 50, т.е.
по ассемблерным вставкам он не проходит. Другого графического debugger-а у меня нет, Codelite после 50 строки выдает MessageBox:
Bash
1
2
 "Program Received signal SIGDEV
  Stack trace is available in the Call Stack tab"
Вот данные из Call Stack tab:
Bash
1
2
0  0x08048a59  find_length  /home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp  50
1  0x08048d21  main  /home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp  230
Вот лог debugger-а после MessageBox:
Bash
1
2
3
4
5
6
7
8
9
10
11
DEBUG>>*stopped,reason="exited-signalled",signal-name="SIGSEGV",signal-meaning="Segmentation fault"
DEBUG>>00000571-file-list-exec-source-file
DEBUG>>00000572-break-list
DEBUG>>00000571^done,line="50",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",macro-info="0"
DEBUG>>00000573-stack-list-frames
DEBUG>>00000572^done,BreakpointTable={nr_rows="3",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x08048d16",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="230",times="1",original-location="\"/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp:230"},bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="0x08048c50",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="188",times="1",original-location="\"/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp:188"},bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0x08048c50",func="main",file="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",fullname="/home/avatar/projects/codelite/InsertToCsvString/InsertToCsvString.cpp",line="188",times="1",original-location="main"}]}
DEBUG>>00000573^error,msg="No registers."
No registers.
DEBUG>>00000574-exec-step
DEBUG>>00000574^error,msg="The program is not being run."
The program is not being run.
Пока не ясно, компилируются ассемблерные вставки или нет, скорее нет. Буду думать.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
17.09.2011, 13:16 10
Из всего этого, я не понял, в чём вопрос состоит. Если в том, компилируются ассемблерные вставки, или нет, то сделай дизассемблер функций, в которых эти вставки, и там всё увидишь. Я слабо разбираюсь в intel'овской системе команд, но по-моему в этом коде нет ни одной веской причины для использования вставок. Их можно взять и тупо на Си переписать, коли не разбираешься в том, как gnu'тые вставки правильно писать
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
17.09.2011, 17:32  [ТС] 11
Из всего этого, я не понял, в чём вопрос состоит.
Не смог отредактировать сообщение после отправки - нужно читать последнее добавление.
сделай дизассемблер функций
Уже сделал. Ассемблерные вставки в программе есть.
"Ошибка сегментации (англ. Segmentation fault или сокращённо segfault) — ошибка программного обеспечения, возникающая при попытке обращения к недоступным для записи участкам памяти либо при попытке изменения памяти запрещённым способом." - из ru.wikipedia.org. Ассемблерный листинг из main:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
00000D08  034304            add eax,[ebx+0x4]
00000D0B  8B00              mov eax,[eax]
00000D0D  8945C8            mov [ebp-0x38],eax
00000D10  8B45C8            mov eax,[ebp-0x38]
00000D13  890424            mov [esp],eax               ; cInputFileName
00000D16  E829FDFFFF        call dword 0xa44            ; iLength = find_length(cInputFileName);
00000D1B  89458C            mov [ebp-0x74],eax          ; iLength
00000D1E  8B45C8            mov eax,[ebp-0x38]
00000D21  89C7              mov edi,eax
00000D23  B02A              mov al,0x2a
00000D25  31C9              xor ecx,ecx
00000D27  8B3F              mov edi,[edi]               ; "movl (%1), %%edi
00000D29  41                inc ecx
00000D2A  AE                scasb
00000D2B  7407              jz 0xd34
00000D2D  803F00            cmp byte [edi],0x0
00000D30  7406              jz 0xd38
00000D32  EBF5              jmp short 0xd29
00000D34  B001              mov al,0x1                  ; "movb $1, %0 
00000D36  89CB              mov ebx,ecx
00000D38  8845AE            mov [ebp-0x52],al           ; bMultyFiles
00000D3B  807DAE00          cmp byte [ebp-0x52],0x0     ; if(bMultyFiles)
00000D3F  0F84D4010000      jz dword 0xf19
00000D45  8B45D8            mov eax,[ebp-0x28]          ; {
00000D48  89442404          mov [esp+0x4],eax
00000D4C  8B45D4            mov eax,[ebp-0x2c]
00000D4F  890424            mov [esp],eax
00000D52  E895FBFFFF        call dword 0x8ec
find_length:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
00000A44  55                push ebp
00000A45  89E5              mov ebp,esp
00000A47  57                push edi
00000A48  83EC10            sub esp,byte +0x10
00000A4B  8B4508            mov eax,[ebp+0x8]
00000A4E  89C7              mov edi,eax
00000A50  8D5701            lea edx,[edi+0x1]       ; "leal 1(%1), %%edx 
00000A53  31C9              xor ecx,ecx
00000A55  8B37              mov esi,[edi]
00000A57  8A06              mov al,[esi]
00000A59  46                inc esi
00000A5A  41                inc ecx
00000A5B  84C0              test al,al
00000A5D  75F8              jnz 0xa57
00000A5F  49                dec ecx
00000A60  8D5201            lea edx,[edx+0x1]       ; leal 1(%0), %%edx
00000A63  890A              mov [edx],ecx
00000A65  89D0              mov eax,edx
00000A67  8945F8            mov [ebp-0x8],eax
00000A6A  8B45F8            mov eax,[ebp-0x8]
00000A6D  83C410            add esp,byte +0x10
00000A70  5F                pop edi
00000A71  5D                pop ebp
00000A72  C3                ret
Пошаговое выполнение step into:
C++
1
2
241 iLength = find_length(cInputFileName);  
52   );   // конец find_length
DEBUG>>*stopped,reason="exited-signalled",signal-name="SIGSEGV",signal-meaning="Segmentation fault"
Поищу причину ошибки сегментации. И попробую найти другой debugger.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
17.09.2011, 17:55 12
Segmentation fault возникает в тех случаях, когда произошло обращение по некорректному адресу. Т.е. программа у тебя совершила недопустимую операцию обращения в память. Проще всего скомпилить всю программу с опцией "-g" и запустить из-под отладчика (например, gdb). В момент падения в отладчике напиши "bt", он тебе покажет стек падения.

Можешь печаталку стека прямо к программе прикрутить: Встроенная в программу печать стека при помощи внешнего отладчика

Добавлено через 1 минуту
Хотя в твоём случае помимо печаталки стека надо ещё и обработчик сигналов настраивать, так что лучше ручками из-под отладчика запусти
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
30.09.2011, 14:13  [ТС] 13
Ошибка была в ассемблерном коде find_length. Исправленный работающий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int find_length(char* input)
{
 int length;
 __asm__  ( 
     "xorl %%ecx, %%ecx            \n\t"
"nexch2:                           \n\t"
     "movb (%%edi), %%al           \n\t"
     "incl %%edi                   \n\t"
     "incl %%ecx                   \n\t" // длина
     "testb %%al, %%al             \n\t"
     "jnz nexch2                   \n\t"
     
     "decl %%ecx                   \n\t" // длина найдена
     : "=&c"(length)     // output
     : "D"(input)        // input
  );
 return length;          // в eax 
}
Ошибка выпадала на "movb (%%esi), %%al \n\t".
Избавился также от "movl (%%edi), %%esi \n\t" , вместо esi использюовал edi.
Ушел от обозначений %0, %1.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
30.09.2011, 14:33 14
Цитата Сообщение от Remontik Посмотреть сообщение
Ушел от обозначений %0, %1
И к чему пришёл? К тому, что ассемблерная вставка вообще никак не связана с языковыми переменными. Сегодня звёзды стоят так, что input у тебя действительно легло на edx, а length - на eax. А на другой версии компилятора не факт, что будет так. Т.е. у тебя этот код работает только благодяря тому, что звёзды должным образом стоят
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
02.10.2011, 10:15  [ТС] 15
Заменил вместо регистров ecx, edi - %0, %1:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#include <stdio.h>
#include <././sys/stat.h> 
#include <fcntl.h>
#include <streambuf> 
#include <dirent.h> 
#include <vector>
#include <string> 
#include <cstdlib> 
#include "Unit1.h" 
 
bool bFind = false, bCsv = false, bFilter = false, bCDRHeader = false;
bool bCDRExchangeID = false, bCDR_SWversion = false, bCDR_FileName = false;
int iInterFieldSize = 0;  // число байт между первыми полями A3
int bufPos = 0;  // текущая позиция в буфере чтения из файла =0
int iFilePos = 0; // текущая позиция в файле =0
int findRecSize =0;   // размер найденной записи
int iSpaceNumber = 0;
int iFoundRecordsNumber = 1; //, iCDRHeaderLength;
long int iFileSize =0; 
 
//------------- ф-ция нахождения длины строки ------------------
int find_length(char* input)
{
 int length;
  __asm__  ( 
     "xorl %0, %0            \n\t"
"nexch2:                           \n\t"
     "movb (%1), %%al           \n\t"
     "incl %1                   \n\t"
     "incl %0                   \n\t" // длина
     "testb %%al, %%al             \n\t"
     "jnz nexch2                   \n\t"
     
     "decl %0                   \n\t" // длина найдена
     : "=c"(length)     // output
     : "D"(input)        // input
  );
 return length;    // в eax 
}
 
//------- ф-ция преобразования строки из 10-тичных цифр в целое число ---------
 
 
 
 
 
//------------------- функция сравнение строки с шаблоном -------------------
 
int wildcmp(const char *wild, const char *string) 
{
 const char *cp, *mp;
 while ((*string) && (*wild != '+'))    {
  if ((*wild != *string) && (*wild != '?')) return 0;
  wild++;
  string++;
 }
 while (*string)        {
  if (*wild == '+')  {
   if (!*++wild) return 1;
   mp = wild;
   cp = string+1;
  }
  else if ((*wild == *string) || (*wild == '?'))        {
   wild++;
   string++;
  }
  else  {
   wild = mp;
   string = cp++;
  }
 }
 while (*wild == '+')  wild++;
 return !*wild;
}
 
//-------------------------- ГЛАВНАЯ ФУНКЦИЯ ---------------------------------
 
int main(int argc, char* argv[])
 
{
 int handle, handle2, bytes, iTBCDlen, iLength; 
 
 int ic_blength, ic_Nlength;
 void *xNsubsc, *xNsubsc2;
 char cTimebuf[32];  // для показа времени
 long iTimeValue;    // для показа времени
 
 int recordsize = 0x100;  // размер find_rec_buf =256 байт для найденной записи 
 
 
 
 bool bOdd;  // признак нечетного номера - другой способ поиска
 bool bNsub, bAsub;
 bool bMultyFiles = false, bFileNamesMatch = false;
 char *arg;
char *cbufsize = "1048576";
char *cSubsc, *cNsubsc, *cOddEven;
 char *sTime = " ";
 char *cInputFileName ="11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111\
 11111111111111111111111111111111111111";
 
 struct stat statbuf;
 int bufsize=0;
 
 void *buf;  // буфер для файла размером bufsize
 
 //char *path = NULL;
 char path1[256]; 
 //size_t size;
 char *filedir;
 DIR *dir;
 struct dirent *ent;
 using namespace std;
 int i=1;
 
  vector<string> FileNameList;
 
 if(argc==1) {
  printf(         //ShowHelp:
  "Q.825 CDR decoder and filter program, version 2.3 (build 40)\n\
Usage:\n\n\
   cdrdec -f inputfile arguments > outputfile\n\n");
 
  return 1;
 }
 printf("Input parameters are:\n");
 for(i; i<argc; i++)  {    // цикл введенных параметров  ebx=argc
  arg = argv[i];
  if(arg[0]=='-') {  // если начинается на '-'
  switch (arg[1]) {
   case 'f':
        i++;
        cInputFileName = argv[i];
    iLength = find_length(cInputFileName);  
    printf(" Length of file name: %d\n", iLength);
           // поиск и подсчет символа * внутри строки
    __asm__  (
           "movb $'+', %%al                \n\t" // '*' = 0x2A
           "xorl %%ecx, %%ecx              \n\t"
 
     "ScasbInputFileName:                  \n\t"
           "incl %%ecx                     \n\t" // счетчик символов внутри cInputFileName
           "scasb                          \n\t"          
           "jz SymbolFound                 \n\t" 
           "xorb %%dl, %%dl                \n\t"          
           "cmpb $0, (%%edi)   \n\t"
           "jz EndSearchSymbolInFileName   \n\t"
           "jmp ScasbInputFileName         \n\t"  
 
     "SymbolFound:                         \n\t"
           "xorb %%dl, %%dl                \n\t"    
           "incb %%dl                      \n\t"           
           //"movb $0, -1(%%edi)             \n\t"  // ноль вместо '+'
           //"movl %%ecx, %%ebx              \n\t" // сохраним позицию '+' внутри cInputFileName
 
     "EndSearchSymbolInFileName:           \n\t" // ecx - позиция '+' внутри cInputFileName
       : "=d" (bMultyFiles)           // output
       : "D" (cInputFileName)         // input        
       );  
       
    printf(" Multy files: %d\n", bMultyFiles);     
               
        if(bMultyFiles==1) {   // если много входных файлов         
         printf(" Input file name: %s\n", cInputFileName);          
         //path = getcwd( path, size);
         getcwd(path1, 256);
         printf(" Directory is: %s\n", path1);
         if ((dir = opendir(path1)) == NULL) {
         perror("Unable to open directory");
     exit(1);
         }
         printf(" input files:\n");
         while ((ent = readdir(dir)) != NULL) {
            filedir = ent->d_name;
           if(wildcmp(cInputFileName, filedir)) {
           printf("  %s\n",ent->d_name);
                   FileNameList.insert(FileNameList.end(),ent->d_name);
           bFileNamesMatch = 1;
          }
         }
         if(!bFileNamesMatch) {
          printf("  no match.\n");
          return 1;
         }
 
         if (closedir(dir) != 0) {
          perror("Unable to close directory");
          return 1;
         }
        }     // конец если много входных файлов
        else     // если один входной файл   
                 if ((handle = open(cInputFileName, O_RDONLY)) != -1) {
          printf(" input file: %s\n", cInputFileName);
                  FileNameList.insert(FileNameList.end(),cInputFileName);
         }
         else {
          perror("open input file failed, error");
          return 1;
         }
   break;
 
   case 'o':
        handle2 = open(argv[i+1], O_CREAT |O_APPEND);
    if (handle2 != -1)  {       // argv[i+1] - выходной файл
     printf(" output file - %s\n", argv[i+1]);
    }
    else {
     perror("create output file failed, error");
     return 1;
    }
   break;
   case 'b':
    cbufsize = argv[i+1];   // argv[i+1] - размер буфера
   break;
   case 'A':   // фильтр поиска аб-та А
        bFilter = 1;
        cSubsc = "A";
        bAsub = true;
        bNsub = false;
        cNsubsc = argv[i+1];
        break;
   case 'B':  // фильтр поиска аб-та Б
        bFilter = 1;
        cSubsc = "B";
        bAsub = false;
        bNsub = false;
        cNsubsc = argv[i+1];
   break;
   case 'N':  // фильтр поиска номера любого аб-та
    bFilter = 1;
        cSubsc = "N";
        bAsub = false;
        bNsub = true;
        cNsubsc = argv[i+1];
        break;
   case 'c':
    bCsv = true;
   break;
  } // конец если начинается на '-'
  } // конец switch
 }  // конец цикла
 
}
Работает:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
avatar@crunchbang:~/projects/InsertToCsvString$ ./InsertToCsvString -f InsertToCsvString+
Input parameters are:
 Length of file name: 18
 Multy files: 1
 Input file name: InsertToCsvString+
 Directory is: /home/avatar/projects/InsertToCsvString
 input files:
  InsertToCsvString_old2.cpp
  InsertToCsvString_g++_001.log
  InsertToCsvString
  InsertToCsvString-old.cpp
  InsertToCsvString.o
  InsertToCsvString_geany_000.log
  InsertToCsvString.log
  InsertToCsvString_old.cpp
  InsertToCsvString_ndisasm_intel.asm
  InsertToCsvString-old
  InsertToCsvString_geany_001.log
  InsertToCsvString_g++_000.log
  InsertToCsvString.cpp
  InsertToCsvString_gcc.log
  InsertToCsvString_dbg
  InsertToCsvString.txt
  InsertToCsvString_mess.cpp
  InsertToCsvString_older.cpp
  InsertToCsvString.ii
  InsertToCsvString.s
avatar@crunchbang:~/projects/InsertToCsvString$
Только в чем разница, пока не времени нет думать. Подумаю. Спасибо.
0
3 / 3 / 1
Регистрация: 12.09.2011
Сообщений: 17
07.10.2011, 14:50  [ТС] 16
Сравнил 2 файла .s для двух коротких тестовых файлов .cpp с ассемб. вставками с %0 и без.
без:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
int find_length(char* input)
{
 int length;
 __asm__  ( 
     "xorl %%ecx, %%ecx            \n\t"
"nexch2:                           \n\t"
     "movb (%%edi), %%al           \n\t"
     "incl %%edi                   \n\t"
     "incl %%ecx                   \n\t" // длина
     "testb %%al, %%al             \n\t"
     "jnz nexch2                   \n\t"
     
     "decl %%ecx                   \n\t" // длина найдена
     : "=c"(length)     // output
     : "D"(input)        // input
  );
 return length;          // в eax 
}
 
int main (int argc, char* argv[])  {
 char *cIn;
 int iLcIn;
 if(argc>1) cIn = argv[1];
 iLcIn = find_length(cIn);
 printf("Length of %s: %d\n", cIn, iLcIn);
}
с 0%:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
int find_length(char* input)
{
 int length;
  __asm__  ( 
     "xorl %0, %0            \n\t"
"nexch2:                           \n\t"
     "movb (%1), %%al           \n\t"
     "incl %1                   \n\t"
     "incl %0                   \n\t" // длина
     "testb %%al, %%al             \n\t"
     "jnz nexch2                   \n\t"
     
     "decl %0                   \n\t" // длина найдена
     : "=c" (length)     // output
     : "D" (input)        // input
  );
 return length;    // в eax 
}
 
int main (int argc, char* argv[])  {
 char *cIn;
 int iLcIn;
 if(argc>1) cIn = argv[1];
 iLcIn = find_length(cIn);
 printf("Length of %s: %d\n", cIn, iLcIn);
}
Разницы нет.

В продолжение решения ошибки "undefined reference to" при компиляции, связанной с вызовом своей функции из ассемблерной вставки.
Вот тестовый код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int iA, iB;
 
int adding(int i1, int i2) {
 return i1 = i1 + i2;
}
 
int main() {
 iA = 4;  
 iB = 5;  
 printf("iA: %d, iB: %d\n", iA, iB);
 __asm__  (
    "pushl $iA        \n\t"
    "pushl $iB        \n\t"
    "call adding      \n\t"
    "movl %eax, iA  "    
 );
 printf("iA + iB = %d\n", iA); 
}
При компиляции выходит ошибка:
Bash
1
2
3
4
avatar@crunchbang:~/projects/cdrdec$ g++ subadd.cpp -o subadd
/tmp/ccHVkPFo.o: In function `main':
subadd.cpp:(.text+0x55): undefined reference to `adding'
collect2: ld returned 1 exit status
Решение нашел:
нужно добавить в начало кода до int main следующее объявление:
C++
1
extern "C" int adding(int i1, int i2);
также его можно добавить в заголовок.
0
07.10.2011, 14:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.10.2011, 14:50
Помогаю со студенческими работами здесь

Inline assembler mingw
Добрый вечер ув. пользователи форума. Возникла проблема с ассемблером, и его реализацией в mingw....

Как исправить код? / Inline assembler
#include &lt;stdio.h&gt; int main(int argc, char** argv ) { int aa; int bb; aa = 42; bb =...

Обращение к переменным объекта с использованием указателя this из inline assembler
Мне нужно написать класс на С++ с учетом возможности ввода количества столбцов и строк матрицы....

Работа со строками. Удалить из строки символы в скобках inline assembler.
Удалить из строки символы в скобках inline assembler. Подскажите в какую сторону копать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru