Project

General

Profile

Вызов программы ASM из Си » History » Version 14

« Previous - Version 14/20 (diff) - Next » - Current version
krufter_multiclet, 07/19/2013 06:50 PM


Вызов программы ASM из Си

Вызов программы, написанной на ассемблере из Си организован при помощи стека. Подробнее о стеке можно прочитать тут Обзор работы со стеком.

Рассмотрим пример вызова процедуры, написанной на ассемблере, из Си функцией типа void.

Для функции типа void

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

На Си вызов функции может выглядеть так:

#include <HDL51001_ccf.h>

void function_add(int arg1, int arg2);

void main()
{
    int a,b;

    a = 19;
    b = 7;
    function_add(a,b);
    a = 20;
    b = 13;
    function_add(a,b);
}

На ассемблере будет следующее:

.alias ron2 4 ; в реальной программе мы должны сохранить текущие значения РОНов в стеке и только потом их использовать и 
.alias ron3 5 ; перед возвратом в Си восстановить их первоначальные значения, но для простоты примера мы это не сделаем.

;настриваем UART для платы HW1-MCp04
.alias UART_DATA    UART0_DATA
.alias UART_BDR     UART0_BDR
.alias UART_ST      UART0_ST
.alias UART_CR      UART0_CR

.alias UART_PORT_PIN  0x300
.alias UART_PORT_BPS  GPIOB_BPS

.global function_ex

.text

function_ex:
   rdl #SP, 4 ;получаем первый аргумент
   rdl #SP, 8 ;получаем второй аргумент
   addl @1, @2 ;складываем аргументы
   setl #ron3, @1
   jmp initUART
complete

initUART:
    getl 0x00000300
    wrl @1, UART_PORT_BPS
    getl 0x00000104
    wrl @1, UART_BDR
    getl 0x00000003
    wrl @1, UART_CR
    jmp send_byte_UART
    setl #ron2, 7
 complete

send_byte_UART:
    getl #ron2
    jne @1, send_byte_UART
    je @2, buf_TXD
    getq #ron3
    slrq @1, 8
    setq #ron3, @1
    wrl @3, UART_DATA
    subl @7, 1
    setl #ron2, @1
 complete

buf_TXD:
    rdl UART_ST
    getl 0x00000004
    and @1, @2
    je @1, buf_TXD
    jne @2, return
complete

return:
    rdl #SP
    jmp @1
complete

Параграфы function_ex и return составляют всю работы со стеком, т.е. работа со стеком заняла 4 команды.

Для функции типа int

Пусть программа на ассемблере принимает два аргумента и выполняет их сложение, а также выдает результат в Си, где
происходит его умножение и вместе с ещё одним аргументом функция на ассемблере вызывается ещё раз, результаты выводятся
по UART на Си.

На Си вызов функции может выглядеть так:

#include <HDL51001_ccf.h>

int function_add(int arg1, int arg2);

void main()
{
    int a,b,c,d,e;
    UART_InitTypeDef UART_InitStructure;
    //настройка UART для отладочной платы HW1-MCp04
    UART_InitStructure.BaudRate = 38400; //скорость
    UART_InitStructure.TypeParity = 0x00000000; //тип контроля четности
    UART_InitStructure.Parity = 0x00000000; //разрешение контроля четности
    UART_InitStructure.FlowControl = 0x00000000; //разрешение аппаратного контроля
    UART_InitStructure.Mode = 0x00000003; //разрешение работы на приём и передачу

    GPIOB->BPS = 0x00000F00;         //разрешение альтернативных функций порта для uart0
    uart_init(UART0, &UART_InitStructure); //инициализация

    a = 19;
    b = 7;
    c = function_add(a,b); //получаем результат работы функции на ассемблере
    uart_send_int(c, UART0); //посылаем результат через uart0
    c = c*2;
    d = 20;
    e = function_add(c,d);
    uart_send_int(e, UART0);
}

На ассемблере будет следующее:

.global function_ex

.text

function_ex:
    rdl #SP, 8 ;получаем первый аргумент
    rdl #SP, 12 ;получаем второй аргумент
    addl @1, @2 ;складываем аргументы
    wrl @1, #SP, 4
    jmp return
complete

return:
    rdl #SP
    jmp @1
complete

Также возникают ситуации, когда необходимо использовать стек в самой программе на ассемблере:
- сохранить текущее значение РОНов
- использовать стек для своих переменных

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