struct / union

Тема в разделе "LANGS.C", создана пользователем Paguo_86PK, 26 апр 2009.

  1. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Вот когда пишешь эмулятор, очень много загвоздок. Например, составил две структуры:
    Для i80x86:
    Код (Text):
    1. typedef struct {
    2.     union {
    3.         struct {
    4.             union {
    5.                 struct {
    6.                     char    al;
    7.                     char    ah;
    8.                 };
    9.                 short   ax;
    10.                 long    eax;
    11.             };
    12.             union {
    13.                 struct {
    14.                     char    cl;
    15.                     char    ch;
    16.                 };
    17.                 short   cx;
    18.                 long    ecx;
    19.             };
    20.             union {
    21.                 struct {
    22.                     char    dl;
    23.                     char    dh;
    24.                 };
    25.                 short   dx;
    26.                 long    edx;
    27.             };
    28.             union {
    29.                 struct {
    30.                     char    bl;
    31.                     char    bh;
    32.                 };
    33.                 short   bx;
    34.                 long    ebx;
    35.             };
    36.             union {
    37.                 short   sp;
    38.                 long    esp;
    39.             };
    40.             union {
    41.                 short   bp;
    42.                 long    ebp;
    43.             };
    44.             union {
    45.                 short   si;
    46.                 long    esi;
    47.             };
    48.             union {
    49.                 short   di;
    50.                 long    edi;
    51.             };
    52.         };
    53.         char    r08[16];
    54.         short   r16[8];
    55.         long    r32[8];
    56.     };
    57.     union {
    58.         char    fl;
    59.         short   fx;
    60.         long    efx;
    61.     };
    62.     union {
    63.         short   ip;
    64.         long    eip;
    65.     };
    66.     short   es;
    67.     short   cs;
    68.     short   ss;
    69.     short   ds;
    70.     short   fs;
    71.     short   gs;
    72. } X86REGS;
    и для i8080 / Z80:
    Код (Text):
    1. typedef union {
    2.     struct {
    3.         BYTE    r8[8];
    4.         struct {
    5.             BYTE    r8[8];
    6.         } ex;
    7.     };
    8.     struct {
    9.         WORD    r16[4];
    10.         struct {
    11.             BYTE    r16[4];
    12.         } ex;
    13.         BYTE    ptr[2];
    14.     };
    15.     struct {
    16.         BYTE    cl;
    17.         BYTE    ch;
    18.         BYTE    dl;
    19.         BYTE    dh;
    20.         BYTE    bl;
    21.         BYTE    bh;
    22.         BYTE    al;
    23.         BYTE    fl;
    24.         struct {
    25.             BYTE    cl;
    26.             BYTE    ch;
    27.             BYTE    dl;
    28.             BYTE    dh;
    29.             BYTE    bl;
    30.             BYTE    bh;
    31.             BYTE    al;
    32.             BYTE    fl;
    33.         } ex;
    34.         BYTE    ixl;
    35.         BYTE    ixh;
    36.         BYTE    iyl;
    37.         BYTE    iyh;
    38.         WORD    ip;
    39.         BYTE    i;
    40.         BYTE    r;
    41.     };
    42.     struct {
    43.         WORD    cx;
    44.         WORD    dx;
    45.         WORD    bx;
    46.         WORD    psw;
    47.         struct {
    48.             WORD    cx;
    49.             WORD    dx;
    50.             WORD    bx;
    51.             WORD    psw;
    52.         } ex;
    53.         WORD    ix;
    54.         WORD    iy;
    55.         WORD    sp;
    56.         WORD    ip;
    57.         WORD    ir;
    58.         __int64 regs;
    59.         __int64 regx;
    60.         __int64 ptrs;
    61.         __int64 cnts;
    62.         __int64 tacts;
    63.     };
    64. } X80REGS;
    Всё хорошо. А вот как можно память описать для стека например? Если описать как
    Код (Text):
    1. typedef struct {
    2.     union {
    3.         char    Char[65537];
    4.         int     Int[65536];
    5. ...
    то реальное выравнивание Int будет кратно двум. Тогда как мне надо объяснить компилятору так, чтобы всюду не применять записи, типо
    *(int*)(Char + addr)
    а просто писать
    Int[addr]
    т.к. компилятор всё дополнит до
    Int[addr] как *(int*)(Char + addr * sizeof(int))
    а мне это не нужно...

    Существует ли решение подобной задачи?

    Спасибо!
     
  2. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    как там у вас с пультом для управления дверями и гвоздями в кинескопе?

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

    или макросы юзайте
     
  3. disaster

    disaster New Member

    Публикаций:
    0
    Регистрация:
    11 фев 2009
    Сообщения:
    12
    Просто так не отделаться уже по той причине, что при обращении к WORD по адресу (индексу) 0xffff, нужно будет обратиться к байту по адресу 0.
     
  4. agrischuk

    agrischuk New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2009
    Сообщения:
    47
    Если правильно понял, нужно поставить выравнивание на структуру:
    Для MSVC __declspec(align(n))
    для GCC __attribute__ ((aligned (n)))
     
  5. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    никак! как 11 лет назад задумал, а лет 5 назад с другом обсуждал, так и всё в теории осталось...
    ошибки нет. на макросах был построен позапрошлый эмулятор. прошлый - чисто в _asm {...}, а нынче хочу всю мощь Си задействовать, если получится...
    само собою. контроль будет или тупое эхо-зеркало.
    Спасибо! проверю этот способ...
     
  6. disaster

    disaster New Member

    Публикаций:
    0
    Регистрация:
    11 фев 2009
    Сообщения:
    12
    Paguo_86PK
    А вот здесь можно подробнее?
    int Int[65536]; - насколько я знаю выделит памяти нам 65536 * sizeof(int) байт, в то время как нам нужно всего 65536 (65536 + 1, если хотим обращаться к массиву слов) байт. Или правила в c++ уже поменялись?
     
  7. disaster

    disaster New Member

    Публикаций:
    0
    Регистрация:
    11 фев 2009
    Сообщения:
    12
    Всё равно ведь нужна проверка на последний байт, не проще ли написать класс для Int и переопределить operator[] или в самом классе Stack написать функции доступа к байтам и словам.
    И align тут непричём, индексирование всё равно будет addr * sizeof(int).
     
  8. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Думается, решения нет :dntknw:
    эх, си - не асм...
     
  9. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    Paguo_86PK
    на непоставленную задачу решения - да, нет. ни на асме, ни на С, ни на С++.
     
  10. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Почему непоставленную? О_о
    я написал же:
    у меня три собственныхх эмулятора имеется: один - 8086 (си+макросы), и два - 8080 (си+макросы и си _asm)
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Paguo_86PK
    Это круто, только не совсем понятно зачем. Хобби такой?
     
  12. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Хобии + ностальгия...
    Lo-Tec тоже заслуживает внимание...
     
  13. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Нет. Разве что использовать макросы или перегрузку операторов из C++.
     
  14. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Начал изучать AngelScript и сильно споткнулся на том, что никакого практического опыта в программировании на Си++ не имею.
    Код (Text):
    1. class   _Screen:                // Объявляем класс "Экран"
    2. public  RefC {                  // счётчик обращений
    3.     private:            // Скрытые
    4.         HDC hDC;            // Указатель контекста DeskTop
    5.         HPEN    hPen;           // Контекст пера
    6.         HBRUSH  hBrush;     // Контекст кисти
    7.         int nPenCounter;        // Счётчик перьев
    8.         int nBrushCounter;  // Счётчик кистей
    9.     public:         // Доступные
    10.     _Screen() {             // Конструктор класса
    11.         hDC = GetDC(NULL);      // Инициация контекста экрана
    12.         hPen = NULL;            // Отчищение пера
    13.         hBrush = NULL;      // Отчищение кисти
    14.         nPenCounter = 0;        // Обнуление счётчика перьев
    15.         nBrushCounter = 0;      // Обнуление счётчика кистей
    16.     };
    17.     ~_Screen() {                // Деструктор класса
    18.         ReleaseDC(NULL, hDC);   // Освободить контекст
    19.         DeleteObject(hPen);     // Удалить перо
    20.         DeleteObject(hBrush);   // Удалить кисть
    21.     };
    22.     // Как здесь правильно объявить? Ошибку компилятор выдаёт
    23.     pen void(int color) {       // Ставим новый цвет кисти
    24.         ++ nPenCounter;     // Инкремент счётчика изменений
    25.         DeleteObject(SelectObject(hDC, hPen = CreatePen(PS_SOLID, 1, color));
    26.     };
    27.     pen int() {             // Возвращаем число изменений кисти
    28.         int n = nPenCounter;
    29.         nPenCounter = 0;
    30.         return n;
    31.     };
    32. };
    Короче, ума не приложу, как в классе объявить, чтобы работал код:
    Код (Text):
    1. _Screen Scr;    // Создаём экран
    2.  
    3.     Scr.pen = 0xFFCCAA; // Должна вызваться функция инкремента счётчика и смены цвета
    4.     if(Scr.pen) ... // Кисть изменилась 1 раз, возвращенно функцией сброса счётчика
    Вообще опыта нет, а с ним - и идей, как объяснить компилятору что я затеял.

    Спасибо за помощь!