Jump to content

    
Sign in to follow this  
Сергей Борщ

GNU as: как описать union?

Recommended Posts

Итак, имеем 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 - будут неприятности). Возможно есть все же какое-то красивое решение?

Share this post


Link to post
Share on other sites

Если 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

 

Естественно, все автоматизируется через мейкфайл.

Share this post


Link to post
Share on other sites
Возможно есть все же какое-то красивое решение?
Ну насколько красивое - решать обществу :)

Ещё в теме про структуры хотел отписаться, родил тогда "ручной" вариант, но не дописал макросы.

Во:

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. Для связи с С-программой таки лучше настроить генерацию как в предыдущем сообщении, автоматика будет.

Share this post


Link to post
Share on other sites
стоит сделать так.
Да, мысль пойти от С в голову не приходила, видимо потому что весь проект, для которого это нужно, уже написан на асме (исходно был на С, но в процессе упихивания в 2К области зарузчика асмовые листинги были заоптимизированы напрочь). Решение красивое. Только  я бы в DECLARE генерил просто асмовые директивы .set, получая сразу глобальные символы без всякой пост-обработки.

 

 

Ну насколько красивое - решать обществу
Афигеть! Собственно, другими словами и не выразить. Спасибо огромное! То, что нужно.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this