Доброе время суток. Подскажите, умеет ли FASM выравнивать структуры, как, например, это делает VisualStudio(#pragma pack(push,4), конечно)? Есть: Код (Text): format PE GUI 4.0 include '%fasminc%\win32a.inc' struct test t1 db ? t2 dw ? t3 dd ? ends entry _start section '.text' code readable executable _start: mov eax,sizeof.test mov [_test.t1],'1' mov [_test.t2],0DEADh mov [_test.t3],0DEADBEEFh invoke ExitProcess,0 section '.data' data readable writeable _test test section '.import' data import readable writeable library kernel32,'kernel32.dll' import kernel32,ExitProcess,'ExitProcess' Который, логично приводится к виду: Код (Text): 00401000 MOV EAX,7 00401005 MOV BYTE PTR DS:[402000],31 0040100C MOV WORD PTR DS:[402001],0DEAD 00401015 MOV DWORD PTR DS:[402003],DEADBEEF 0040101F PUSH 0 00401021 CALL DWORD PTR DS:[<&kernel32.ExitProces>] А хотелось бы заставить FASM выравнивать данные так: Код (Text): #pragma pack(push,4) struct testtest { char t1; short t2; int t3; }; #pragma pop() int main(void) { struct testtest *t = (struct testtest*)malloc(sizeof(struct testtest)); t->t1 = '1'; t->t2 = 0xDEAD; t->t3 = 0xDEADBEEF; } В результате: Код (Text): .text:004016D8 call malloc .text:004016DD add esp, 4 .text:004016E0 mov [ebp+var_C], eax .text:004016E3 mov eax, [ebp+var_C] .text:004016E6 mov byte ptr [eax], 31h .text:004016E9 mov ecx, [ebp+var_C] .text:004016EC mov word ptr [ecx+2], 0DEADh .text:004016F2 mov edx, [ebp+var_C] .text:004016F5 mov dword ptr [edx+4], 0DEADBEEFh Такое возможно или только руками выравнивать?
m0r1arty, это как , если написать "какашка" , а фасм чтоб скомпилировал ака "конфетка" ? MS VS так может, да...
litrovith, мне вот интересно, этот форум когда-нибудь избавиться от школьников, которым лишь бы написать хоть что-нибудь? Выравнивание - это хорошая и полезная вещь, не надо спрашивать откуда я узнал, ладно? А вообще, если кто переносил десятки килобайт структур и определений с одного языка на другой - меня поймёт(как и моё желание получить данный функционал, незаработав рак мозга).
m0r1arty, учусь в пятом классе, но знаю, что правильнее было бы написать "избавится". Как школьник НЕшкольнику - переносил сотни килобайт структур и никакого "рака мозга" нет. Мы, школьники, такие ))). Ручками делайте, лентяй! struct test t1 rb 4 t2 rw 2 t3 rd 1 ends если вам шото не нравится в фасме, никто не мешает писать свои макросы( ты ж уже взрослый)
litrovith А ты, значит, НЕлентяй и свое правило выравнивания на 4 придумал?! По общим правилам нужно только t1 на rb 2 заменить (ну или добавить безымянный db ? перед t2)
А кстати, неплохая фича для IDE: правый клик на структуру и выбрать "Align All Members". Поля перетасуются редактором и/или что-то добавится (Pad1, Pad2, ... etc.).
m0r1arty Такое возможно, но как по мне, так очень даже нетривиально. Со всеми этими вложенными структурами и объединениями, макросы из struct.inc — одни из самых запутанных. Для самых простых случаев можно так: Код (Text): format PE GUI 4.0 include 'win32a.inc' ;Allows to assign new value to a symbol without congesting it's stack ;usage: mysym equ 1 ; mysym reequ 1,2 struc reequ [val] { common tmp equ val restore . . equ tmp restore tmp } macro struct name,alignment { struct name local field@struct,revfield@struct,fieldcount,prevfieldssize define matched - match anything,alignment \{ fieldcount equ irp data_def, db,dw,du,dd,dp,dq,dt,rb,rw,rd,rp,rq,rt \\{ struc data_def [args] \\\{ \\\forward revfield@struct equ \\\. data_def args fieldcount reequ fieldcount + \\\} macro data_def [args] \\\{ \\\forward \\\local tmp revfield@struct equ tmp data_def args fieldcount reequ fieldcount + \\\} \\} macro struct \\{ struct macro ends@redefined \\\{ \\\} \\} macro ends@redefined \\{ restruc db,dw,du,dd,dp,dq,dt,rb,rw,rd,rp,rq,rt purge db,dw,du,dd,dp,dq,dt,rb,rw,rd,rp,rq,rt match _fieldcount,fieldcount \\\{ irps any, _fieldcount \\\\{ field@struct equ revfield@struct restore revfield@struct \\\\} \\\} match _fieldcount,fieldcount \\\{ prevfieldssize = 0 irps any, _fieldcount \\\\{ \\\\local \\\\alignment match field rest, field@struct \\\\\{ tmp equ rest virtual at 0 tmp if $ < alignment ;align at natural boundary \\\\alignment = ($ - prevfieldssize mod $) mod $ else ;align at alignment \\\\alignment = (alignment - prevfieldssize mod alignment) mod alignment end if prevfieldssize = prevfieldssize + $ + \\\\alignment end virtual restore tmp \\\\\} rb \\\\alignment match _field@struct, field@struct \\\\\{ _field@struct \\\\\} restore field@struct \\\\} \\\} restore fieldcount \\} restore matched define matched + \} match -,matched \{ macro struct \\{ struct macro ends@redefined \\\{ \\\} \\} macro ends@redefined \\{ \\} \} restore matched } macro ends { purge struct ends@redefined purge ends@redefined ends } struct test,4 t1 db ? t2 dw ? t3 dd ? ends entry _start section '.text' code readable executable _start: mov eax,sizeof.test mov [_test.t1],'1' mov [_test.t2],0DEADh mov [_test.t3],0DEADBEEFh invoke ExitProcess,0 section '.data' data readable writeable _test test section '.import' data import readable writeable library kernel32,'kernel32.dll' import kernel32,ExitProcess,'ExitProcess' Но чуть только пойдут структуры-члены или вложенные структуры, уже этот набросок работать не будет. Поэтому лучше уж заново переписать struct.inc с добавлением такой возможности.
Извиняюсь, за долгое отсутствие. Спасибо за ответы. В тайне надеялся, что кто-нибудь выложит готовое решение. Пришлось переписать стандартные макросы из struct.inc. Сейчас struct_aligned работает со вложенными структурами(членами) и объединениями(проверил, сравнивая с дизасмом около 30 разных структур и объединений с различным размером элементов в структурах). Аналог #pragma pack(push,4)(размер задается после имени структуры struct_aligned struct_name:4), на первый взгляд, тоже работает, но тестировал не так дотошно, как выравнивание "по умолчанию"(эл-т на адрес кратный размеру эл-та). Так же макрос не будет дружить с вложенными структурами от стандартного макроса struct, поэтому если надо такое вложенную структуру можно записать как struct_aligned struct_name:1 - тогда дружба будет. Еще в макросе остался кое-какой мусор, и кое-где можно более элегантно переписать. Будет время - сделаю, а пока прошу не пинать.
m0r1arty Если не ошибаюсь, естесственным выравниванием для примитивных типов является выравнивание не на адрес, кратный размеру, а на адрес, кратный наибольшей степени двойки, не превышающей размер.
"Процессоры работают эффективнее, когда имеют дело с правильно выровненными данными. Например, значение типа WORD всегда должно начинаться с четного адреса, кратного 2, значение типа DWORD - с четного адреса, кратного 4, и т.д." (С) Джефри Рихтер Кажется, я правильно понял.
m0r1arty Я не знаю, что Вы поняли, но 1. приведенная цитата никак не противоречит тому, что я написал 2. Ваша модификация выравнивает поля неправильно.
Если уж на то пошло, то Ваш пост, насчет степени двойки является только уточнением из учебника моей формулировки. А не могли бы Вы пример такой структуры привести?
m0r1arty Или я не понимаю фразу, или пример учебника в студию. Между моей и Вашей формулировкой есть принципиальная разница, никак не тянущая на то, чтобы называться уточнением. Код (Text): struct_aligned some_struct field1 db ? field2 dt ? ends field2 получает смещение 10. Должно быть 8.
Понял ошибку. А размер самой структуры выравнивается тоже до степени двойки не превышающей размер самого большого элемента в структуре или до размера этого эл-та?
m0r1arty Думаю, что это implementation dependend, но, например, студия выравнивает размер структуры до размера, кратного максимальному среди её членов выравниванию.