it-place.net > Уроци > Други
Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 Асемблер за по-напреднали: Малки трикове...
  1. Малки трикове-Аритметика
  2. Малки трикове-Функции Min/Max
  3. Използване на инструкцията LEA
  4. Цикли
  5. Проверка на сложни условия
     
Автор  johnfound (11.06.2004 17:31)  съобщение до автора
Погледнат  3224 пъти  добави към любими
Оценка  добави коментар
Гласове  1  изпрати на приятел
Коментари  (0)  абонирай се за Други
    Страница 1 / 5

 



В тази статия ще изложа някои кратки трикове, които могат да се реализират само на асемблер и правят програмата по-къса и/или по-бърза.
 
Предполагам, че за разбирането на тези трикове се изисква базисни знания за инструкциите на x86, както и познания за бройни системи - специално двоична и шестнайсетична, както и за основните бинарни логически операции.

По-начинаещите също могат да прочетат статията и дори и да не разберат всичко, могат да питат, а и някои от примерите могат да им помогнат да си изградят "мислене на асемблер".
 
1. Аритметика:

1.1 Изчисляване на абсолютна стойност.

Най-късото решение известно до сега е:
CODE
1
2
3
.abs:
    
neg   eax
     jl
    .abs

Дължина 4 байта. Кода работи така:

а) Ако eax съдържа отрицателно число на входа, след инверсията резултата е по-голям от 0, прехода не се изпълнява и на изхода получаваме положителна стойност.

б) Ако eax съдържа положително число, след инверсията, резултата е по-малък от нула, прехода се изпълнява и попадаме в ситуация а) когато имаме отрицателно число на входа.

Този трик е по-известен във варианта:
CODE
1
2
3
.abs:
     
neg   eax
      js
    .abs

Този вариант има обаче един недостатък, че има скрит бъг, който води до безкраен цикъл. Наистина, ако на входа се подаде числото $80000000, което няма положителен еквивалент, се получава безкраен цикъл и програмата ще заспи. При варианта с jl проблема се решава, защото при него се използва и флага за препълване (инструкцията е за работа с числа със знак) който при "neg $80000000" се вдига, индицирайки грешен знак и прехода не се изпълнява.

Горният вариант е най-късото възможно решение, но дали е най-бързото. При новите процесори - не, заради прехода. Въобще при последните модели процесори, условните преходи трябва да се избягват, ако искаме да получим най-високата скорост на изпълнение.

Ето един вариант на abs, без използването на преходи:

CODE
1
2
3
      cdq
     
xor   eax, edx
     
sub   eax, edx

Как работи този код:

Знаем, че:

 -x = (not x) + 1 = (not x) - (-1);       (1)
 
От друга страна знаем, че:

not x = x xor (-1);    (2)

Инструкцията cdq (convert dword to qword) запълва edx със знаковият бит на eax - тоест ако eax e положително, edx = 0, а ако eax е отрицателно, edx=-1.

Сега, ако на входа на кода се подаде положително число, edx = 0 и операциите върху eax са:

  xor  eax, 0
  sub  eax, 0
 
Което очевидно няма да промени стойността му.

Ако eax е отрицателно, ще имаме:

  xor  eax, -1  ( not eax от (2) )
  sub  eax, -1  ( събирането с 1 от (1) )
 
Което ще ни даде точно neg eax.

Този код ще се изпълни по-бързо на компютри Pentium и по-нови.
Недостатъците му са два:
  1. задължително трябва да се използват eax/edx (ax/dx)
  2. Губи се съдържанието на edx.
  3. инструкцията cdq не е от най бързите в новите процесори.
 
Решението на проблеми 1 и 3 е замяната на cdq със еквивалента и:

CODE
1
2
 mov  edx, eax
  sar  edx
, 31

Така получаваме окончателният код:

CODE
1
2
3
4
      mov  edx, eax
      sar  edx
, 31
     
xor  eax, edx
     
sub  eax, edx

Този код с дължина 9 байта е най-бърз от показаните, ако се направи правилно сдвояване на кода, за използване на двата конвеера на новите процесори. Тоест между инструкциите трябва да се вмъкнат други инструкции от кода, които не са свързани с тези и могат да се изпълняват паралелно.

Допълнително предимство е, че могат да се използват произволни два регистъра.



  Следваща страница >> 


Ключови думи: аритметика трик асемблер


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 За автора: johnfound  
Занимавам се с програмиране от 1983 година. Експерт по програмиране на Delphi и Assembler. Разбира се понякога работя и на PHP, Perl и др.под. В момента се занимавам с програмиране на автоматизирани системи за производство в голяма немска фирма в България. От 2003г започнах проект с отворен код, целта на който е разработката на съвременна среда и средства за програмиране на асемблер под Windows, конкурентна на езиците от високо ниво. Подробности за проекта можете да намерите на: http://fresh.flatassembler.net
   
 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

 

 
  • Интересно от Софтуер
 



IT-PLACE.NET © 2004 - 2008