Страницы

Поиск по вопросам

вторник, 2 апреля 2019 г.

Крашится программа с ассемблерной вставкой

При выполнении этого кода получаю следующую ошибку:
Run-Time Check Failure #2 - Stack around the variable 'C' was corrupted.
Сам код:
#include #include #include
#define SIZE_ROW 1000 #define SIZE_COLUMN 8
#ifndef BYTE #define BYTE typedef unsigned char byte; #endif
void init(byte* A) { for (long long int i = 0; i < (SIZE_ROW * SIZE_COLUMN); i++) { A[i] = rand() + 5*i + 9; } }
void MyAsm(byte* A, byte* B, byte* C, byte k) {
byte lastRes = 0;
_asm { pusha
;init mov ecx, SIZE_ROW*SIZE_COLUMN xor esi, esi
loop1: mov bl, byte ptr B[esi] mov al, k mov dl, byte ptr C[esi]
imul dl ;k*C add al, bl ;b+k*C
mov byte ptr A[esi], al mov lastRes, al
inc esi loop loop1
popa }
std::cout << ("Последний результат из ассемблера: " + std::to_string((long long)lastRes));
}
int main() { srand(time(NULL));
byte A[SIZE_ROW * SIZE_COLUMN], B[SIZE_ROW * SIZE_COLUMN], C[SIZE_ROW * SIZE_COLUMN];
byte k = 2;
init(B); init(C);
MyAsm(A, B, C, k);
return 0; }
При этом если поместить тело функции MyAsm в main(), то всё нормально работает. В чем может быть ошибка и как ее исправить?
Компилятор: Microsoft Visual Studio 2010 Professtional ОС: Windows 10 Pro x64
Сама задача: вычислить значение выражения A = B + k*C, где k - постоянный коэффециент, а A, B, C - матрицы одинаковых размеров. При этом нужно сделать через ассемблерную вставку.


Ответ

Инструкции типа
mov byte ptr A[esi], al
записывают данные в память самой локальной переменной A со смещением esi. То есть это даже близко не является записью в память, указуемую указателем A (как вы, очевидно, хотели). В результате вместо доступа к своим массивам вы разрушаете значение A, а затем и стек вашей функции MyAsm
Чтобы доступиться к памяти массива, переданного через указатель A, вам надо прочитать содержимое A в регистр и адресоваться уже от него. Аналогично со всеми остальными указателями.
То есть если делать "в лоб" то например так
mov edi, B mov bl, byte ptr [edi + esi] mov edi, C mov dl, byte ptr [edi + esi] ... mov edi, A mov byte ptr [edi + esi], al
Разумеется, аккуратно манипулируя регистрами, вы можете избежать постоянного чтения значений A, B и С из памяти.

Комментариев нет:

Отправить комментарий