Выравнивание структур в FASM

Тема в разделе "WASM.ASSEMBLER", создана пользователем m0r1arty, 16 сен 2011.

  1. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    Доброе время суток. Подскажите, умеет ли FASM выравнивать структуры, как, например, это делает VisualStudio(#pragma pack(push,4), конечно)?

    Есть:
    Код (Text):
    1. format PE GUI 4.0
    2.  
    3. include '%fasminc%\win32a.inc'
    4.  
    5. struct test
    6.  
    7.   t1 db ?
    8.   t2 dw ?
    9.   t3 dd ?
    10.  
    11. ends
    12.  
    13. entry _start
    14. section '.text' code readable executable
    15. _start:
    16. mov eax,sizeof.test
    17. mov [_test.t1],'1'
    18. mov [_test.t2],0DEADh
    19. mov [_test.t3],0DEADBEEFh
    20. invoke ExitProcess,0
    21.  
    22. section '.data' data readable writeable
    23.  
    24. _test test
    25.  
    26. section '.import' data import readable writeable
    27. library kernel32,'kernel32.dll'
    28. import kernel32,ExitProcess,'ExitProcess'
    Который, логично приводится к виду:
    Код (Text):
    1. 00401000 MOV EAX,7
    2. 00401005 MOV BYTE PTR DS:[402000],31
    3. 0040100C MOV WORD PTR DS:[402001],0DEAD
    4. 00401015 MOV DWORD PTR DS:[402003],DEADBEEF
    5. 0040101F PUSH 0
    6. 00401021 CALL DWORD PTR DS:[<&kernel32.ExitProces>]
    А хотелось бы заставить FASM выравнивать данные так:
    Код (Text):
    1. #pragma pack(push,4)
    2. struct testtest
    3. {
    4.     char t1;
    5.     short t2;
    6.     int t3;
    7. };
    8. #pragma pop()
    9. int main(void)
    10. {
    11.     struct testtest *t = (struct testtest*)malloc(sizeof(struct testtest));
    12.     t->t1 = '1';
    13.     t->t2 = 0xDEAD;
    14.     t->t3 = 0xDEADBEEF;
    15. }
    В результате:
    Код (Text):
    1. .text:004016D8                 call    malloc
    2. .text:004016DD                 add     esp, 4
    3. .text:004016E0                 mov     [ebp+var_C], eax
    4. .text:004016E3                 mov     eax, [ebp+var_C]
    5.  
    6. .text:004016E6                 mov     byte ptr [eax], 31h
    7. .text:004016E9                 mov     ecx, [ebp+var_C]
    8.  
    9. .text:004016EC                 mov     word ptr [ecx+2], 0DEADh
    10. .text:004016F2                 mov     edx, [ebp+var_C]
    11.  
    12. .text:004016F5                 mov     dword ptr [edx+4], 0DEADBEEFh
    Такое возможно или только руками выравнивать?
     
  2. Kaimi

    Kaimi Андрей

    Публикаций:
    0
    Регистрация:
    15 апр 2010
    Сообщения:
    120
    А
    struct test 4

    в fasm не работает?
     
  3. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    Error: illegal instuction
    test.fields@4 t1 db

    Было бы слишком просто
     
  4. litrovith

    litrovith Member

    Публикаций:
    0
    Регистрация:
    20 июн 2007
    Сообщения:
    509
    m0r1arty, это как , если написать "какашка" , а фасм чтоб скомпилировал ака "конфетка" ? MS VS так может, да...
     
  5. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    litrovith, мне вот интересно, этот форум когда-нибудь избавиться от школьников, которым лишь бы написать хоть что-нибудь? Выравнивание - это хорошая и полезная вещь, не надо спрашивать откуда я узнал, ладно? А вообще, если кто переносил десятки килобайт структур и определений с одного языка на другой - меня поймёт(как и моё желание получить данный функционал, незаработав рак мозга).
     
  6. litrovith

    litrovith Member

    Публикаций:
    0
    Регистрация:
    20 июн 2007
    Сообщения:
    509
    m0r1arty, учусь в пятом классе, но знаю, что правильнее было бы написать "избавится".
    Как школьник НЕшкольнику - переносил сотни килобайт структур и никакого "рака мозга" нет. Мы, школьники, такие ))).
    Ручками делайте, лентяй!

    struct test
    t1 rb 4
    t2 rw 2
    t3 rd 1
    ends

    если вам шото не нравится в фасме, никто не мешает писать свои макросы( ты ж уже взрослый) ;)
     
  7. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    align (num of bytes)?
    RTFM
    http://flatassembler.net/docs.php?article=manual
     
  8. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    litrovith
    А ты, значит, НЕлентяй и свое правило выравнивания на 4 придумал?!
    По общим правилам нужно только t1 на rb 2 заменить (ну или добавить безымянный db ? перед t2)
     
  9. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    А кстати, неплохая фича для IDE: правый клик на структуру и выбрать "Align All Members".
    Поля перетасуются редактором и/или что-то добавится (Pad1, Pad2, ... etc.).
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    m0r1arty
    Такое возможно, но как по мне, так очень даже нетривиально. Со всеми этими вложенными структурами и объединениями, макросы из struct.inc — одни из самых запутанных.
    Для самых простых случаев можно так:
    Код (Text):
    1. format PE GUI 4.0
    2.  
    3. include 'win32a.inc'
    4.  
    5. ;Allows to assign new value to a symbol without congesting it's stack
    6. ;usage: mysym equ 1
    7. ;               mysym reequ 1,2
    8. struc reequ [val]
    9. {
    10.     common
    11.         tmp equ val
    12.             restore .
    13.             . equ tmp
    14.         restore tmp
    15. }
    16.  
    17. macro struct name,alignment
    18. {
    19.     struct name
    20.     local field@struct,revfield@struct,fieldcount,prevfieldssize
    21.    
    22.     define matched -
    23.     match anything,alignment
    24.     \{
    25.         fieldcount equ
    26.         irp data_def, db,dw,du,dd,dp,dq,dt,rb,rw,rd,rp,rq,rt
    27.         \\{
    28.             struc data_def [args]
    29.             \\\{
    30.                 \\\forward
    31.                     revfield@struct equ \\\. data_def args
    32.                     fieldcount reequ fieldcount +
    33.             \\\}
    34.             macro data_def [args]
    35.             \\\{
    36.                 \\\forward \\\local tmp
    37.                     revfield@struct equ tmp data_def args
    38.                     fieldcount reequ fieldcount +
    39.             \\\}
    40.         \\}
    41.        
    42.         macro struct
    43.         \\{
    44.             struct
    45.             macro ends@redefined \\\{ \\\}
    46.         \\}
    47.  
    48.         macro ends@redefined
    49.         \\{
    50.             restruc db,dw,du,dd,dp,dq,dt,rb,rw,rd,rp,rq,rt
    51.             purge db,dw,du,dd,dp,dq,dt,rb,rw,rd,rp,rq,rt
    52.            
    53.             match _fieldcount,fieldcount
    54.             \\\{
    55.                 irps any, _fieldcount
    56.                 \\\\{
    57.                     field@struct equ revfield@struct
    58.                     restore revfield@struct
    59.                 \\\\}
    60.             \\\}
    61.            
    62.             match _fieldcount,fieldcount
    63.             \\\{
    64.                 prevfieldssize = 0
    65.                 irps any, _fieldcount
    66.                 \\\\{
    67.                     \\\\local \\\\alignment
    68.                     match field rest, field@struct
    69.                     \\\\\{
    70.                         tmp equ rest
    71.                         virtual at 0
    72.                             tmp
    73.                             if $ < alignment
    74.                                 ;align at natural boundary
    75.                                 \\\\alignment = ($ - prevfieldssize mod $) mod $
    76.                             else
    77.                                 ;align at alignment
    78.                                 \\\\alignment = (alignment - prevfieldssize mod alignment) mod alignment
    79.                             end if
    80.                             prevfieldssize = prevfieldssize + $ + \\\\alignment
    81.                         end virtual
    82.                         restore tmp
    83.                     \\\\\}
    84.                     rb \\\\alignment
    85.                     match _field@struct, field@struct \\\\\{ _field@struct \\\\\}
    86.                     restore field@struct
    87.                 \\\\}
    88.             \\\}
    89.             restore fieldcount
    90.         \\}
    91.         restore matched
    92.         define matched +
    93.     \}
    94.     match -,matched
    95.     \{
    96.         macro struct
    97.         \\{
    98.             struct
    99.             macro ends@redefined \\\{ \\\}
    100.         \\}
    101.        
    102.         macro ends@redefined \\{ \\}
    103.     \}
    104.     restore matched
    105. }
    106. macro ends
    107. {
    108.     purge struct
    109.     ends@redefined
    110.     purge ends@redefined
    111.     ends
    112. }
    113. struct test,4
    114.   t1 db ?
    115.   t2 dw ?
    116.   t3 dd ?
    117. ends
    118.  
    119. entry _start
    120. section '.text' code readable executable
    121. _start:
    122. mov eax,sizeof.test
    123. mov [_test.t1],'1'
    124. mov [_test.t2],0DEADh
    125. mov [_test.t3],0DEADBEEFh
    126. invoke ExitProcess,0
    127.  
    128. section '.data' data readable writeable
    129.  
    130. _test test
    131.  
    132. section '.import' data import readable writeable
    133. library kernel32,'kernel32.dll'
    134. import kernel32,ExitProcess,'ExitProcess'
    Но чуть только пойдут структуры-члены или вложенные структуры, уже этот набросок работать не будет. Поэтому лучше уж заново переписать struct.inc с добавлением такой возможности.
     
  11. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    Извиняюсь, за долгое отсутствие. Спасибо за ответы.
    В тайне надеялся, что кто-нибудь выложит готовое решение. Пришлось переписать стандартные макросы из struct.inc.

    Сейчас struct_aligned работает со вложенными структурами(членами) и объединениями(проверил, сравнивая с дизасмом около 30 разных структур и объединений с различным размером элементов в структурах).
    Аналог #pragma pack(push,4)(размер задается после имени структуры struct_aligned struct_name:4), на первый взгляд, тоже работает, но тестировал не так дотошно, как выравнивание "по умолчанию"(эл-т на адрес кратный размеру эл-та).
    Так же макрос не будет дружить с вложенными структурами от стандартного макроса struct, поэтому если надо такое вложенную структуру можно записать как struct_aligned struct_name:1 - тогда дружба будет.

    Еще в макросе остался кое-какой мусор, и кое-где можно более элегантно переписать. Будет время - сделаю, а пока прошу не пинать.
     
  12. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    m0r1arty
    Если не ошибаюсь, естесственным выравниванием для примитивных типов является выравнивание не на адрес, кратный размеру, а на адрес, кратный наибольшей степени двойки, не превышающей размер.
     
  13. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    "Процессоры работают эффективнее, когда имеют дело с правильно выровненными данными. Например, значение типа WORD всегда должно начинаться с четного адреса, кратного 2, значение типа DWORD - с четного адреса, кратного 4, и т.д." (С) Джефри Рихтер

    Кажется, я правильно понял.
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    m0r1arty
    Я не знаю, что Вы поняли, но
    1. приведенная цитата никак не противоречит тому, что я написал
    2. Ваша модификация выравнивает поля неправильно.
     
  15. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    Если уж на то пошло, то Ваш пост, насчет степени двойки является только уточнением из учебника моей формулировки.

    А не могли бы Вы пример такой структуры привести?
     
  16. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    m0r1arty
    Или я не понимаю фразу, или пример учебника в студию. Между моей и Вашей формулировкой есть принципиальная разница, никак не тянущая на то, чтобы называться уточнением.
    Код (Text):
    1. struct_aligned some_struct
    2.   field1 db ?
    3.   field2 dt ?
    4. ends
    field2 получает смещение 10. Должно быть 8.
     
  17. m0r1arty

    m0r1arty New Member

    Публикаций:
    0
    Регистрация:
    31 янв 2009
    Сообщения:
    14
    Понял ошибку. А размер самой структуры выравнивается тоже до степени двойки не превышающей размер самого большого элемента в структуре или до размера этого эл-та?
     
  18. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    m0r1arty
    Думаю, что это implementation dependend, но, например, студия выравнивает размер структуры до размера, кратного максимальному среди её членов выравниванию.