Ассемблер (original) (raw)

Profile
Ассемблер, низкий уровень
Page Summary
[#] Ассемблер строить и жить помогает [#] mmx как замена 64 битных регистров общего назначения [#] CGI-программирование на ассемблере?!? – Легко! [#] 256 день [#] (без темы) [#] (без темы) [#] Про программирование [#] Радости профессии [#] Низкоуровневая оптимизация [#] 5. Ring-0, программирование на уровне бога [#] MadWizard [#] Программирование [#] Вот было дело.
Navigation
Свежие записиАрхивДрузьяЛичная информация
Июль 2010
12345678910111213141516171819202122232425262728293031
Ассемблер строить и жить помогает 17 мар, 2008 @ 13:25
maximpechkunov Была для одного проекта написана Dll на Watcom C. Версию уже не скажу - было достаточно давно - просто не помню - да для этого сообщества и не так уж важно.Но общая суть в следующем.В какой-то момент замечаем, что иногда результат работы не такой, какой ожидается. Гонялся я за этой ошибкой долго. Причём как оказалось увидеть её можно было только если уже готовую Dll'ку дизассемблировать и посмотреть глазками. Где-то в расчётах использовалась структура (причём без наворотов - самая простая). Ну и значит в какой-то момент в эту структура заносятся данные, примерно так:st.Num1 = dwNum1;st.Num2 = dwNum2;st.Num3 = dwNum3;st.Num4 = dwNum4;Так вот: первые три присваивания отрабатываются, а четвёртое - нет! Этой строки просто не оказывается в результирующем коде. Если б не знание ассемблера, то даже не знаю как долго бы искал эту ошибку. Причём если после каждой строки выводить, что в структуру записалось, то всё отрабатывается правильно. А если выполнять все присваивания последовательно (без промежуточных проверок и вывода результатов), то последнее теряется!!!В результате какое-то время работающий код был примерно таким:st.Num1 = dwNum1;st.Num2 = dwNum2;st.Num3 = dwNum3;st.Num4 = dwNum4;st.Num4 = dwNum4;Потом нашли (в списке исправленных ошибок), что такой глюк был признан - скачали новую версию - проверили... хм. работает - убрали дублёж присваивания, чтобы никого не смушал.Вот такие были у нас долбанутые весёлые будни программистов...Upd: К этому случаю очень подходит старый анекдот...Приходит один ассемблерщик к другому. Тот ему код свой показывает.Первый и спрашивает: _- А зачем у тебя тут подряд два безусловных перехода?_На что и идёт ответ, ставший уже (позже) классическим: - А вдруг первый не сработает?(Оставить комментарий)
mmx как замена 64 битных регистров общего назначения 7 июл, 2007 @ 15:50
insooo Следующая проблема у меня, да.Нужно написать "оптимизированные" низкоуровневые процедуры для обработки примитивов типов данных в одной программе на с++. Проект под линукс на 32-битной x86 платформе и этот самый тип данных просто typedef uint64_t prim_t;, т.е. 64 битное целое. Операции довольно нетривиальные, но сводятся к циклическим сдвигам и логическим операциям по маскам.Соответственно три подхода: - использовать 32 битные регистры, загружать данные в две части в два регистра, следить за переносами, адресовать маски по частям и т.д.- Оперировать непосредственно с памятью.- Загружать данные в mmx регистры и работать как с единым целым.Для начала я решил написать Си-версию и транслировать в ассемблерный код (gcc 4.1.2 -O3). Компилятор использовал первый подход. Ну вот собственно и вопрос, какой подход использовать? И насколько описанные операции медленнее на сопроцессоре?Спасибо, и извините если вопрос ламерский)Музыка: Björk - Earth Intruders / Volta / 2007 (2 комментария | Оставить комментарий)
CGI-программирование на ассемблере?!? – Легко! 28 ноя, 2006 @ 01:35
eugene_ivanov В этой статье я хочу рассказать о CGI интерфейсе вообще, его реализации для windows и использовании при написании CGI-программ языка ассемблер в частности. В рамки этой статьи не входит полное описание CGI, так-как в Интернете материала по этому вопросу просто море и пересказывать все это здесь я просто не вижу смысла.Вот в общем и все о чем я хотел написать, не знаю насколько это все окажется Вам полезным, но скажу что у меня работает сервер интрасети используя скрипты на ассемблере. Каюсь, больших оснований делать это не было, но все же я сделал это сначала просто из эстетических соображений и некоторой не охоты учить перл/php или что-то еще. НО я никоим образом не отговариваю Вас учить перл, а наоборот скажу что сделать это нужно, и даже очень нужно, это я понял позже, но все же считаю, что на сильно загруженных серверах, где скорость выполнения, загрузки и объем памяти занимаемый приложением играет решающую роль cgi-скрипты, написанные на ассемблере займут свое достойное место.Читать всю статью! Потрясно!(16 комментариев | Оставить комментарий)
256 день 13 сент, 2006 @ 11:28
eugene_ivanov Всех поздравляю с днём программиста. Желаю чистого кода, умных свежих идей.(1 комментарий | Оставить комментарий)

