Страницы

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

пятница, 31 января 2020 г.

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

#cpp #c #visual_studio #ассемблер #visual_studio_2010


При выполнении этого кода получаю следующую ошибку:


  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 - матрицы одинаковых размеров. При этом нужно сделать через ассемблерную вставку.
    


Ответы

Ответ 1



Инструкции типа 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 и С из памяти.

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

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