Форум программистов, компьютерный форум, киберфорум
Наши страницы

Assembler для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Saraharas
0 / 0 / 0
Регистрация: 14.10.2014
Сообщений: 53
#1

Ассемблерная вставка на Си, ошибка Run-Time check failure #0 - Assembler

01.06.2015, 00:05. Просмотров 967. Ответов 22
Метки нет (Все метки)

Здравствуйте! Помогите, пожалуйста, с реализацией ассемблерной вставки в Си. У меня есть программа на Си, нужно написать такую же программу в виде ассемблерной вставки (использую ассемблерный листинг сишной версии). Компилируется без ошибок, но потом выдает ошибку "Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention" Подскажите, пожалуйста, как исправить ошибку. Прилагаю Сишную программу и ее вариант на ассемблере
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
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<memory.h>
#include <time.h>
 
const int max_sqrt_n = 100000;
const int S = 100000;
bool nprime[max_sqrt_n], bloc[S];
int primes[max_sqrt_n], cnt;
 
int main()
{
    int n;
    scanf("%d", &n);
    clock_t start_time;
    start_time = clock();
    int nsqrt = (int)sqrt((double)n);
    for (int i = 2; i <= nsqrt; ++i)
        if (!nprime[i])
        {
            primes[cnt++] = i;
            if (i <= n)
                for (int j = i * i; j <= nsqrt; j += i)
                    nprime[j] = true;
        }
    int result = 0;
    for (int k = 0, maxk = n / S; k <= maxk; ++k)
    {
        memset(bloc, 0, sizeof bloc);
        int start = k * S;
        for (int i = 0; i < cnt; ++i)
        {
            int start_idx = (start + primes[i] - 1) / primes[i];
            int temp = start_idx < 2 ? 2 : start_idx;
            int j = temp * primes[i] - start;
            for (; j < S; j += primes[i]) bloc[j] = true;
        }
        if (k == 0) bloc[0] = bloc[1] = true;
        for (int i = 0; i < S && start + i <= n; ++i) if (!(bloc[i])) ++result;
    }
    start_time = clock() - start_time;
    printf("%d %.4lfs", result, (double)start_time / CLOCKS_PER_SEC);
    return 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
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
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include <time.h>
#include <memory.h>
#include <stdbool.h>
#pragma function(memset)
const int max_sqrt_n = 100000;
const int S = 100000;
bool nprime[max_sqrt_n];
bool bloc[S];
int primes[max_sqrt_n], cnt;
const char fmt[] = "%d";
const char fmt1[] = " %.4lfs";
 
int main()
{
    long long int c = CLOCKS_PER_SEC;
    int n, nsqrt, k, maxk;
    int result = 0;
    clock_t start_time;
 
    _asm
    {
        lea eax, n
            push    eax
            push    OFFSET fmt
            call    DWORD PTR scanf
            add esp, 8
 
            call  dword ptr clock
            mov start_time, eax
 
            finit
            fild n
            fsqrt
            fist nsqrt
            mov edx, nsqrt
            mov ecx, 2
            cmp edx, ecx
            jl  LN57
            mov edi, cnt
 
        LL22 : cmp  nprime[ecx], 0
               jne  LN21
 
               mov  eax, ecx
               mov  primes[edi * 4], ecx
               imul eax, ecx
               inc  edi
               cmp  eax, edx
               jg   LN21
 
 
               mov  eax, ecx
               imul eax, ecx
               cmp  eax, edx
               jg   LN21
 
           LL17 :
 
        mov nprime[eax], 1
            add eax, ecx
            cmp eax, edx
            jle LL17
 
        LN21 :
 
        inc ecx
            cmp ecx, edx
            jle LL22
 
 
            mov cnt, edi
            mov edi, n
 
        LN57 :
        mov eax, 351843721
            xor esi, esi
            imul    edi
            mov ebx, esi
            mov result, esi
            sar edx, 13
            mov eax, edx
            mov k, ebx
            shr eax, 31
            add eax, edx
            mov maxk, eax
            js  LN12
 
        LL14 :
        push    100000
            push    0
            push offset bloc
            call memset
            xor edi, edi
            imul    ebx, ebx, 100000
            add esp, 12
            cmp cnt, edi
            jle LN9
            mov esi, cnt
 
        LL11 :
 
        mov ecx, primes[edi * 4]
            lea eax, [ebx - 1]
            add eax, ecx
            cdq
            idiv    ecx
 
            mov edx, 2
            cmp eax, 2
            cmovl   eax, edx
 
            imul    eax, ecx
            sub eax, ebx
            cmp eax, 100000
            jge LN10
 
        LL8 :
        mov bloc[eax], 1
            add eax, ecx
            cmp eax, 100000
            jl  LL8
        LN10 :
        inc edi
            cmp edi, esi
            jl  LL11
            mov esi, result
 
        LN9 :
        cmp k, 0
            jne LN5
            mov bloc, 257
        LN5 :
            mov edx, n
            mov edi, ebx
            xor ecx, ecx
            sub edi, OFFSET bloc
 
        LL4 :
        lea eax, bloc[ecx]
            add eax, edi
            cmp eax, edx
            jg  LN13
            cmp bloc[ecx], 0
            jne LN3
            inc esi
        LN3 :
        lea eax, [ebx + 1]
            add eax, ecx
            cmp eax, edx
            jg  LN13
            cmp bloc[ecx + 1], 0
            jne LN43
            inc esi
        LN43 :
        lea eax, [ebx + 2]
            add eax, ecx
            cmp eax, edx
            jg LN13
            cmp bloc[ecx + 2], 0
            jne LN45
            inc esi
        LN45 :
        lea eax, [ebx + 3]
            add eax, ecx
            cmp eax, edx
            jg  LN13
            cmp bloc[ecx + 3], 0
            jne LN47
            inc esi
        LN47 :
        lea eax, [ebx + 4]
            add eax, ecx
            cmp eax, edx
            jg LN13
            cmp bloc[ecx + 4], 0
            jne LN49
            inc esi
        LN49 :
        add ecx, 5
            cmp ecx, 100000
            jl  LL4
 
        LN13 :
        mov ebx, k
            inc ebx
            mov result, esi
            mov k, ebx
            cmp ebx, maxk
            jle LL14
 
        LN12 :
 
        call    DWORD PTR clock
            mov ebx, start_time
            sub eax, ebx
            sub esp, 8
            mov start_time, eax
            fild    dword ptr start_time
            fdiv    dword ptr c
            fstp    QWORD PTR[esp]
            push     offset fmt
            call    DWORD PTR printf
            sub esi, 1
            push    esi
            push    OFFSET fmt1
            call    DWORD PTR printf
            add esp, 16
    }
 
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.06.2015, 00:05
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Ассемблерная вставка на Си, ошибка Run-Time check failure #0 (Assembler):

Run-time check failure #0 - Assembler
Добрый день. Как понимаю, ошибка возникла вследствие неверного esp. Ниже используемый код. После выхода из фции asm вылетает Run-Time Check...

ассемблерная вставка - Assembler
Здравствуйте, в задании нужно было написать код на С и сделать ассемблерную вставку. &quot;Дана длина отрезка в метрах,...

Ассемблерная вставка на Си - Assembler
Задана следующая задача : дана длина отрезка в метрах, сантиметрах,миллиметрах. Перевести в футы и дюймы. 1 дюйм = 2,54 см. 1 фут =...

Ассемблерная вставка, С++ - Assembler
Доброе утро. Достался &quot;по наследству&quot; код __declspec(dllexport) int __stdcall NtUserPostMes(HWND hWnd, unsigned int Msg, WPARAM...

ассемблерная вставка - Assembler
здравствуйте, подскажите пожалуйста алгоритм для моей задачи: нужно написать в порядке возрастания числа, в двоичном представлении которых...

Ассемблерная вставка в C++ - Assembler
Приветствую,нужен направляющий пинок по решению задачки) задача в следующем Разделить массив на две части, поместив в первую эле-менты,...

22
maxillion
273 / 183 / 38
Регистрация: 25.12.2012
Сообщений: 616
03.06.2015, 14:24 #16
Я про то что в асм вставке у ТС используются локальные переменные, и если бы где то в начале изменили EBP то код бы точно не работал. Да и вообще нельзя полагаться на то какой регистр использует компилятор для обращения к локальным переменным, это вроде как не где не документировано. Вдруг это ESI, который использует ТС в своём коде.
0
Ethereal
2864 / 1204 / 148
Регистрация: 17.02.2013
Сообщений: 1,998
03.06.2015, 14:28 #17
Цитата Сообщение от maxillion Посмотреть сообщение
То что что выполняется до main написано на Visual c++, а он требует что бы (The compiler generates prolog and epilog code to save and restore the ESI, EDI, EBX, and EBP registers, if they are used in the function.) - из msdn.
Означает ли это то, что на входе в main() регистры esi edi ebx будут сохранены, а на выходе из main() восстановлены, а значит их внутри main() похабить можно ?

Добавлено через 2 минуты
Цитата Сообщение от maxillion Посмотреть сообщение
Я про то что в асм вставке у ТС используются локальные переменные, и если бы где то в начале изменили EBP то код бы точно не работал.
В такой формулировке - это святая истина.
1
maxillion
273 / 183 / 38
Регистрация: 25.12.2012
Сообщений: 616
03.06.2015, 14:28 #18
Это решает компилятор, если он использует ESI, EDI, EBX, EBP то должен сохранить и восстановить.
0
Ethereal
2864 / 1204 / 148
Регистрация: 17.02.2013
Сообщений: 1,998
03.06.2015, 14:34 #19
Слушай, у тебя под рукой этот Visual C++ есть ? У меня нет. Не мог бы ты скомпилять пример ТС с ассемблерной вставкой до EXE-шника и архивом прицепить к сообщению. Пора уже вердикт вынести где именно у него косяк и закрыть тему.
1
maxillion
273 / 183 / 38
Регистрация: 25.12.2012
Сообщений: 616
03.06.2015, 14:46 #20
Цитата Сообщение от Ethereal Посмотреть сообщение
Слушай, у тебя под рукой этот Visual C++ есть ? У меня нет. Не мог бы ты скомпилять пример ТС с ассемблерной вставкой до EXE-шника и архивом прицепить к сообщению. Пора уже вердикт вынести где именно у него косяк и закрыть тему.
Очень смешно, да пускай хоть компилятор от Васи Пупкина, соглашение о вызовах (x86 calling conventions) должно быть одинаковым везде, а иначе будет не понятно что.
0
Ethereal
2864 / 1204 / 148
Регистрация: 17.02.2013
Сообщений: 1,998
03.06.2015, 15:05 #21
Нету таких x86 calling conventions, свойственных всем x86. В том-же Турбо Паскале можешь пахабить регистр BX в любой момент. И это тоже calling convention ... конкретного компилятора.
Сохранение ebx esi edi ebp и флаг направления в ноль - это соглашения Виндоуз.
1
maxillion
273 / 183 / 38
Регистрация: 25.12.2012
Сообщений: 616
03.06.2015, 15:09 #22
Цитата Сообщение от Ethereal Посмотреть сообщение
Сохранение ebx esi edi ebp и флаг направления в ноль - это соглашения Виндоуз.
Calling conventions gcc
0
Ethereal
2864 / 1204 / 148
Регистрация: 17.02.2013
Сообщений: 1,998
03.06.2015, 15:21 #23
Чо сказать-то хотел ? Что еще не было Виндоуз, а уже был GCC с такими вот соглашениями ? Или что ссылка на GCC calling convention доказывает, что никаких соглашений конретных компиляторов не существует ?
1
03.06.2015, 15:21
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.06.2015, 15:21
Привет! Вот еще темы с ответами:

Ассемблерная вставка в С++ - Assembler
Привет, есть простая функция по обмену двух переменных, механизм обмена реализован через асм. вставку. В самой функции переменные...

Ассемблерная вставка - Assembler
На Си создать с помощью датчика случайных чисел(random) файл F1 с целочисленными матрицами 2х3. Из файла F1 получить файл F2, содержащий...

Ассемблерная вставка на C++ - Assembler
Делаю программу на С++ с использованием ассемблерных вставок. При использовании прерываний выдает ошибку сегментации: asm(&quot;movb $0x10,...

Ассемблерная вставка - Assembler
Приветствую! Есть небольшая проблемка, во вставке должно считаться значение выражения (A * X^3 + B * X^2 + C div X + D div X) div X, все...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.