реклама на сайте
подробности

 
 
> GNU as: как описать union?, Что-то не придумывается.
Сергей Борщ
сообщение Mar 27 2009, 17:48
Сообщение #1


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Итак, имеем union, описанный на С примерно так:
Код
union a_t
    {
        struct
        {
            uint16_t    a;
            uint8_t     b;
            uint16_t    c;
        };
        struct
        {
            uint8_t     d;
            uint16_t    e;
            uint8_t     f;
        };
    } A;
Для ИАРа делается просто:
Код
    RSEG MYDATA : DATA(0)
    A:
    a   DS  2
    b   DS  1
    c   DS  2
        ORG 0
    d   DS  1
    e   DS  2
    f   DS  1
    
    теперь
      LDI R30, LOW(A)
      LDI R31, HIGH(A)
      LD  R16, Z+ (a - A) + 0
      LD  R17, Z+ (a - A) + 1
      LD  R18, Z+ (b - A)
А у гнутого асма .org работает иначе, им нельзя сдвинуть location counter назад и как мне организовать что-то эквивалентное - не могу придумать. Делать
Код
A:
      .skip 4,0
      .set  a, A + 0
      .set  b, a + 2
      .set  c, b + 1
      .set  d, A + 0
      .set  e, d + 1
      .set  f, e + 2
не хочется, ибо и размеры переменных неочевидны и нет автоматического резервирования места (если добавить переменную и забыть исправить .skip - будут неприятности). Возможно есть все же какое-то красивое решение?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 3)
Diz
сообщение Mar 28 2009, 12:11
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 1-08-06
Пользователь №: 19 250



Если union объявляется в C, и к нему нужен доступ из ассемблера (с вычислением оффсетов переменных), стоит сделать так.

Код
/** Nick Stephen's trick to get info from C-file */
#define DECLARE(SYM,VAL) __asm__("\r#define\t" SYM "\t%0" : : "n" ((int)(VAL)))


Создается C-файл для генерации оффсетов

Код
#include "mystruct.h"

void calc_offsets( void)
{
    DECLARE( "A_A",offsetof( a_t, a));
    DECLARE( "A_F",offsetof( a_t, f));
}


Из файла делается ассемблерный листинг, offsets.S (скомпилировать его не удастся по понятным причинам :-)
Затем grep '#define' offsets.S offsets.inc
offsets.inc замечательно включается в ассемблерный исходник и содержит все нужные строчки, типа #define A_A #0

Естественно, все автоматизируется через мейкфайл.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 28 2009, 22:51
Сообщение #3


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Сергей Борщ @ Mar 27 2009, 19:48) *
Возможно есть все же какое-то красивое решение?
Ну насколько красивое - решать обществу smile.gif
Ещё в теме про структуры хотел отписаться, родил тогда "ручной" вариант, но не дописал макросы.
Во:
main.S
Код
.nolist
#include <avr/io.h>
.list

.macro struct_start name
\name\()_begin:
.endm

.macro struct_field name, fldname, size
.set \name\()_\fldname, . - \name\()_begin
    .skip \size
.endm

.macro struct_end name
.set \name\()_size , . - \name\()_begin
.endm

.macro set_max name, val1, val2
    .if \val1 > \val2
    .set \name, \val1
    .else
    .set \name, \val2
    .endif
.endm


    .section    .structs,"",@nobits
    struct_start A
    struct_field A, a, 2
    struct_field A, b, 1
    struct_field A, c, 2
    struct_end    A

    struct_start B
    struct_field B, d, 1
    struct_field B, e, 2
    struct_field B, f, 1
    struct_end    B

    set_max AB_size, A_size, B_size


    .data
union1:    .skip AB_size
union2:    .skip AB_size

    .text
    .global main
main:
    lds    R16, union1+A_b
    ldi    ZL, lo8(union2)
    ldi    ZH, hi8(union2)
    ldd    R0, Z+B_e
    ldd    R1, Z+B_e+1
    
    .end

elf-dump (.data пошло с 0x60):
Код
00000038 <main>:
  38:    00 91 62 00     lds    r16, 0x0062
  3c:    e5 e6           ldi    r30, 0x65; 101
  3e:    f0 e0           ldi    r31, 0x00; 0
  40:    01 80           ldd    r0, Z+1; 0x01
  42:    12 80           ldd    r1, Z+2; 0x02

00000044 <_exit>:
  44:    ff cf           rjmp    .-2     ; 0x44 <_exit>

Пойдёт? ;-)
Пописать, чтоли, на ассемблере...

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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 29 2009, 00:42
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Diz @ Mar 28 2009, 14:11) *
стоит сделать так.
Да, мысль пойти от С в голову не приходила, видимо потому что весь проект, для которого это нужно, уже написан на асме (исходно был на С, но в процессе упихивания в 2К области зарузчика асмовые листинги были заоптимизированы напрочь). Решение красивое. Только  я бы в DECLARE генерил просто асмовые директивы .set, получая сразу глобальные символы без всякой пост-обработки.


Цитата(ReAl @ Mar 29 2009, 00:51) *
Ну насколько красивое - решать обществу
Афигеть! Собственно, другими словами и не выразить. Спасибо огромное! То, что нужно.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 17:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.0139 секунд с 7
ELECTRONIX ©2004-2016