| | 30 май, 2006 @ 09:46 | | ---------------------- |

eugene_ivanov Директор по безопасности Oracle утверждает, что рынок программного обеспечения так нашпигован недобросовестными софтверными компаниями, что «вы бы не сели на самолет, построенный программистами». Выступив в четверг на конференции WWW2006 в Эдинбурге, Мэри-Энн Дэвидсон заявила, что «большинство программистов не обучено думать в терминах безопасности и надежности» и вместо этого они насаждают культуру «patch, patch, patch», что обходится отрасли в $59 млрд.(7 комментариев | Оставить комментарий)

| | 17 мар, 2006 @ 14:15 | | ---------------------- |

eugene_ivanov В раздел Статьи — Базовые сервисы добавлена статья Пишем на WinAPI с ''нуля''.(1 комментарий | Оставить комментарий)
Про программирование 9 окт, 2005 @ 17:07
eugene_ivanov Самое главное - это делать то, что нужно. и не сваливать на нехотенье... а делать то, как задумано.То есть, как ты задумал сделать - и нужно к этому стремиться.(Оставить комментарий)
Радости профессии 28 май, 2005 @ 19:17
eugene_ivanov Почему заниматься программированием интересно? Какими радостямивознаграждаются те, кто им занимается? Во-первых, это просто радость, получаемая при создании чего-либо своимируками. Как ребенок радуется, делая куличики из песка, так и взрослыйполучает удовольствие, создавая какие-либо вещи, особенно если сам их ипридумал. Я думаю, что этот восторг - отражение восторга Господа, творящегомир, восторга, проявляющегося в индивидуальности и новизне каждого листочкаи каждой снежинки. Во-вторых, это удовольствие создавать вещи, которые могут быть полезныдругим людям. Глубоко в душе мы испытываем потребность в том, чтобы другиеиспользовали результаты нашего труда и считали их полезными. В этомотношении программная система по своей сути - то же, что и изготовленнаяребенком подставка для карандашей "папе в подарок". В-третьих, это очарование создания сложных головоломных объектов,состоящих из взаимодействующих движущихся частей и наблюдения за их работой,круг за кругом демонстрирующей результаты изначально заложенных принципов.Компьютер с работающей на нем программой обладает доведенным до высшегопредела очарованием игорного или музыкального автомата. В-четвертых, это радость, получаемая от неизменного узнавания нового,проистекающего из неповторимой природы задачи. В том или ином отношениизадача всегда ставится по-новому, и тот, кто ее решает, получает новыезнания - либо практические, либо теоретические, либо те и другие вместе. Наконец, наслаждение доставляет работа со столь податливым материалом.Программист, подобно поэту, работает почти непосредственно с чистой мыслью.Он строит свои замки в воздухе и из воздуха, творя силой воображения. Труднонайти другой материал, используемый в творчестве, который столь же гибок,прост для шлифовки или переработки и доступен для воплощения грандиозныхзамыслов. (Как мы позднее увидим, такая податливость таит свои проблемы.) Однако программная конструкция, в отличие от поэтических творений,реальна, в том смысле, что она движется и работает, производя видимыерезультаты, которые отделимы от самой конструкции. Она печатает результаты,рисует картинки, производит звуки, приводит в движение рычаги. В наше времяосуществилось волшебство мифа и легенды. С клавиатуры вводится верноезаклинание, и экран монитора оживает, показывая то, чего никогда не было ине могло быть. Таким образом, программирование доставляет удовольствие, посколькуотвечает глубокой внутренней потребности в творчестве и удовлетворяетчувственные потребности, которые есть у всех нас.(15 комментариев | Оставить комментарий)
Низкоуровневая оптимизация 4 сент, 2004 @ 14:34
eugene_ivanov Быстрые умножения и деления. Умножения на степени двойки (2, 4, 8, 16) заменяются логическими сдвигами (соответственно на 1, 2, 3, 4 разрядов влево), инструкцией LEA или последовательными сложениями: x *= 8;shl eax, 3 ; Сдвинуть на 3 разряда влево — так делают LCC32, D, MinGW, ; MSVC++ (оптимизация по размеру), FreePascal и BCClea ecx, DWORD PTR [eax*8] ; MSVC++ (оптимизация по скорости)add eax, eax ; eax = x * 2 — Intel C++ Compileradd eax, eax ; eax = x * 4add eax, eax ; eax = x * 8Последние два варианта на современных процессорах работают быстрее, так как инструкции LEA и ADD могут выполняться параллельно с другими инструкциями на разных конвейерах процессора. Некоторые компиляторы умеют представлять умножение на 7 как умножение на 8, а затем вычитание сомножителя. Точно так же умножение x на пять представляется как x*4 + x, которое можно выполнить одной быстрой инструкцией LEA:x *= 7;; компиляторы MinGW, MSVC++lea ecx, DWORD PTR [eax*8] ; Умножить eax на восемьsub ecx, eax ; Вычесть eax; компилятор Borland C++mov edx, eaxshl eax,3 ; Умножить eax на 8, вычесть edx. Слегка медленнее, чем LEA,sub eax,edx ; так как SHL может выполняться только на U-конвейере; компиляторы LCC32, Free Pascal и D используют гораздо более медленный вариант:imul eax, 07x *= 5;; компиляторы MinGW, MSVC++, LCC, Borland C++lea eax, DWORD PTR [eax*4 + eax] ; Быстрый способ умножить eax на 5; компиляторы D и Free Pascalimul eax, 05 ; Обычное умножение работает намного медленнееДеление на константу можно заменить умножением на обратную константу, которое выполняется слегка быстрее. Эту особенность учитывают компиляторы MinGW, MSVC++, LCC:unsigned int x; // Для чисел со знаком требуется чутьx /= 3; // более сложный ассемблерный трюкmov eax, aaaaaaabH ;Записываем в eax число (2^33)/3mul [ebp-4] ;Часть произведения x * (2^33/3), начиная с 32-го разряда, ;будет записана в edx. В результате edx = (x / 3) * 2shr edx, 1 ;edx = edx / 2 = x / 3Из-за погрешности при переводе в двоичную систему счисления приходится сохранять один дополнительный разряд. Так, если бы мы умножили 3 на (2^32)/3, в EAX получили бы FF FF FF FF, а в EDX — ноль. Так как мы отбрасываем EAX, в результате деления на три получился бы ноль, а не единица. Поэтому приходится умножать на (2^33)/3, а затем делить на 2.Музыка: Special Prank - Baby [ПЕРЕЗАГРУЗКА] (1 комментарий | Оставить комментарий)
5. Ring-0, программирование на уровне бога 31 июл, 2004 @ 17:20
eugene_ivanov Свобода! Разве вы не любите ее? В ring-0 у нас нет никаких огpаничений, никакие законы не pаспpостpаняются на нас. Из-за некомпетентности Микpософта у нас есть множество путей, чтобы попасть на уpовень, на котоpый (теоpетически) мы не можем попасть. Тем не менее, мы можем это сделать под ОСями Win9x. Глупцы из Micro$oft оставили незащищенными таблицу пpеpываний, напpимеp. Это гигантская бpешь в безопасности, на мой взгляд. Hо какого чеpта, если мы можем написать виpус, используя его, это не бpешь, это пpосто подаpок! ;) Получение доступа к Ring-0 Ок, я объясню самый пpостой способ с моей точки зpения, котоpым является модификация IDT. IDT (Interrupt Descriptor Table) не является фиксиpованным адpесом, поэтому чтобы найти ее местоположение, мы должны использовать специальную инстpукцию, напpимеp SIDT. -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-· ------------------------------------------------------------¬ ¦ SIDT - Сохpаняет pегистp IDT (286+, пpивилегиpованная) ¦ L------------------------------------------------------------ + Использование: SIDT dest + Модифициpуемые флаги: none Сохpаняет pегистp IDT в указанный опеpанд. Такты Размеp Operands 808X 286 386 486 Байты mem64 - 12 9 10 5 0F 01 /1 SIDT mem64 сохpаняет IDTR в mem64 -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·Hа случай, если еще не понятно, для чего мы используем SIDT, поясню: она помещает смещение в фоpмате FWORD (WORD:DWORD), по котоpому находится IDT. И, если мы знаем, где находится IDT, мы можем модифициpовать вектоpы пpеpываний и сделать так, чтобы они указывали на наш код. Это показывает нам ламеpность Micro$oft'овских кодеpов. Давайте пpодолжим нашу pаботу. После изменений вектоpов так, чтобы они указывали на наш код (и сохpанения их для последующего восстановления), нам остается только вызвать небольшой код, чтобы пеpейти в Ring-0, модифициpовав IDT. ;---[ CUT HERE ]------------------------------------------------------------- .586p ; Бах... пpосто для забавы. .model flat ; Хехехе, я люблю 32 бита ;)extrn ExitProcess:PROCextrn MessageBoxA:PROCInterrupt equ 01h ; Hичего особенного .data szTitle db "Ring-0 example",0 szMessage db "I'm alive and kicking ass",0 ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Ок, все это для вас пока что вполне понятно, pазве не так? :) ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; .code start: push edx sidt [esp-2] ; Помещаем адpес таблицы пpеpываний ; в стек pop edx add edx,(Interrupt*8)+4 ; Получаем вектоp пpеpываний ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Это очень пpосто. SIDT, как я объяснял pаньше, помещает адpес IDT в ; ; память, и для того, чтобы нам было пpоще, мы используем непосpедственно ; ; стек. Поэтому следующей инстpукцией идет POP, котоpый должен загpузить в ; ; pегистp, в котоpый мы POP'им (в нашем случае - это EDX), смещение IDT. ; ; Следующая стpока служит для позициониpования на то пpеpывание, котоpое ; ; нам нужно. Это как мы игpали с IVT в DOS... ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; mov ebx,[edx] mov bx,word ptr [edx-4] ; Whoot Whoot ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Достаточно пpосто. Пpосто сохpаняем содеpжимое EDX в EBX для ; последующего восстановления. ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; lea edi,InterruptHandler mov [edx-4],di ror edi,16 ; Пеpемещаем MSW в LSW mov [edx+2],di ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Говоpил ли я pаньше, насколько это пpосто? :) Hа выходе в EDI у нас ; смещение нового обpаботчика пpеpывания, а тpи стpоки спустя мы помещаем ; этот обpаботчик в IDT. А зачем здесь нужен ROR? Ок, не имеет значения, ; будете ли вы использовать ROR, SHR или SAR, так как здесь это ; используется для смещения содеpжимого веpхнего слова в нижнее. ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; push ds ; Безопасность, безопасность... push es int Interrupt ; Ring-0 пpиходит отсюда!!!!!!! pop es pop ds ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Мммм... Интеpесно. Я заPUSHил DS и ES в целях безопасности, чтобы ; ; пpедотвpатить pедкие, но возможные глюки, но данный код будет pаботать и ; ; без этого, повеpьте мне. Мы вызываем обpаботчик пpеpывания... И ; ; оказываемся в RING0. Код пpодолжается с метки InterruptHandler. ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; mov [edx-4],bx ; Восстанавливаем стаpый обpаботчик ror ebx,16 ; ROR, SHR, SAR... кого это заботит? mov [edx+2],bx back2host: push 00h ; Флаги MessageBox push offset szTitle ; Заголовок MessageBox push offset szMessage ; Само сообщение push 00h ; Владелец MessageBox call MessageBoxA ; Собственно вызов функции push 00h call ExitProcess ret ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Hичего не остается делать, как восстановить оpигинальные вектоpа ; ; пpеpываний, котоpые мы сохpанили в EBX. Кpуто, не пpавда ли? :) А затем ; ; мы возвpащаем упpавление носителю. (По кpайней меpе это пpедполагается ; ; ;) ). ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; InterruptHandler: pushad ; Здесь идет ваш код :) popad iretd end start;---[ CUT HERE ]-------------------------------------------------------------Музыка: 01 - The Wind of Chimes (Part One And Part Two) (6 комментариев | Оставить комментарий)
MadWizard 24 июл, 2004 @ 23:12
eugene_ivanov MadWizard.orgОтличные вещи для программиста!(Оставить комментарий)
Программирование 3 июн, 2004 @ 13:08
eugene_ivanov http://subscribe.ru/catalog/comp.soft.prog.urisprogРассылка "Познавательное программирование"В этой рассылке ПОЛНОСТЬЮ публикуются редкие эксклюзивные статьи по программированию.Музыка: Yello (Оставить комментарий)
Вот было дело. 24 май, 2004 @ 20:01
eugene_ivanov Вот было дело:Отвечает СтасДоброе время суток, Alexander!Потому, что не предусмотрено. Набор команд ограничен.Сейчас, ассемблер развивается, команды добавляются, например PUSH число, или CMP память,число не существовали на 8086.Может со временем и эта появится. Хотя по моему и так достаточно.--------------------------------------------------------------------------------Ответ отправлен: 16.05.2004, 03:12Отправитель: Стас Ну что я скажу? Смешно, честное слово. :)Команды CMP память, число существовали ещё с 8088 !А насчёт PUSH imm скажу так - они существуют с 80286, так что можно считать, что тоже с самого начала, так как, только начиная с 80386, можно говорить о серьёзной работе с защищённым режимом и вообще комфортными условиями программирования. Также 80386 стоит копейки, не считая того, что и Intel 200 Мгц тоже стоит сейчас копейки, так что даже думать о компах менее Pentium просто стыдно и ГЛУПО. Пожалейте своё время и голову.Музыка: Сергей Попов, радио "Рандеву" - 15 ноября 2002 года, часть 1 (5 комментариев | Оставить комментарий)