А за счет чего она станет меньше? Можно на пальцах В секции днанных например я размещу 10 байт данных или в секции кода размещу 10 байт данных. Как будет это влиять на размер? А за счет чего она станет медленней? (прошу прощения за совсем детские вопросы, просто ветки ниже BEGINNERS ничего нет)
Shoorup Давай на практике -- создай в секции .idata переменную X db 10000 dup (?) скомпилируй программу и посмотри ее размер, а теперь создай в секции .data переменную X db 10000 dup (0) скомпилируй программу и посмотри ее размер. Если при компиляции не используется ключ /ALIGN -- секции имеют размер кратный 512 байтам. Если у тебя всего две секции: кода и данных, то, в целом, размер программы 512+512=1024 байт хотя, данных всего на 10 байт. Теперь размещаем эти же данные в секцию кода, и размер уже не 1024, а всего 512 байт. Программа с записываемыми данными в секции работает медленее потому, что при записи в эти переменные будут происходить сброс кэша и сброс механизма предсказания переходов, это тебе лучше всего leo или Y_Mur смогут объяснить
Продолжаю копать дальше. Чем дальше копаю тем более непонятно. 1. почему неинициализированные данные Code (Text): .data? mesbox_text db 600h dup(?) у меня в коде: Code (Text): .386 .model flat,stdcall .data? m db 10000h dup(?) .code start: nop end start отображаются в дампе, а у Mikl___а в коде? Чую ну очень идиотский вопрос, ну уж простите - учусь До конца не понимаю механизма работы. Как в отладчике работает понимаю, но сам бы не додумался и не повторил бы... Как это работает: Code (Text): mov edi,offset mesbox_text mov esi,offset buffer mov [esi+11],ebx mov [esi+15],edx mov [esi+19],ecx Напишите пожалуйста коменты к этим строчкам и вызываемой процедуре StringOut.
Shoorup Неинициализированные данные (в данном случае под неинициализированными данными понимаются те, при указании которых ставится знак "?") могут как отображаться, так и не отображаться в дампе, находясь в любой секции. 1) Если неинициализированные данные находятся в конце секции (не важно, какой), то самым логичным поведением компилятора было бы увеличение атрибута секции VirtualSize при неизменном атрибуте SizeOfRawData. Т.о. на размер образа на диске такие неинициализированные данные не повлияют, но при загрузке образа в память, необходимый объём памяти будет выделен. 2) Если Вы вдруг захотите после инициализированных данных впихнуть инициализированные. Т.е примерно так: section '.data' data readable writeable uninitData db 1000 dup ? initData db 'ю' , то компилятор будет вынужден заполнить промежуток реально существующими данными. И тогда такие "неинициализированные данные" на самом деле будут находиться в образе на диске. И инициализированы они будут нулями. Опять таки это независимо от того, в какой секции они находятся. Всё выше сказанное относится к fasm, но может быть перенесено и на masm с учётом того, что masm несколько ограничивает программисту свободу выбора. ИМХО fasm демонстрирует более истинную картину.
Shoorup Статьи Агнера Фога на WASM.RU читай, от программ на ассемблере (ассемблерных вставок) требуется либо минимальный размер либо запредельная скорость. И то, и другое совместить редко удается -- обычно сосредотачиваются на чем то одном.
Code (Text): StringOut proc a1: lodsb ;загружаем символ из [esi] в al и увеличиваем esi or al,al ; если al равен 0 jz a2 ; то выход stosb ;копируем символ в [edi] и увеличиваем edi loop a1 ;уменьшаем ecx, если не равен 0, то повторяем итерацию a2: retn StringOut endp Эта процедура копирует нульзавершённую строку из [esi] в [edi] длиной не более чем ecx. Некий аналог lstrcpy из kernel32.dll.
Shoorup имхо, вобще что-то не то... наверно надо что-то вроде Code (Text): LODSB STOSB TEST AL, AL LOOPNZ a1
K10 ноль занесешь тогда. LODSB; загружаем STOSB; копируем TEST AL, AL; проверяем LOOPNZ a1; переходим если не ноль А если ноль то мы его занесем и выйдем из процедуры. Или я не правильно понял?
Shoorup Ага, завершающий ноль же тоже нужен... Ну и в ECX максимальный размер. Либо можно немного переделать и по ЕСХ определять количество скопированных байт если нужно, но тогда максимального размера не будет.
Я так понимаю, что все строки выводятся в мессбокс. А как происходит переход на следующую строку? Частоту процессора определяют по rdtsc? Или я опять не туда смотрю?
db 0Ah Там просто замеряется сколько тактов пройдёт за 1000 миллисекунд (герц - это количество тактов в секунду, в секунде 1000 миллисекунд). Code (Text): mov TimerLo,eax mov TimerHi,edx push 1000 ; DelayTime=1000 call _imp__Sleep@4 ; Sleep(DelayTime); rdtsc sub eax,TimerLo sbb edx,TimerHi mov TimerLo,eax mov TimerHi,edx
Не могу понять почему в один и тот же выделенный размер (как мне кажется) компилятор отказывается заносить содержимое регистров? Вот так: Code (Text): .data CPU_Vender dd 3 dup(?) String_null db 0 .code start: ... mov CPU_Vender, ebx mov CPU_Vender+4, edx mov CPU_Vender+8, ecx нормуль все, но если пытаюсь поменять CPU_Vender dd 3 dup(?) на CPU_Vender db 12 dup(?) , компилятор почему то ругается на 3 строчки с movами. Почему? В принципе понимаю, что для строчки достаточно 12 байт. Так dd 3 dup(?) создаю 3 раза по 4 байта (двойному слову), и так db 12 dup(?) создаю 12 байт по байту. Так какая разница как я выделил память?
Shoorup Если CPU_Vender db 12 dup(?) тогда должно быть Code (Text): mov dword ptr CPU_Vender, ebx mov dword ptr CPU_Vender+4, edx mov dword ptr CPU_Vender+8, ecx
Как всегда спасибо Mikl___ Единственное для себя не уяснил один момент - или где-то не дочитал или нет нигде такого: есть ли раличие в хранении данных в памяти? Запишу я слово в память или 2 байта - есть ли разница?
Всеравно не очень догоняю... уж не бейте за "жирафа"... Получается для х86 идет little-endian или "от младшего к старшему". Я выделяю и в первом и во втором случае место 12 байт. Процессор будет заносить содержимое регистров в эту область по "правилу от младшего к старшему" Какая разница как я выделил память? Почему во втором случае мне нужно переопределять dword ptr ?
Shoorup Пример из жизни -- Леонид Ильич Брежнев, с одной стороны, генеральный секретарь, с другой --папа, с третьей -- Лёня. Можно звать и так, и так, но папа -- он только для Галины Брежневой, а генеральный секретарь для всех остальных. Всё зависит от контекста. Переменная обявленная размером 4 байта для всех будет dword, а вот регистр AL может занести свои данные в любой из четырех байтов этой переменной обращаясь через byte ptr