Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AiPSP_ekzamen_main.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
1 Мб
Скачать
☆

2.5.3. Вызов подпрограммы на ассемблере из программы на с

Хорошим стилем программирования считается описание прототипа ассемблерной функции для определения аргументов функции и интерфейса между программой на С и подпрограммой на ассемблере.

Модель run-time среды выполнения определяет некоторые регистры как рабочие (Scratch), а некоторые – как "сохраняемые при вызове" (Call Preserved). Scratch-регистры могут использоваться в ассемблерной подпрограмме без ограничений, не нужно заботиться о восстановлении их старых значений при выходе из подпрограммы. Если рабочих регистров недостаточно, то можно использовать CallPreserved-регистры, однако при входе в функцию следует сохранить их значения, а при выходе – восстановить. Следует стремиться к тому, чтобы использовать выделенные регистры по их прямому назначению (например, для работы со стеком), поскольку компилятор, библиотечные функции и прерывания предполагают именно такое их использование.

Компилятор предполагает, что режимы работы процессора во время выполнения asm-функции не изменяются.

Пример взаимодействия подпрограмм на С и ассемблере.

Текст модуля на языке С

#include <stdio.h>

int a, b, c, d, e;

// прототипы функций

int SumC(int u, int v, int x, int y, int z);

extern int SumAsm(int u, int v, int x,

int y, int z);

int SumC(int u, int v, int x, int y, int z)

{

int temp1;

temp1 = u + v + x + y + z;

return temp1;

}

int main()

{

a = 1; b = 5; c = 8; d = 3; e = 10;

e = SumAsm(a, b, c, d, e);

e = SumC(a, b, c, d, e);

return 0;

}

Код процедуры main() с оптимизацией:

…

r2=10; // r2 = e

r1=3; // r1 = d

dm(i7,m7)=r2; // push (e)

r8=5; // r8 = b

r12=8; // r12 = c

r4=m14; // r4 = 1

dm(i7,m7)=r1; // push (d)

//сохранить a,b,c,d,e

dm(_a)=r4; dm(_b)=r8; dm(_c)=r12; dm(_d)=r1; dm(_e)=r2;

// вызов

cjump _SumAsm (DB);

dm(i7,m7)=r2;

dm(i7,m7)=pc;

// возврат, результат в r0 – это e

modify(i7,2); //очистка стека от параметров

// подготовка к следующему вызову

r2=dm(_d); // r2 = d

dm(i7,m7)=r0; // push (e)

r12=dm(_c); // r12 = c

r8=dm(_b); // r8 = b

r4=dm(_a); // r4 = a

dm(i7,m7)=r2; // push (d)

dm(_e)=r0; // сохранить e=SumC()

// вызов

cjump _SumC (DB);

dm(i7,m7)=r2;

dm(i7,m7)=pc;

dm(_e)=r0; // сохранить результат в e

modify(i7,2); // очистить стек от параметров

…

Код процедуры SumC без оптимизации (Debug)

_SumC:

// место под локальную temp и автопеременные

modify(i7,-5);

// полученные параметры -> в автопеременные

dm(-4,i6)=r4;

dm(-3,i6)=r8;

dm(-2,i6)=r12;

// вычисления (без оптимизации)

r2=r4+r8; // r2 = u+v

r1=r2+r12; // r2 = u+v+x

r0=dm(1,i6); // r0 = y (i6+1)

r2=r1+r0; // r2 = u+v+x+y

r1=dm(2,i6); // r1 = z (i6+2)

r0=r2+r1; // r0 = u+v+x+y+z

dm(-6,i6)=r0; // temp = r0

// возврат

i12=dm(m7,i6);

jump(m14,i12) (DB);

rframe;

nop;

Код процедуры SumC с оптимизацией (Release)

_SumC:

modify(i7,-4); //место под локальную temp (лишнее)

r2=dm(2,i6);

r2=r2+r4, r1=dm(1,i6);

r2=r2+r1, i12=dm(m7,i6);

jump(m14,i12) (DB), r2=r2+r12;

r0=r2+r8;

rframe;

Модуль с кодом процедуры SumAsm, написанный вручную

#include <def21060.h>

#include <asm_sprt.h>

.section/pm seg_pmco;

.global _SumAsm;

//int SumAsm(int u, int v, int x, int y, int z)

_SumAsm:

r0 = r4+r8, r4 = dm(0x1,i6); // r0=u+v, r4=y;

r0 = r0 + r4, r4 = dm(0x2,i6); // r0=u+v+y, r4=z;

r0 = r0 + r4, i12=dm(m7, i6); // r0=u+v+y+z

jump (m14, i12) (DB), r0 = r0 + r12; // r0=Sum, возврат

nop;

rframe;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]