1. В сообществе нашего форума Вконтакте создан раздел по продаже электронных компонентов.
    Каждый может продать в нем свои залежавшиеся детали. Подробности здесь.

Сравнение загружаемого кода написанного на С и ассемблере

Тема в разделе "Программирование", создана пользователем UL7AAjr, 27 ноя 2016.

  1. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Недавно зашел разговор о том, насколько ассемблерный код эффективнее кода после компиляции с языка С. Вот тут предлагаю сравнить.

    Для сравнения выбрал простую задачку, которую может написать даже начинающий программист.

    Задача такая. Имеется МК и терминальное соединение по UART (например с обычным ПК). Пользователь печатает на терминале число от 0 до 255 и нажимает Enter. МК считывает это число и выполняет в цикле расчет суммы арифметической прогрессии для принятого числа. Например если было введено число"4", то МК вычисляет 1+2+3+4 (простой цикл, без использования формул). Результат выводит на терминал по UART и ждет ввода следующего числа.

    Желающие присоединяйтесь. Победителю - пиво:)

    Я буду использовать МК STM8L и ассемблер.

    PS: Защиту от дурака делать не надо, предполагается, что пользователь все вводит правильно.
     
  2. .ctor

    .ctor В доску свой

    Сообщения:
    712
    Симпатии:
    200
    Род занятий:
    парогенератор
    Адрес:
    Алматы
    Ты нашел прекрасный способ купить сам себе пиво))
  3. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Не, на самом деле интересно сравнить. Например AVR и STM.
  4. .ctor

    .ctor В доску свой

    Сообщения:
    712
    Симпатии:
    200
    Род занятий:
    парогенератор
    Адрес:
    Алматы
    Да и так понятно все, что на ассемблере быстрее и меньше результат выйдет.
  5. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Так вот и посмотреть на сколько, просто я думаю, что в два раза по-любому, но есть несогласные.
    Время будет - тоже напиши, ты-же под atmel за пару минут нарисуешь:)
  6. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    Готов озвучить результаты для STM8S105C4T6. :)
  7. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Ну отлично, и что получилось?
  8. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    Осталось на работе. Позже напишу.
  9. _VN_

    _VN_ В доску свой

    Сообщения:
    468
    Симпатии:
    58
    Род занятий:
    Инженер
    Адрес:
    Алматы
    Интересная тема. Некоторые предложения со скамейки сторонних крайне заинтересованных наблюдателей:
    1. Нужно обозначить начальные условия для программ - они должны иметь одинаковое число имён постоянных и переменных, выделенные объёмы памяти для программ, констант и переменных и другие пока мне неизвестные параметры разрабатываемых программ;
    2. Показать объём программы для простейшей операции, например, +1 в регистр с именем "А" - одна операция;
    3. Повторение пп.2, например, с двумя регистрами и аналогичной операцией;
    Далее, постепенно усложняя программу, можно определить избыточные, по сравнению с ассемблером, объёмы программы, которые создаются в программе на языке С, считая программу на ассемблере эталоном в смысле минимально возможного объёма генерируемого кода.
  10. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Не выйдет с одинаковым количеством переменных. На ассемблере подход к написанию алгоритмов отличается от принятого в языках высокого уровня. А если принудительно эмулировать язык высокого уровня, то нет смысла использовать ассемблер.
  11. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    У меня 119 байта получилось (0x80f7 - 0x8080). RAM не использовал. Количество циклов для вычисления суммы прогрессии = 5 + N * 5 - 1, где N - введенное число.

    Например для введенного числа 255 получается 1279 тактов.

    Untitled-1.jpg
    Последнее редактирование: 1 дек 2016
  12. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    Контроллер - STM8S105C4T6.
    Компилятор IAR.
    Оптимизация High - Balanced.
    Скрин из терминалки.

    [​IMG]

    Данные из листинга:

    15 bytes in section .near.bss
    14 bytes in section .near.noinit
    3 bytes in section .near.rodata
    208 bytes in section .near_func.text

    208 bytes of CODE memory
    3 bytes of CONST memory
    15 bytes of DATA memory (+ 14 bytes shared)

    Исходный код:

    Код:
    #include "iostm8s105c4.h"
    #include "intrinsics.h"
    #include "stdlib.h"
    #include "stdio.h"
    
    char BUFF_RX[4];
    char BUFF_TX[6];
    unsigned char P_RX;
    unsigned char P_TX;
    unsigned char IN_N;
    unsigned int OUT_SUMM;
    
    void send_byte(unsigned char s_byte)
    {
      PD_ODR_ODR4=1;
      UART2_DR=s_byte;
      while(UART2_SR_TC==0){}
      PD_ODR_ODR4=0; 
    }
    
    int main( void )
    {
      CLK_ECKR_bit.HSEEN=0;
      CLK_SWR=0xE1;
      CLK_CKDIVR=0;
      while(CLK_CMSR!=0xE1);
      CLK_CSSR_bit.CSSEN=1;
      UART2_CR2_REN=UART2_CR2_TEN=1;
      UART2_BRR2=0x02;
      UART2_BRR1=0x68;
    
      PD_ODR_bit.ODR4=0;
      PD_DDR_bit.DDR4=1;
      PD_CR1_bit.C14=1;
      PD_CR2_bit.C24=0;
      P_RX=0;
    
      __enable_interrupt();
      while(1)
      {
        if(UART2_SR_RXNE==1)
        {
          BUFF_RX[P_RX]=UART2_DR;
          if(BUFF_RX[P_RX]==0x0D)
          {
            BUFF_RX[P_RX]=0;
            P_RX=0;
            IN_N=atoi(&BUFF_RX[0]);
            OUT_SUMM=0;
            for(unsigned char i=0;(i<IN_N);i++)
            {
              OUT_SUMM+=i+1;
            }
            sprintf(BUFF_TX, "%d", OUT_SUMM);
            P_TX=0;
            while(BUFF_TX[P_TX]!=0x00)
            {
              send_byte(BUFF_TX[P_TX++]);
            }
          }
          else
          {
            P_RX++;
            P_RX&=0x03;
          }
        }
      }
    }
  13. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    А код библиотек тоже надо еще добавить там-же sprintf, atoi.
  14. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    :D
  15. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Исходный текст на ассемблере для STM8L, STM8S.

    *исправил цикл вычисления (переделал под один байт 0..255)

    PHP:
    stm8/
        
    #include "stm8l151c6.inc"
       
        
    segment 'rom'
       
    ;-----------------------------------------------------------
    main.l
            
    настройка стека
            ldw     X
    #$07FF
            
    ldw     SPX
           
            
    запуск UART
            bset    CLK_PCKENR1
    #5
            
    clr        USART1_BRR2
            mov        USART1_BRR1
    #$0D
            
    mov        USART1_CR2#%00001100
           
            
    TX на выход
            bset    PC_DDR
    #3
            
    bset    PC_CR1#3
           
            
    основной цикл
    infinite_loop
    .l
            call    usart_crlf 
    перевод строки

            
    чтение данныхрезультат в X
            clrw    X
    _read_uart       
            
    чтение UART
            btjf    USART1_SR
    #5, *
            
    ld        AUSART1_DR
            call    usart_write  
    эхо
            cp        A
    #13
            
    jreq    _read_done
           
            sllw    X
            pushw    X
            sllw    X
            sllw    X
            addw    X
    , (1,SP)
            and        
    A#$0F
            
    push    A
            push    
    #0
            
    addw    X, (1,SP)
           
            
    addw    SP#4
            
    jra        _read_uart
           
    _read_done

            call    usart_crlf 
    перевод строки
           
            
    расчет прогрессии в X
            
    количество циклов 5 1
           
            pushw    X         
    ;2cy
            clrw    X             
    ;1cy
           
            
    тело цикла
    _add_more   
            addw    X
    , (1,SP)  ; 2cy
            dec        
    (2,SP)     ; 1cy
            jrne    _add_more 
    2cy
            
    конец цикла
           
            addw        SP
    #2  ; 2cy
           
    _out_res       
           
            
    преобразовать результат в строку
            push    
    #0
    _out_more       
            ldw        Y
    #10
            
    divw    XY
            ld        A
    YL
            
    or        A#$30
            
    push    A
            tnzw    X
            jrne    _out_more
           
            
    вывести результат
    _put_more       
            pop        A
            call    usart_write
            jrne    _put_more

        jra infinite_loop
       
    ;-----------------------------------------------------------
    usart_crlf
            ld        A
    #10
            
    call    usart_write
            ld        A
    #13
    ;-----------------------------------------------------------
    usart_write
            
    подождать предыдущую отправку
            btjf    USART1_SR
    #6, *
            
    отправить байт
            ld        USART1_DR
    A
        ret
       
       

        segment 
    'vectit'
        
    dc.{$82000000+main}                                    ; reset
        end
    Последнее редактирование: 1 дек 2016
  16. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    Код без библиотек:

    PHP:
    #include "iostm8s105c4.h"

    void uart_send(unsigned char out_byte)
    {
      
    UART2_DR=out_byte;
      while(
    UART2_SR_TC==0){};
    }

    int mainvoid )
    {
      
    char BUFF_TX[5];
      
    unsigned char L_TX;
      
    unsigned char IN_N;
     
     
      
    CLK_ECKR_bit.HSEEN=0;
      
    CLK_SWR=0xE1;
      
    CLK_CKDIVR=0;
      while(
    CLK_CMSR!=0xE1);
      
    CLK_CSSR_bit.CSSEN=1;
      
    UART2_CR2_REN=UART2_CR2_TEN=1;
      
    UART2_BRR2=0x02;
      
    UART2_BRR1=0x68;

      
    PD_ODR_bit.ODR4=0;
      
    PD_DDR_bit.DDR4=1;
      
    PD_CR1_bit.C14=1;
      
    PD_CR2_bit.C24=0;
      
    IN_N=0;

      while(
    1)
      {
        if(
    UART2_SR_RXNE==1)
        {
          if(
    UART2_DR==0x0D)
          {
            
    unsigned int OUT_SUMM=0;
            for(
    unsigned char i=1i<=IN_N ;i++)
            {
              
    OUT_SUMM+=i;
            }
            
    IN_N=0;

            
    PD_ODR_ODR4=1;
            if(
    OUT_SUMM==0)
            {
              
    uart_send(0x30);
            }
            else
            {
              
    L_TX=0;
              while(
    OUT_SUMM>0)
              {
                
    BUFF_TX[L_TX++]=(OUT_SUMM%10)+0x30;
                
    OUT_SUMM/=10;
              }

              while(
    L_TX>0)
              {
                
    uart_send(BUFF_TX[--L_TX]);
              }
            }
            
    uart_send(0x0D);
            
    PD_ODR_ODR4=0
          }
          else
          {
            
    IN_N=IN_N*10+(UART2_DR-0x30);
          }
        }
      }
    }
    --- Сообщения объединены, 1 дек 2016 ---
    Из листинга:

    14 bytes in section .near.noinit
    225 bytes in section .near_func.text

    225 bytes of CODE memory
    0 bytes of DATA memory (+ 14 bytes shared)

    Ну и собственно проект в архиве:

    Вложения:

    • Test_AP.rar
      Размер файла:
      54,5 КБ
      Просмотров:
      2
  17. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Исправил код немного. Получилось 119 байт кода. Для исходного числа = 255 получается 1279 тактов.

    PS: это все-же больше чем в два раза быстрее. И более, чем в два раза меньше по коду:)
  18. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    Я ещё не сдался! ;)
  19. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.895
    Симпатии:
    310
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Можно задачу сменить, если хочешь:)
  20. [Raiden]

    [Raiden] Гость

    Сообщения:
    28
    Симпатии:
    7
    Ну я сегодня над этой поколдую ещё!

Поделиться этой страницей