<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0MBR3k7fyp7ImA9WhRbFk8.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983</id><updated>2012-02-07T10:30:56.707-03:00</updated><category term="Outros" /><category term="Wireless" /><category term="MySQL" /><category term="Dicas Hackers" /><category term="CSS" /><category term="Rede" /><category term="Dicas de segurança" /><category term="Anti-vírus" /><category term="ASP" /><category term="Windows" /><category term="Java" /><category term="Oracle" /><category term="C\C++" /><category term="Programas" /><category term="Linguagem BATCH" /><category term="PHP" /><category term="Access" /><category term="Flash" /><category term="Assembly" /><category term="Games" /><category term="LINUX" /><category term="HARDWARE" /><category term="Ruby" /><category term="mac" /><category term="Delphi" /><category term="HTML" /><category term="Visual Basic" /><category term="Downloads" /><category term="Séris" /><category term="JavaScript" /><category term=".NET" /><title>ProgMaster</title><subtitle type="html">Tudo sobre programação, PHP, asp, Delphi, visual basic, C++, C#, SQL e muito mais...</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blogprogramadores.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>383</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/Otim" /><feedburner:info uri="blogspot/otim" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DU8DQ308eip7ImA9WhRUFUU.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-7602260902830946732</id><published>2012-01-26T11:22:00.001-03:00</published><updated>2012-01-26T11:24:32.372-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-26T11:24:32.372-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Outros" /><title>Veja agora como você será monitorado</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-family: inherit; font-size: small;"&gt;O google lança sua nova "Política de Privacidade" que irá monitorar você 24 horas por dia em tudo que você faz na internet seja direto ou indiretamente por meio dos produtos fornecidos pela google ou pelos anúncios e vínculos de outros sites que utilizem os produtos da google. &lt;br /&gt;
&lt;br /&gt;
A Nova Política de Privacidade explica:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: inherit; font-size: small;"&gt;&lt;br /&gt;
•&amp;nbsp;&amp;nbsp; &amp;nbsp;Quais informações são coletadas e por que elas são coletadas. &lt;br /&gt;
•&amp;nbsp;&amp;nbsp; &amp;nbsp;Como serão usadas essas informações. &lt;br /&gt;
•&amp;nbsp;&amp;nbsp; &amp;nbsp;As opções que oferecem, incluindo o modo de acessar e atualizar informações.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: inherit; font-size: small;"&gt;&lt;br /&gt;
Veja no link abaixo toda a nova política de privacidade do Google:&lt;br /&gt;
&lt;a href="http://www.google.com.br/intl/pt-BR/policies/privacy/preview/" target="_blank"&gt;http://www.google.com.br/intl/pt-BR/policies/privacy/preview/&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-7602260902830946732?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2frxDkD2mXLYl3t746lKC5vnHJw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2frxDkD2mXLYl3t746lKC5vnHJw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2frxDkD2mXLYl3t746lKC5vnHJw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2frxDkD2mXLYl3t746lKC5vnHJw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/6JkVAX84A5U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/7602260902830946732/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2012/01/veja-agora-como-voce-sera-monitorado.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/7602260902830946732?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/7602260902830946732?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/6JkVAX84A5U/veja-agora-como-voce-sera-monitorado.html" title="Veja agora como você será monitorado" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2012/01/veja-agora-como-voce-sera-monitorado.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMBQno4fCp7ImA9WhRXEEk.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-5193450138290463279</id><published>2011-12-16T10:48:00.001-03:00</published><updated>2011-12-16T10:50:53.434-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-16T10:50:53.434-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C\C++" /><title>Como converter AnsiString para char[] (C ++ Builder)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="JUSTIFY" style="color: black; font-family: inherit; margin-bottom: 0cm; margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;b&gt;&lt;span style="font-size: small;"&gt;O exemplo a seguir leva um &lt;i&gt;Button&lt;/i&gt;, um &lt;i&gt;Label&lt;/i&gt; e 4 &lt;i&gt;Edits&lt;/i&gt; no &lt;i&gt;Form&lt;/i&gt;. Quando o usuário dá um clique no botão, o programa realiza algumas conversões entre AnsiString e char[] e vice-versa:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm; margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;//-------------------------------------------------------------&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style="color: green; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&lt;b&gt;#include &lt;vcl.h&gt;&lt;/vcl.h&gt;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;
&lt;span style="color: green; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&lt;b&gt;#pragma hdrstop&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;

&lt;span style="color: green; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&lt;b&gt;#include "Unit1.h"&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;
&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;//-------------------------------------------------------------&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style="color: green; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&lt;b&gt;#pragma package(smart_init)&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;
&lt;span style="color: green; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&lt;b&gt;#pragma resource "*.dfm"&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TForm1 &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;*&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Form1&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;//-------------------------------------------------------------&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;b&gt;&lt;span style="color: navy;"&gt;__fastcall &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TForm1&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TForm1&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TComponent&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;* &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Owner&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;        : &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TForm&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Owner&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: red; font-family: inherit; font-size: small;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: red; font-family: inherit; font-size: small;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;
&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;//-------------------------------------------------------------&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;b&gt;&lt;span style="color: navy;"&gt;void __fastcall &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TForm1&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;FormCreate&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TObject &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;*&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Sender&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: red; font-family: inherit; font-size: small;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Edit1 &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;-&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Text &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;"String inicial de Edit1"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;;        &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: red; font-family: inherit; font-size: small;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;//-------------------------------------------------------------&lt;/i&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;b&gt;&lt;span style="color: navy;"&gt;void __fastcall &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TForm1&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Button1Click&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;TObject &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;*&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Sender&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: red; font-family: inherit; font-size: small;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;b&gt;&lt;span style="color: navy;"&gt;char &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;100&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;] = &lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;"Valor inicial de buffer"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Label1 &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;-&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Caption &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Edit2 &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;-&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Text &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;0&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: olive;"&gt;// converte Text de AnsiString para char*&lt;/span&gt;&lt;/i&gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;strcpy &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;, &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Edit1&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Text&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;.&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;c_str&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;());&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-left: 0.6cm; margin-right: 1.1cm;"&gt;&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Edit3 &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;-&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Text &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;0&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Edit4 &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;-&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Text &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;= (&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;String&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;) &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;0&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;]+ &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;1&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;] + &lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;buffer&lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;i&gt;&lt;span style="color: #c000c0;"&gt;2&lt;/span&gt;&lt;/i&gt;&lt;span style="color: red;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="color: red; font-family: inherit; font-size: small;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;
&lt;i&gt;&lt;span style="color: olive; font-family: inherit; font-size: small;"&gt;&lt;i&gt;//-------------------------------------------------------------&lt;/i&gt;&lt;/span&gt;&lt;/i&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-5193450138290463279?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/e8MRKnrkOqCUxvovY5ysWgfm2cw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e8MRKnrkOqCUxvovY5ysWgfm2cw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/e8MRKnrkOqCUxvovY5ysWgfm2cw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e8MRKnrkOqCUxvovY5ysWgfm2cw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/wbiadH-VJ2s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/5193450138290463279/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/12/como-converter-ansistring-para-char-c.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5193450138290463279?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5193450138290463279?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/wbiadH-VJ2s/como-converter-ansistring-para-char-c.html" title="Como converter AnsiString para char[] (C ++ Builder)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/12/como-converter-ansistring-para-char-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkECR3w6fip7ImA9WhRQFUg.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-711921547928826643</id><published>2011-12-10T19:04:00.000-03:00</published><updated>2011-12-10T19:04:26.216-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-10T19:04:26.216-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PHP" /><title>Como copiar arquivos com php?</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;O código abaixo explica como copiar arquivos dentro de um servidor php, permitindo a qualquer momento mudar determinados arquivos de diretório, muito útil em backups.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
// copia o arquivo testes.txt para o diretório /imagens&lt;br /&gt;
&amp;nbsp; $de = "/site/public_html/testes.txt";&lt;br /&gt;
&amp;nbsp; $para = "/site/imagens/testes.txt";&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
&amp;nbsp; if(copy($de, $para))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; echo "Arquivo copiado com sucesso.";&lt;br /&gt;
&amp;nbsp; else&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; echo "Não foi possível copiar o arquivo.";&lt;br /&gt;
?&amp;gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-711921547928826643?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nCC0fymUL19J-2go5coyoSDnR4A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nCC0fymUL19J-2go5coyoSDnR4A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nCC0fymUL19J-2go5coyoSDnR4A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nCC0fymUL19J-2go5coyoSDnR4A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/LrKMxvUqNA0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/711921547928826643/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/12/como-copiar-arquivos-com-php.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/711921547928826643?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/711921547928826643?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/LrKMxvUqNA0/como-copiar-arquivos-com-php.html" title="Como copiar arquivos com php?" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/12/como-copiar-arquivos-com-php.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUADRnc9fSp7ImA9WhRQFU8.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-9072808513322386776</id><published>2011-12-10T10:26:00.001-03:00</published><updated>2011-12-10T10:29:37.965-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-10T10:29:37.965-03:00</app:edited><title>ProgMaster - Validar Dados 1.0 + Source(Código-Fonte)</title><content type="html">Este programa testa dados pessoais como PIS , CNPJ , CEP , Título de Eleitor , CNH , Cartão de Crédito e CPF , foi&amp;nbsp;Desenvolvido para pessoas que não querem revelar seus dados para criar uma conta em algum site ou outra coisa.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;a href="http://www.4shared.com/file/uoR29xAW/ProgMaster_-_Validar_dados_10.html"&gt;Download&lt;/a&gt;&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;Veja&amp;nbsp;uma imagem do programa :&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;a href="http://2.bp.blogspot.com/-OY6mN2xbtw0/TuNdxGJ8msI/AAAAAAAAAAg/PZ_2V6pSscM/s1600/Print.jpg" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="219" mda="true" src="http://2.bp.blogspot.com/-OY6mN2xbtw0/TuNdxGJ8msI/AAAAAAAAAAg/PZ_2V6pSscM/s320/Print.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-9072808513322386776?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZJ_ZF9v_mceqQJ4cXzoGqqEvHK8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZJ_ZF9v_mceqQJ4cXzoGqqEvHK8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZJ_ZF9v_mceqQJ4cXzoGqqEvHK8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZJ_ZF9v_mceqQJ4cXzoGqqEvHK8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/yr7sE78bhgw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/9072808513322386776/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/12/progmaster-validadar-dados-10.html#comment-form" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/9072808513322386776?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/9072808513322386776?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/yr7sE78bhgw/progmaster-validadar-dados-10.html" title="ProgMaster - Validar Dados 1.0 + Source(Código-Fonte)" /><author><name>Saberling 2011</name><uri>http://www.blogger.com/profile/02174946110768497770</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-OY6mN2xbtw0/TuNdxGJ8msI/AAAAAAAAAAg/PZ_2V6pSscM/s72-c/Print.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/12/progmaster-validadar-dados-10.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04FSHY5eip7ImA9WhRRFks.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-5395172854823224582</id><published>2011-11-30T11:05:00.000-03:00</published><updated>2011-11-30T11:05:19.822-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-30T11:05:19.822-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Outros" /><title>Banco de dados em Firebird com milhares de ENDEREÇOS e CEP’s de todo o Brasil!</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h2 class="h2-simulate-h1-size-underline"&gt;&lt;br /&gt;
&lt;/h2&gt;&lt;div style="float: right; margin-left: 10px;"&gt; &lt;div class="share-this"&gt;   &lt;div class="facebook-share-button"&gt;  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id="content-item-above"&gt;                                   &lt;span class="content-item-above-widget-block"&gt;                           &lt;/span&gt;                                  &lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;img alt="" class="size-full wp-image-447 aligncenter" height="400" src="http://www.resumoti.com.br/wp-content/uploads/2011/04/BancoFirebirdCEP.jpg" title="BancoFirebirdCEP" width="400" /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;Banco de dados em Firebird com milhares  de endereços cadastrados, importado do banco de dados do IBGE, muito  útil para sistemas que possue cadastros extenso que contém endereços a  serem preenchidos!&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt; &lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;span id="more-446"&gt;&lt;/span&gt;- Retirado os  acentos no nomes do logradouros, facilitando assim a busca, já que  nativamente o Firebird DIFERENCIA palavras acentuadas.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt; &lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;- Todas os nomes estão em maiúsculos, facilitando assim a busca, já que nativamente o Firebird é CASE SENSITIVE.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt; &lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;- As cidades já estão com seus respectivos códigos, inserir para facilitar no caso de utilizar a NF-e.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt; &lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;Em fim, um ótimo recurso para se utilizar e incrementar mais ainda os seus sistemas.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
link : &lt;a href="http://hotfile.com/dl/116023163/ad197a6/ENDERECO.FDB.html" target="_blank" title="Banco de dados firebird com milhares de endereços"&gt;http://hotfile.com/dl/116023163/ad197a6/ENDERECO.FDB.html&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-5395172854823224582?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/r4lnmBz4QGhSbg88LdmKrOegkKM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/r4lnmBz4QGhSbg88LdmKrOegkKM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/r4lnmBz4QGhSbg88LdmKrOegkKM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/r4lnmBz4QGhSbg88LdmKrOegkKM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/vThZo0rW4U0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/5395172854823224582/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/11/banco-de-dados-em-firebird-com-milhares.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5395172854823224582?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5395172854823224582?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/vThZo0rW4U0/banco-de-dados-em-firebird-com-milhares.html" title="Banco de dados em Firebird com milhares de ENDEREÇOS e CEP’s de todo o Brasil!" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/11/banco-de-dados-em-firebird-com-milhares.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMHQns-cSp7ImA9WhRRFUs.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-5288320523020014655</id><published>2011-11-29T09:01:00.002-03:00</published><updated>2011-11-29T09:07:13.559-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-29T09:07:13.559-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dicas de segurança" /><category scheme="http://www.blogger.com/atom/ns#" term="Programas" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas Hackers" /><title>Programa para rastrear computador perdido ou roubado (Free)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;br /&gt;
&lt;div class="materia-titulo"&gt;&lt;h2&gt;Ferramenta gratuita permite monitorar até três dispositivos.&lt;br /&gt;
&lt;/h2&gt;&lt;/div&gt;&lt;div class="materia-conteudo entry-content" id="materia-letra"&gt;&lt;div&gt;&lt;div&gt;&lt;div class="foto componente_materia midia-largura-300"&gt;&lt;img alt="Prey é um programa gratuito para rastreamento quando o notebook for perdido (Foto: Reprodução)" height="156" src="http://s.glbimg.com/jo/g1/f/original/2011/06/06/prey.jpg" title="Prey é um programa gratuito para rastreamento quando o notebook for perdido (Foto: Reprodução)" width="300" /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Prey é um programa gratuito para rastreamento&lt;br /&gt;
quando o notebook for perdido (Foto: Reprodução)&lt;/b&gt;&lt;/div&gt;Os computadores portáteis tornaram-se ferramentas poderosas para quem  precisa contar com um equipamento que possa ser levado a qualquer lugar.  Porém, ninguém está livre de perder o equipamento, seja em situação de  roubo, extravio ou esquecimento. Recentemente a &lt;a href="http://g1.globo.com/mundo/noticia/2011/06/policia-recupera-laptop-gracas-a-programa-que-envia-localizacao-e-fotos-para-o-dono.html"&gt;polícia recuperou um laptop graças a programa que envia localização&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Dependendo da importância dos arquivos contidos nele, o prejuízo maior  não é nem o valor da máquina, mas as informações armazenadas. Para  prevenir, valem os cuidados de sempre, mas que tal contar com um  aplicativo gratuito que disponibiliza a localização do computador num  serviço na internet?&lt;br /&gt;
Nesta coluna, irei apresentar o &lt;a href="http://preyproject.com/" target="_blank"&gt;Prey Project&lt;/a&gt;,  um aplicativo de código aberto que permite rastrear o computador em  caso de perda. O programa pode ser instalado no Windows, Linux, Mac e  Android. A localização do equipamento fica disponível num serviço na  internet, em que o usuário deve estar cadastrado previamente. A  modalidade gratuita permite que sejam adicionados até três equipamentos  para o monitoramento. Caso seja necessário adicionar mais computadores, é  possível contar com a modalidade paga.&lt;br /&gt;
O instalador do Prey Project pode ser &lt;a href="http://preyproject.com/download" target="_blank"&gt;baixado no site do fabricante&lt;/a&gt;.  Escolha a opção de download correspondente ao sistema operacional no  computador a ser rastreado. Durante o processo de instalação, é  necessário criar um usuário para acessar o painel de monitoramento no  site. Esse usuário poderá ser adicionado em outras duas instalações de  computadores, que também poderão ser rastreados. Para usuários do  sistema operacional Windows, pode ser necessário autorizar a execução do  aplicativo nos programas de segurança. Ao término da instalação, o  agente de rastreamento ficará ativo e irá se reportar a cada 10 minutos  ao painel de monitoramento. O tempo de envio da posição pode ser  personalizado para cada equipamento.&lt;br /&gt;
Para acessar as configurações de usuário e verificar a situação dos computadores que estão sendo rastreados, basta &lt;a href="http://control.preyproject.com/devices" target="_blank"&gt;acessar o site&lt;/a&gt;  e autenticar no sistema. Já na página inicial ficam visíveis as  máquinas monitoradas. Para definir configurações avançadas ou notificar a  perda, é preciso clicar sobre a imagem corresponde ao dispositivo.&lt;br /&gt;
&lt;div class="foto componente_materia midia-largura-620"&gt;&lt;img alt="Dispositivos monitorados pelo Prey Project (Foto: Reprodução)" height="256" src="http://s.glbimg.com/jo/g1/f/original/2011/06/06/dispositivos.jpg" title="Dispositivos monitorados pelo Prey Project (Foto: Reprodução)" width="400" /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Dispositivos monitorados pelo Prey Project (Foto: Reprodução)&lt;/b&gt;&lt;/div&gt;O sistema só irá gerar relatórios de rastreamento quando o usuário  alterar o status do dispositivo para “missing”. Nessa mesma tela é  possível definir a periodicidade de coleta de dados.&lt;br /&gt;
&lt;div class="foto componente_materia midia-largura-620"&gt;&lt;img alt="ela responsável pelas configurações do sistema, assim como o acionamento da rastreamento quando o notebook for perdido (Foto: Reprodução)" height="243" src="http://s.glbimg.com/jo/g1/f/original/2011/06/06/definicao.jpg" title="ela responsável pelas configurações do sistema, assim como o acionamento da rastreamento quando o notebook for perdido (Foto: Reprodução)" width="400" /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Tela  responsável pelas configurações do sistema, assim como o acionamento da  rastreamento quando o notebook for perdido (Foto: Reprodução)&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;
Nos notebooks que possuírem webcam, durante o processo de coleta, o  programa faz fotografias, a fim de registrar o rosto do usuário que está  acessando o equipamento indevidamente. Além disso, o software registra  informações sobre as configurações da rede, programas em uso e arquivos  alterados.&lt;br /&gt;
&lt;div class="foto componente_materia midia-largura-620"&gt;&lt;img alt="Após sinalizar o notebook perdido, o sistema irá exibir em vermelho a ilustração do dispositivo (Foto: Reprodução)" height="257" src="http://s.glbimg.com/jo/g1/f/original/2011/06/06/perdido.jpg" title="Após sinalizar o notebook perdido, o sistema irá exibir em vermelho a ilustração do dispositivo (Foto: Reprodução)" width="400" /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Após sinalizar o notebook perdido, o sistema irá exibir em vermelho a ilustração do dispositivo (Foto: Reprodução)&lt;/b&gt;&lt;/div&gt;Após definido como perdido, o programa irá enviar para página de  monitoramento o relatório contendo as informações que foram  configuradas. Nele também será enviada a localização usando serviço o  Google Maps. A precisão do rastreamento impressiona. O relatório também é  enviado para a conta de e-mail cadastrada pelo usuário.&lt;br /&gt;
&lt;div class="foto componente_materia midia-largura-620"&gt;&lt;img alt="Localização do notebook perdido (Foto: Reprodução)" height="228" src="http://s.glbimg.com/jo/g1/f/original/2011/06/06/localizacao.jpg" title="Localização do notebook perdido (Foto: Reprodução)" width="400" /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Localização do notebook perdido (Foto: Reprodução)&lt;/b&gt;&lt;/div&gt;Vale salientar que, para o Prey Project funcionar, o equipamento  perdido não pode ter sido formatado e a sua localização só será possível  quando ele estiver conectado à internet. Uma dica para desestimular a  formatação num primeiro momento é deixar ativo um usuário visitante, sem  senha, no sistema operacional. Afinal, é muito provável que quem  estiver com o equipamento irá tentar usá-lo e, se estiver acessível,  talvez a formatação nem ocorra.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-5288320523020014655?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yu2YCpxqVeJs5detkPTQZ_g8K_0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yu2YCpxqVeJs5detkPTQZ_g8K_0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yu2YCpxqVeJs5detkPTQZ_g8K_0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yu2YCpxqVeJs5detkPTQZ_g8K_0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/V-0FGz-Ek_M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/5288320523020014655/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/11/programa-para-rastrear-computador.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5288320523020014655?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5288320523020014655?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/V-0FGz-Ek_M/programa-para-rastrear-computador.html" title="Programa para rastrear computador perdido ou roubado (Free)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/11/programa-para-rastrear-computador.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYMQXg5eyp7ImA9WhRSF08.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-4193657932024810533</id><published>2011-11-19T14:10:00.004-03:00</published><updated>2011-11-19T14:19:40.623-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-19T14:19:40.623-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dicas de segurança" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas Hackers" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><title>Como consertar o pendrive depois de um vírus?</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;br /&gt;
&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Perder todos os seus arquivos que estavam em seu pendrive por causa de um vírus pode ser uma experiência bastante desagradável, mas perder todos os arquivos é uma coisa que evidentemente pode-se evitar, com apenas alguns comandos de atributos é possível recuperar e retirar possíveis vírus de seu pendriver. Primeiro temos que entender o que realmente os vírus de pendrive fazem e como eles funcionam em especial os que transformam pastas em atalhos.&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Os vírus de pendrive (em especial os que transformam pastas em atalhos) apenas modificam o tipo de atributo das pastas para oculto e de sistema, para entender melhor se você estiver com um pendrive à mão siga os passos para entender:&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;1° pegue seu pendrive de preferência vazio e crie algumas pastas só para teste&lt;/b&gt;.&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Crie 5 novas pastas.&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-1SKrLne7xx0/TsffpSoiKAI/AAAAAAAAAQg/rvHO-lUad0g/s1600/criar+pastas.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="176" src="http://1.bp.blogspot.com/-1SKrLne7xx0/TsffpSoiKAI/AAAAAAAAAQg/rvHO-lUad0g/s400/criar+pastas.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp; Deve ficar assim:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Xid5fgnobQs/Tsff5RO8FhI/AAAAAAAAAQo/CASAbOM-sHk/s1600/pastas.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="166" src="http://3.bp.blogspot.com/-Xid5fgnobQs/Tsff5RO8FhI/AAAAAAAAAQo/CASAbOM-sHk/s400/pastas.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;2° Agora vamos abrir o cmd e alterar os atributos de nossos arquivos e pastas do pendrive;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp; Clique em Iniciar&amp;gt;Executar&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-saRdiVySkYw/TsfgGIGWoPI/AAAAAAAAAQw/G28DpkMRFDw/s1600/iniciar+executar.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="162" src="http://2.bp.blogspot.com/-saRdiVySkYw/TsfgGIGWoPI/AAAAAAAAAQw/G28DpkMRFDw/s400/iniciar+executar.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Depois digite cmd e tecle ENTER ou pressione o botão OK&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-t1r0VVX00k4/TsfgR7Bwg5I/AAAAAAAAAQ4/YJHsYudEpJw/s1600/executar+OK.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="211" src="http://2.bp.blogspot.com/-t1r0VVX00k4/TsfgR7Bwg5I/AAAAAAAAAQ4/YJHsYudEpJw/s400/executar+OK.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Na tela do Pront de comando digite: &lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;cd e tecle ENTER &lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Digite a letra que representa a unidade de seu pendrive e tecle ENTER; Ex F: ou G:&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Para saber qual é a unidade de seu pendrive vá em: Meu Computador e olhe:&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Wfy0lJwYsho/TsfgohZ7OOI/AAAAAAAAARA/YrtHXQ4IPks/s1600/meu+computador.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="178" src="http://3.bp.blogspot.com/-Wfy0lJwYsho/TsfgohZ7OOI/AAAAAAAAARA/YrtHXQ4IPks/s400/meu+computador.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;No meu caso a letra que representa meu pendrive é H, então no pront vai ficar assim:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-7_6jRPsRWKM/Tsfg9A2O3mI/AAAAAAAAARI/l39z4sOBOkQ/s1600/pront1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="202" src="http://3.bp.blogspot.com/-7_6jRPsRWKM/Tsfg9A2O3mI/AAAAAAAAARI/l39z4sOBOkQ/s400/pront1.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;3° digite na tela do pront:&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;ATTRIB +H +S /D /S&amp;nbsp; e tecle ENTER&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-BcyPlqRDSUg/TsfhFysAv0I/AAAAAAAAARQ/7WYl3mejeF4/s1600/PRONT+2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="162" src="http://3.bp.blogspot.com/-BcyPlqRDSUg/TsfhFysAv0I/AAAAAAAAARQ/7WYl3mejeF4/s320/PRONT+2.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Agora vá novamente a seu pendrive e tente olhar o que tem por lá:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-giJV4kIg9QU/TsfhTCP58yI/AAAAAAAAARY/sJOVEvV6wos/s1600/pendrive+vazio.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="226" src="http://3.bp.blogspot.com/-giJV4kIg9QU/TsfhTCP58yI/AAAAAAAAARY/sJOVEvV6wos/s400/pendrive+vazio.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;È isso que os vírus fazem, aparentemente sumiu tudo, mas não foi realmente isso que aconteceu, agora vamos executar alguns procedimentos para poder visualizar nossos documentos e pastas:&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Clique em: FERRAMENTAs&amp;gt;OPÇÕES DE PASTAS&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-OguJlDACPu8/Tsfhds6txeI/AAAAAAAAARg/mIdieTEHc3M/s1600/opcoes+de+pasta.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="185" src="http://4.bp.blogspot.com/-OguJlDACPu8/Tsfhds6txeI/AAAAAAAAARg/mIdieTEHc3M/s400/opcoes+de+pasta.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Clique na Aba Modo de Exibição&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CP9mdLukGmE/TsfhlLwBIEI/AAAAAAAAARo/V1CleT5l1WE/s1600/modo+de+exibicao.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-CP9mdLukGmE/TsfhlLwBIEI/AAAAAAAAARo/V1CleT5l1WE/s400/modo+de+exibicao.JPG" width="380" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Procure a opção: Ocultar arquivos protegidos do sistema operacional (recomendado) &amp;nbsp;e desmarque, irá aparecer uma mensagem clique em SIM.&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-DJciAr9Mr68/TsfhwL-dMnI/AAAAAAAAARw/ffq5vuDuHSc/s1600/imagem.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="183" src="http://3.bp.blogspot.com/-DJciAr9Mr68/TsfhwL-dMnI/AAAAAAAAARw/ffq5vuDuHSc/s400/imagem.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Agora procure a opção Mostrar Pastas e arquivos ocultos e marque-a.&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;E em seguida clique em O&lt;/b&gt;K&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-uPJp5HjG_l8/Tsfh55pBsRI/AAAAAAAAAR4/EnvswWO4vxI/s1600/OK.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/-uPJp5HjG_l8/Tsfh55pBsRI/AAAAAAAAAR4/EnvswWO4vxI/s400/OK.JPG" width="376" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Perceba agora que tudo que estava escondido apareceu no pendrive:&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-dpCLpP_VzZY/TsfiL7yxZtI/AAAAAAAAASA/jC1ULdccm6g/s1600/showall.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="182" src="http://4.bp.blogspot.com/-dpCLpP_VzZY/TsfiL7yxZtI/AAAAAAAAASA/jC1ULdccm6g/s400/showall.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: red; text-align: justify;"&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: red; text-align: justify;"&gt;&lt;b&gt;Bom, agora que já sabemos como os vírus modificam os atributos das pastas, vamos aprender como remover os tais atributos:&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;1° ainda dentro do pront digite: ATTRIB –S –H /D /S e tecle ENTER&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ex:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-B_lt3qRSw-s/Tsfij9HsNcI/AAAAAAAAASI/4da8Tz863kg/s1600/PRONT+3.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-B_lt3qRSw-s/Tsfij9HsNcI/AAAAAAAAASI/4da8Tz863kg/s400/PRONT+3.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;2° Vá a seu pendrive e dê uma olhada, perceba que as pastas e arquivos voltaram ao normal:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-axC3h3K5eXw/TsfiwzQDIkI/AAAAAAAAASQ/viZ1sPRrYDg/s1600/all+normal.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="161" src="http://4.bp.blogspot.com/-axC3h3K5eXw/TsfiwzQDIkI/AAAAAAAAASQ/viZ1sPRrYDg/s400/all+normal.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;Sempre que seu pendrive estiver com as pastas ocultas execute esse procedimento para alterar os atributos.&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;Até a próxima.&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;OBS:&lt;/span&gt;&lt;/b&gt; &lt;span style="color: red;"&gt;depois de terminar este procedimento marque novamente a opção de ocultar arquivos protegidos do sistema.&lt;/span&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-4193657932024810533?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/k2YnKP5ZC4WgVLXy62TVIpMXAno/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/k2YnKP5ZC4WgVLXy62TVIpMXAno/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/k2YnKP5ZC4WgVLXy62TVIpMXAno/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/k2YnKP5ZC4WgVLXy62TVIpMXAno/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/8BWwCqPDpmI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/4193657932024810533/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/11/como-consertar-o-pendriver-depois-d-eum.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/4193657932024810533?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/4193657932024810533?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/8BWwCqPDpmI/como-consertar-o-pendriver-depois-d-eum.html" title="Como consertar o pendrive depois de um vírus?" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-1SKrLne7xx0/TsffpSoiKAI/AAAAAAAAAQg/rvHO-lUad0g/s72-c/criar+pastas.JPG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/11/como-consertar-o-pendriver-depois-d-eum.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QMR3kzfyp7ImA9WhRWEE0.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-2175329221790931218</id><published>2011-11-02T12:39:00.007-03:00</published><updated>2011-12-27T12:56:26.787-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-27T12:56:26.787-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dicas de segurança" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas Hackers" /><title>Super Keylogger - Keen eye | v. 2.1</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-V5aA7TENmJ0/TrFe6DPbAGI/AAAAAAAAAPQ/SEiF0WKwOnw/s1600/imagem1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="236" src="http://2.bp.blogspot.com/-V5aA7TENmJ0/TrFe6DPbAGI/AAAAAAAAAPQ/SEiF0WKwOnw/s400/imagem1.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: inherit;"&gt;Muitas vezes você quer garantir a segurança de seus filhos, saber o que  eles estão fazendo no computador enquanto você não está olhando, ou até  mesmo você quer saber o que seus funcionários andam fazendo, e quem sabe  deseja apenas garantir a segurança de seu computador, seja qual for o  motivo nós estamos fornecendo um Keylogger de monitoramento, saiba tudo que é digitado, todas as URLs visitadas,  janelas abertas,&amp;nbsp; processos activos, conversas realizadas e muito  mais... tudo isso 100% invisível.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&amp;nbsp;&amp;nbsp; O keylogger é de facíl instalação e requer apenas conhecimentos  básicos de computação, apenas com alguns cliques você terá todo o controle  sobre seu ou seus computadores.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Veja algumas funcionalidades do Keylogger:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&amp;nbsp; Monitoramento 24 horas por dia 7 dias por semana.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Logs recebidos por emai. &lt;/li&gt;
&lt;li&gt;&amp;nbsp; Captura de todas as teclas digitadas.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Captura de todas as janelas abertas.&lt;/li&gt;
&lt;li&gt; &amp;nbsp; Informações com data e hora.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Logs recebidos com o nome do computador e o usuário logado no momento.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Criptografia de logs.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Captura de todas as janelas acessadas no windows.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Captura de todos os emails de conversas realizadas pelo MSN.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; Captura do teclado virtual do windows. &lt;/li&gt;
&lt;li&gt;&amp;nbsp; Envio de logs via SMTP(email) ou FTP(servidor remoto).&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&lt;b&gt;Veja algumas Telas&lt;/b&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-KO8e1CkWg-c/TrFfo_oWIMI/AAAAAAAAAQA/ple9nf3ySV8/s1600/imagem2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="245" src="http://2.bp.blogspot.com/-KO8e1CkWg-c/TrFfo_oWIMI/AAAAAAAAAQA/ple9nf3ySV8/s400/imagem2.JPG" width="400" /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Pf0HvD_CfLM/TrFf7v2x6eI/AAAAAAAAAQI/ti6Z-_5KrPw/s1600/imagem3.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="243" src="http://3.bp.blogspot.com/-Pf0HvD_CfLM/TrFf7v2x6eI/AAAAAAAAAQI/ti6Z-_5KrPw/s400/imagem3.JPG" width="400" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-KFjoTqu8nIs/TrFgLk82dfI/AAAAAAAAAQQ/0YnUPXJgVlE/s1600/imagem5.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="245" src="http://3.bp.blogspot.com/-KFjoTqu8nIs/TrFgLk82dfI/AAAAAAAAAQQ/0YnUPXJgVlE/s400/imagem5.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-aX78Jmd6Tu8/TrFgVL1YRHI/AAAAAAAAAQY/MbKM9IT5a60/s1600/imagem6.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="243" src="http://2.bp.blogspot.com/-aX78Jmd6Tu8/TrFgVL1YRHI/AAAAAAAAAQY/MbKM9IT5a60/s400/imagem6.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="color: red; text-align: center;"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;_______________________________________________&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;Adquira agora mesmo o serviço de monitoramento ProgMaster:(50,00 $)&lt;/b&gt;&lt;/div&gt;&lt;form action="https://pagseguro.uol.com.br/v2/checkout/cart.html?action=add" method="post" target="pagseguro"&gt;&lt;input name="receiverEmail" type="hidden" value="jeffersonfariassampaio@hotmail.com" /&gt;&lt;input name="currency" type="hidden" value="BRL" /&gt;&lt;input name="itemId" type="hidden" value="1" /&gt;&lt;input name="itemDescription" type="hidden" value="Keylogger de monitoramento" /&gt;&lt;input name="itemQuantity" type="hidden" value="1" /&gt;&lt;input name="itemAmount" type="hidden" value="50.00" /&gt;&lt;input name="itemWeight" type="hidden" value="" /&gt;&lt;input name="itemShippingCost" type="hidden" value="0.00" /&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;input alt="Pague com PagSeguro - é rápido, grátis e seguro!" name="submit" src="https://p.simg.uol.com.br/out/pagseguro/i/botoes/pagamentos/209x48-comprar-preto-assina.gif" type="image" /&gt;&lt;/div&gt;&lt;/form&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="color: red;"&gt;&lt;span style="font-size: small;"&gt;&lt;b style="color: black;"&gt;Adquira o Super Keylogger + código fonte: (200,00 $)&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;form action="https://pagseguro.uol.com.br/v2/checkout/cart.html?action=add" method="post" target="pagseguro"&gt;&lt;input name="receiverEmail" type="hidden" value="jeffersonfariassampaio@hotmail.com" /&gt;&lt;input name="currency" type="hidden" value="BRL" /&gt;&lt;input name="itemId" type="hidden" value="2" /&gt;&lt;br /&gt;
&lt;input name="itemDescription" type="hidden" value="Super keylogger + codigo fonte" /&gt;&lt;input name="itemQuantity" type="hidden" value="1" /&gt;&lt;input name="itemAmount" type="hidden" value="200.00" /&gt;&lt;input name="itemWeight" type="hidden" value="" /&gt;&lt;input name="itemShippingCost" type="hidden" value="0.00" /&gt;&lt;input alt="Pague com PagSeguro - é rápido, grátis e seguro!" name="submit" src="https://p.simg.uol.com.br/out/pagseguro/i/botoes/pagamentos/209x48-comprar-preto-assina.gif" type="image" /&gt;&lt;br /&gt;
&lt;div style="color: red; text-align: center;"&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;Teste o keylogger gratuitamente clicando logo abaixo, se você gostar pode adiquirir uma licença &lt;/span&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: red; text-align: center;"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;_______________________________________________&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;u style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;a href="http://www.4shared.com/file/uGz0Re-8/Super_Keylogger_-_Keen_eye_v21.html" target="_blank"&gt;Clique aqui para download&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;span style="color: red;"&gt;Vendas canceladas temporariamente ...&lt;/span&gt; &lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/div&gt;&lt;/form&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-2175329221790931218?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qmtbNwio_AQnoDw1tvQjmzafDig/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qmtbNwio_AQnoDw1tvQjmzafDig/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qmtbNwio_AQnoDw1tvQjmzafDig/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qmtbNwio_AQnoDw1tvQjmzafDig/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/ppE0RI6omsw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/2175329221790931218/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/11/super-keylogger-keen-eye-v-20.html#comment-form" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/2175329221790931218?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/2175329221790931218?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/ppE0RI6omsw/super-keylogger-keen-eye-v-20.html" title="Super Keylogger - Keen eye | v. 2.1" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-V5aA7TENmJ0/TrFe6DPbAGI/AAAAAAAAAPQ/SEiF0WKwOnw/s72-c/imagem1.JPG" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/11/super-keylogger-keen-eye-v-20.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMNSH0-eSp7ImA9WhdaGUU.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-725216474407461507</id><published>2011-10-30T11:49:00.001-03:00</published><updated>2011-10-30T11:54:59.351-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-30T11:54:59.351-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dicas de segurança" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas Hackers" /><title>FastScanner - ProgMaster</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-c_NGDVZZYGE/Tq1jFBysbhI/AAAAAAAAAPI/8KHwobBLZ2g/s1600/FastScanner.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="381" src="http://1.bp.blogspot.com/-c_NGDVZZYGE/Tq1jFBysbhI/AAAAAAAAAPI/8KHwobBLZ2g/s400/FastScanner.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Portas abertas podem significar uma falha de segurança em servidores da sua empresa e até mesmo em seu computador pessoal. Os Hackers estão sempre de olho em serviços com alguma falha que possa ser explorada por eles. O FastScanner - ProgMaster verifica o status das portas de computadores da sua rede ou da Internet, permitindo que você descubra portas que estão abertas sem necessidade.&lt;br /&gt;
&lt;br /&gt;
O programa, além de leve, é fácil de usar. Não possui complicações, basta escolher o IP e as portas a serem escaneadas que ele exibe uma lista com o status de cada uma.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;a href="http://www.4shared.com/file/0OtTaKcZ/FS-P_Installer.html" target="_blank"&gt;&lt;span style="font-size: x-large;"&gt;&lt;u&gt;&lt;b&gt;Clique aqui para Download&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; &lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-725216474407461507?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_wKng547FV_SW5dbPETs6hM1zm0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_wKng547FV_SW5dbPETs6hM1zm0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_wKng547FV_SW5dbPETs6hM1zm0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_wKng547FV_SW5dbPETs6hM1zm0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/OhDiiZu4vFQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/725216474407461507/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/10/fastscanner-progmaster.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/725216474407461507?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/725216474407461507?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/OhDiiZu4vFQ/fastscanner-progmaster.html" title="FastScanner - ProgMaster" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-c_NGDVZZYGE/Tq1jFBysbhI/AAAAAAAAAPI/8KHwobBLZ2g/s72-c/FastScanner.JPG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/10/fastscanner-progmaster.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4CRnc7eyp7ImA9WhdbFkQ.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-2287645428545411166</id><published>2011-10-15T12:58:00.001-03:00</published><updated>2011-10-15T13:09:27.903-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-15T13:09:27.903-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><title>Escrevendo em arquivos de texto no delphi.</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;Existem vários métodos em Delphi para gravar arquivos texto a partir de informações gravadas em bases de dados ou para ler arquivos texto e armazená-los em bases de dados. &lt;/span&gt;&lt;/code&gt;&lt;span class="me1"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;Esta&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt; dica apresenta dois destes métodos: o uso de TextFiles e da classe TStringList.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;Primeiro vamos usar o TextFiles ...&lt;/span&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="kw4"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;TextFile&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt; é um tipo de dado pré-definido no Delphi e corresponde ao tipo Text &lt;/span&gt;&lt;/code&gt;&lt;span class="kw1"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt; Turbo &lt;/span&gt;&lt;/code&gt;&lt;span class="kw1"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;Pascal&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt; e &lt;/span&gt;&lt;/code&gt;&lt;span class="kw1"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt; &lt;/span&gt;&lt;/code&gt;&lt;span class="kw1"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;Object&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt; &lt;/span&gt;&lt;/code&gt;&lt;span class="kw1"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;Pascal&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;. &lt;/span&gt;&lt;/code&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt;"&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="me1"&gt;Inicialmente&lt;/span&gt;&lt;code&gt; para acessar um arquivo de texto, você precisa definir uma variável tipo &lt;/code&gt;&lt;span class="kw4"&gt;TextFile&lt;/span&gt;&lt;code&gt;, no local que você achar mais apropriado, da seguinte forma:&amp;nbsp;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-bottom: .0001pt; margin: 0cm;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;Var &lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div style="margin-bottom: .0001pt; margin: 0cm;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;F : TextFile;&amp;nbsp;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;Exemplo do uso do TextFile, siga os passos abaixo:&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;1°&lt;/b&gt; - Abra o Delphi.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;2&lt;/b&gt;° - Insira um botão.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;3&lt;/b&gt;° - Altere o Caption do botão para escrever texto com TextFile.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;4&lt;/b&gt;° - Salve o projeto com o nome de ExemploProgmaster.dpr em uma pasta de sua escolha.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;5&lt;/b&gt;° - Adicione uma variavel global logo abaixo de {$R *.dfm} da seguinte foma:&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;var&amp;nbsp; F:Textfile; &lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;6&lt;/b&gt;° - No evento OnClick do button1 adicione o seguinte código:&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;ssignfile(F,'log.txt');&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not FileExists('log.txt') Then&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;begin&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Rewrite(F);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Closefile(F);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Else&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assignfile(F,'log.txt');&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {$I-}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Append(F);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {$I+}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If IOResult&amp;lt;&amp;gt; 0 Then&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Begin&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ShowMessage('-');&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span lang="EN-US" style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;End;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write(F,'Progmaster: Exemplo de como usar o TextFiles.');&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Closefile(F);&amp;nbsp;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;code&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;a href="http://www.4shared.com/file/hxBrSPVo/exemplo_de_como_usar_TextFile_.html" target="_blank"&gt;&lt;span style="font-family: Verdana,sans-serif;"&gt;Download do exemplo acima&lt;/span&gt;&lt;/a&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&lt;b&gt;Agora vamos usar a Classe TStringList ...&amp;nbsp;&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;Siga os passos abaixo:&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;1° Abra seu Delphi.&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;2° Insira um botão.&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;3° No Evento Onclick do Button adicione o seguinte código:&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;Texto: TStringList;&lt;br /&gt;
begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;Texto := TStringList.Create;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;try&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Texto.Add('Linha 1');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Texto.Add('Linha 2');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Texto.SaveToFile('c:\testeProgmaster.txt');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;finally&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Texto.Free;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;end;&lt;br /&gt;
end;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;code&gt;&amp;nbsp;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;a href="http://www.4shared.com/file/fgvZmlOM/exemplo_de_como_escrever_com_T.html" target="_Blank"&gt;&lt;span style="font-size: 10pt;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-family: Verdana,sans-serif;"&gt;Download do exemplo acima&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-2287645428545411166?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LhqndISivBlDyeI0wUPIJK7MAU0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LhqndISivBlDyeI0wUPIJK7MAU0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LhqndISivBlDyeI0wUPIJK7MAU0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LhqndISivBlDyeI0wUPIJK7MAU0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/QD-V-butE38" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/2287645428545411166/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/10/escrevendo-em-arquivos-de-texto-no.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/2287645428545411166?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/2287645428545411166?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/QD-V-butE38/escrevendo-em-arquivos-de-texto-no.html" title="Escrevendo em arquivos de texto no delphi." /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/10/escrevendo-em-arquivos-de-texto-no.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQXcyeyp7ImA9WhdWGUw.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-3128187888838838484</id><published>2011-09-13T09:10:00.002-03:00</published><updated>2011-09-13T09:25:20.993-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-13T09:25:20.993-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C\C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Downloads" /><title>FBI rat. baseado no Aryan rat 0.5. by albinoskunk.</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Olá.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Alguns de vocês podem ter visto o Aryan v0.5 bem, eu estou reescrevendo tudo, no caminho eu tenho adicionado algumas novas funcionalidades, melhora na estabilidade, acrescentou a criptografia para o transporte de dados e incluído injecção no navegador padrão. &lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;F.B.I RAT (Integração Backdoor Full) V0.1&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Suporta xp / Vista / Windows 7, todos os recursos foram testados em injecção, incluindo esses OS, mas houve algumas limitações sobre o sniffer. &lt;br /&gt;
&lt;br /&gt;
Características:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Gerenciador de Arquivos:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Execute, Normal e Escondido.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Copiar e Colar, como o Windows Explorer.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Display tamanho do arquivo e o tipo.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Delete.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Download &amp;amp; Upload (re-coded) Multi-threaded downloads, que permite que você baixe vários arquivos de uma vez.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Stop, Pause e retomar a transferência de ativos.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Busca de arquivos.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Renomear arquivos. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;System Manager:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Process Manager - Atualizar os processos em execução e pode dar kill&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Window Manager - Atualizar e fecha janelas, mostra janelas escondidas e visíveis.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Programas Instalados - Nome da lista do programa e do diretório.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Serviços Instalados - Lista dos serviços instalados, permite parar, iniciar e pausar serviços.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Keylogger:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Permite que o usuário tenha um tempo e data da janela ativa, bem como a codificação de cores personalizadas.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Usa um gancho de teclado, por isso não caiu como a maioria das chaves keyloggers, e 0 uso da CPU.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Offline keylogs e on-line, off-line são keylogs baixado uma vez que você iniciar o keylogger Online, e uma vez que a sessão tenha terminado keylogger on-line, o keylogger off-line começa novamente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Captura de tela:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Reworked transferência e captura.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Permite ao usuário selecionar a qualidade, a intervalos de capturas de tela e Stop &amp;amp; Start de captura de tela.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Webcam:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Reworked transferência e captura.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Permite ao usuário parar e começar a captura, também permite um intervalo para o envio de captura.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Packet Sniffer:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; - "Stat Net" Permite ao usuário visualizar as conexões locais no computador, e então selecionar qual conexão que você deseja usar o sniff, displays IP do servidor remoto e informações de IP e porta local, também o estado da conexão, toda esta informação vem da TCP pilha de janelas.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; -Packet sniffer, fareja os pacotes, utilizando sockets janelas e formatos RAW-los em texto para você ler, eu testei isso com sites do mundo real, e permitiu-me a roubar informações, como logins de site, mas devido às limitações do Vista e Windows 7, é provável que não vai funcionar, para aqueles dois sistemas operacionais.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Escolha de injeção, Esta fonte vem com um outro projeto que permite injetar seu servidor para o browser padrão da Vítima, você também pode usar o exe e executá-lo normalmente, sem injeção, para testes, o código de injeção foi modificado de um velho fonte que eu encontrei, eu tirei a fonte tentei melhorá-la, tornou detectar o navegador padrão e tornou-carga da API indiretamente, assim você pode criptografar as cordas API, e ignorar AV.&lt;br /&gt;
&lt;div id="post_message_83466"&gt;&lt;blockquote class="postcontent restore"&gt;&lt;div class="bbcode_container"&gt;&lt;div class="bbcode_quote"&gt;&lt;div class="quote_container"&gt;Download Link: &lt;a href="http://www.megaupload.com/?d=ROHUUZO7" target="_blank"&gt;http://www.megaupload.com/?d=ROHUUZO7&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-Thanks&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;span style="font-size: x-large;"&gt;&lt;b&gt;&lt;a href="http://www.opensc.ws/attachments/rat-source/4310d1272237790-fbi-rat-based-aryan-rat-0-5-albinoskunk-fbi-rat.7z"&gt;Download &lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-3128187888838838484?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uFZHI-nKBge0OtzMvWyEJCF-P18/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uFZHI-nKBge0OtzMvWyEJCF-P18/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uFZHI-nKBge0OtzMvWyEJCF-P18/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uFZHI-nKBge0OtzMvWyEJCF-P18/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/TsxfQPvxSMw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/3128187888838838484/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/09/fbi-rat-baseado-no-aryan-rat-05-by.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/3128187888838838484?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/3128187888838838484?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/TsxfQPvxSMw/fbi-rat-baseado-no-aryan-rat-05-by.html" title="FBI rat. baseado no Aryan rat 0.5. by albinoskunk." /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/09/fbi-rat-baseado-no-aryan-rat-05-by.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYFQnc8fCp7ImA9WhdXGUo.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-5033799893994616173</id><published>2011-09-02T12:36:00.001-03:00</published><updated>2011-09-02T12:41:53.974-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-02T12:41:53.974-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><title>Ruby 1.9.2 download</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div id="content"&gt;
Ruby 1.9.2-p290 está disponível.&lt;br /&gt;
Esta versão não inclui a correcção de nenhuma vulnerabilidade de segurança, no entanto foram corrigidos muitos bugs.&lt;br /&gt;
&lt;div id="extended"&gt;
&lt;br /&gt;
&lt;h3&gt;


&lt;a href="http://www.blogger.com/blogger.g?blogID=967430253837456983" id="label-0" name="label-0"&gt;Downloads&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.bz2"&gt;http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.bz2&lt;/a&gt;
&lt;dl&gt;&lt;a href="http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.bz2"&gt;
&lt;/a&gt;
&lt;dt&gt;&lt;a href="http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.bz2"&gt;&lt;/a&gt;TAMANHO:&lt;/dt&gt;
&lt;dd&gt;8811237 bytes
&lt;/dd&gt;
&lt;dt&gt;MD5:&lt;/dt&gt;
&lt;dd&gt;096758c3e853b839dc980b183227b182
&lt;/dd&gt;
&lt;dt&gt;SHA256:&lt;/dt&gt;
&lt;dd&gt;403b3093fbe8a08dc69c269753b8c6e7bd8f87fb79a7dd7d676913efe7642487
&lt;/dd&gt;&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz"&gt;http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz&lt;/a&gt;
&lt;dl&gt;
&lt;dt&gt;TAMANHO:&lt;/dt&gt;
&lt;dd&gt;11182217 bytes
&lt;/dd&gt;
&lt;dt&gt;MD5:&lt;/dt&gt;
&lt;dd&gt;604da71839a6ae02b5b5b5e1b792d5eb
&lt;/dd&gt;
&lt;dt&gt;SHA256:&lt;/dt&gt;
&lt;dd&gt;1cc817575c4944d3d78959024320ed1d5b7c2b4931a855772dacad7c3f6ebd7e&amp;nbsp; &lt;/dd&gt;&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.zip"&gt;&lt;url:http: 1.9="" ftp.ruby-lang.org="" pub="" ruby-1.9.2-p290.zip="" ruby=""&gt;&lt;/url:http:&gt;&lt;/a&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;a href="http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.zip%20"&gt;http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.zip &lt;/a&gt;&lt;/dt&gt;
&lt;dt&gt;TAMANHO:&lt;/dt&gt;
&lt;dd&gt;12600100 bytes
&lt;/dd&gt;
&lt;dt&gt;MD5:&lt;/dt&gt;
&lt;dd&gt;6060b410aa15d09ac13b93033b8b5c66
&lt;/dd&gt;
&lt;dt&gt;SHA256:&lt;/dt&gt;
&lt;dd&gt;bce3d1c8c78fbafb6a0d67df2b8dec5322301f7b4b0f7594656ad689e9cb461d
&lt;/dd&gt;&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-5033799893994616173?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zYq5egQHY9yyg5UpT8BgYaO_He8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zYq5egQHY9yyg5UpT8BgYaO_He8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zYq5egQHY9yyg5UpT8BgYaO_He8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zYq5egQHY9yyg5UpT8BgYaO_He8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/KmcGaUunSTk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/5033799893994616173/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/09/ruby-192-download.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5033799893994616173?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/5033799893994616173?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/KmcGaUunSTk/ruby-192-download.html" title="Ruby 1.9.2 download" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/09/ruby-192-download.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUENQXg6fyp7ImA9WhdXGUo.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-4627412147504974996</id><published>2011-09-02T12:34:00.000-03:00</published><updated>2011-09-02T12:34:50.617-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-02T12:34:50.617-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><title>Ruby (linguagem de programação)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div style="color: black;"&gt;
&lt;b&gt;Ruby é uma linguagem de programação interpretada &lt;a href="http://pt.wikipedia.org/wiki/Linguagem_de_programa%C3%A7%C3%A3o_multiparadigma" title="Linguagem de programação multiparadigma"&gt;multiparadigma&lt;/a&gt;, de &lt;a href="http://pt.wikipedia.org/wiki/Tipagem_din%C3%A2mica" title="Tipagem dinâmica"&gt;tipagem dinâmica&lt;/a&gt; e &lt;a href="http://pt.wikipedia.org/wiki/Tipo_de_dado#Tipo_forte_e_fraco" title="Tipo de dado"&gt;forte&lt;/a&gt;, com &lt;a href="http://pt.wikipedia.org/wiki/Gerenciamento_de_mem%C3%B3ria" title="Gerenciamento de memória"&gt;gerenciamento de memória&lt;/a&gt; automático, originalmente planejada e desenvolvida no &lt;a href="http://pt.wikipedia.org/wiki/Jap%C3%A3o" title="Japão"&gt;Japão&lt;/a&gt; em 1995, por &lt;a href="http://pt.wikipedia.org/wiki/Yukihiro_Matsumoto" title="Yukihiro Matsumoto"&gt;Yukihiro "Matz" Matsumoto&lt;/a&gt;, para ser usada como &lt;a href="http://pt.wikipedia.org/wiki/Linguagem_de_script" title="Linguagem de script"&gt;linguagem de script&lt;/a&gt;. Matz queria uma linguagem de script que fosse mais poderosa do que &lt;a href="http://pt.wikipedia.org/wiki/Perl" title="Perl"&gt;Perl&lt;/a&gt;, e mais &lt;a href="http://pt.wikipedia.org/wiki/Orienta%C3%A7%C3%A3o_a_objetos" title="Orientação a objetos"&gt;orientada a objetos&lt;/a&gt; do que &lt;a href="http://pt.wikipedia.org/wiki/Python" title="Python"&gt;Python&lt;/a&gt;.&lt;sup class="reference" id="cite_ref-Interview_0-0"&gt;&lt;a href="http://pt.wikipedia.org/wiki/Ruby_%28linguagem_de_programa%C3%A7%C3%A3o%29#cite_note-Interview-0"&gt;[1]&lt;/a&gt;&lt;/sup&gt; Ruby suporta &lt;a href="http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_funcional" title="Programação funcional"&gt;programação funcional&lt;/a&gt;, orientada a objetos, &lt;a href="http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_imperativa" title="Programação imperativa"&gt;imperativa&lt;/a&gt; e reflexiva. Foi inspirada principalmente por Python, Perl, Smalltalk, Eiffel, Ada e Lisp, sendo muito similar em vários aspectos a Python. Atualmente, Ruby é a 12º linguagem de programação mais popular do mundo, de acordo com o Índice Tiobe.&lt;/b&gt;&lt;/div&gt;
&lt;b style="color: black;"&gt;
&lt;/b&gt;&lt;div style="color: black;"&gt;
&lt;b&gt;A implementação 1.8.7 padrão é escrita em &lt;a href="http://pt.wikipedia.org/wiki/C_%28linguagem_de_programa%C3%A7%C3%A3o%29" title="C (linguagem de programação)"&gt;C&lt;/a&gt;, como uma linguagem de programação de único passe. Não há qualquer especificação da linguagem, assim a implementação 
original é considerada de fato uma referência. Atualmente, há várias 
implementações alternativas da linguagem, incluindo &lt;i&gt;YARV&lt;/i&gt;, &lt;a href="http://pt.wikipedia.org/wiki/JRuby" title="JRuby"&gt;JRuby&lt;/a&gt;, &lt;i&gt;Rubinius&lt;/i&gt;, &lt;i&gt;IronRuby&lt;/i&gt;, &lt;i&gt;MacRuby&lt;/i&gt; e &lt;i&gt;HotRuby&lt;/i&gt;, cada qual com uma abordagem diferente, com IronRuby, JRuby e MacRuby fornecendo compilação &lt;a href="http://pt.wikipedia.org/wiki/JIT" title="JIT"&gt;Just-In-Time&lt;/a&gt; e, JRubye MacRuby também fornecendo compilação &lt;a class="new" href="http://pt.wikipedia.org/w/index.php?title=AOT&amp;amp;action=edit&amp;amp;redlink=1" title="AOT (página não existe)"&gt;Ahead-Of-Time&lt;/a&gt;.
 A série 1.9 usa YARV (Yet Another Ruby VirtualMachine), como também a 
2.0 (em desenvolvimento), substituindo a lenta Ruby MRI (Matz's Ruby 
Interpreter).&lt;/b&gt;&lt;/div&gt;
&lt;table class="toc" id="toc"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;
&lt;span class="editsection"&gt;&lt;/span&gt;&amp;nbsp;&lt;span class="mw-headline" id="Hist.C3.B3ria"&gt;História&lt;/span&gt;&lt;/h2&gt;
&lt;div class="thumb tright"&gt;

&lt;div class="thumbinner" style="width: 162px;"&gt;
&lt;a class="image" href="http://pt.wikipedia.org/wiki/Ficheiro:Yukihiro_Matsumoto.JPG"&gt;&lt;img alt="" class="thumbimage" height="239" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Yukihiro_Matsumoto.JPG/160px-Yukihiro_Matsumoto.JPG" width="160" /&gt;&lt;/a&gt;
&lt;div class="thumbcaption"&gt;

&lt;div class="magnify"&gt;
&lt;a class="internal" href="http://pt.wikipedia.org/wiki/Ficheiro:Yukihiro_Matsumoto.JPG" title="Ampliar"&gt;&lt;img alt="" height="11" src="http://bits.wikimedia.org/skins-1.17/common/images/magnify-clip.png" width="15" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a href="http://pt.wikipedia.org/wiki/Yukihiro_Matsumoto" title="Yukihiro Matsumoto"&gt;Yukihiro Matsumoto&lt;/a&gt;, criador da linguagem Ruby&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
A linguagem Ruby foi concebida em &lt;a href="http://pt.wikipedia.org/wiki/24_de_fevereiro" title="24 de fevereiro"&gt;24 de fevereiro&lt;/a&gt; de &lt;a href="http://pt.wikipedia.org/wiki/1993" title="1993"&gt;1993&lt;/a&gt; por &lt;a href="http://pt.wikipedia.org/wiki/Yukihiro_Matsumoto" title="Yukihiro Matsumoto"&gt;Yukihiro Matsumoto&lt;/a&gt;, que pretendia criar uma nova &lt;a href="http://pt.wikipedia.org/wiki/Linguagem_de_programa%C3%A7%C3%A3o" title="Linguagem de programação"&gt;linguagem&lt;/a&gt; que balanceava &lt;a href="http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_funcional" title="Programação funcional"&gt;programação funcional&lt;/a&gt; com a &lt;a href="http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_imperativa" title="Programação imperativa"&gt;programação imperativa&lt;/a&gt;. Matsumoto afirmou: "Eu queria uma &lt;a href="http://pt.wikipedia.org/wiki/Linguagem_de_script" title="Linguagem de script"&gt;linguagem de script&lt;/a&gt; que fosse mais poderosa do que &lt;a href="http://pt.wikipedia.org/wiki/Perl" title="Perl"&gt;Perl&lt;/a&gt;, e mais &lt;a href="http://pt.wikipedia.org/wiki/Orienta%C3%A7%C3%A3o_a_objetos" title="Orientação a objetos"&gt;orientada a objetos&lt;/a&gt; do que &lt;a href="http://pt.wikipedia.org/wiki/Python" title="Python"&gt;Python&lt;/a&gt;. É por isso que eu decidi desenvolver minha própria linguagem.".&lt;br /&gt;

Após o lançamento do Ruby 1.3 em &lt;a href="http://pt.wikipedia.org/wiki/1999" title="1999"&gt;1999&lt;/a&gt;, iniciou-se a primeira &lt;a href="http://pt.wikipedia.org/wiki/Lista_de_discuss%C3%A3o" title="Lista de discussão"&gt;lista de discussão&lt;/a&gt; em &lt;a href="http://pt.wikipedia.org/wiki/L%C3%ADngua_inglesa" title="Língua inglesa"&gt;inglês&lt;/a&gt; chamada &lt;i&gt;Ruby-Talk&lt;/i&gt;, marcando um interesse crescente na linguagem fora do &lt;a href="http://pt.wikipedia.org/wiki/Jap%C3%A3o" title="Japão"&gt;Japão&lt;/a&gt;. Em setembro de &lt;a href="http://pt.wikipedia.org/wiki/2000" title="2000"&gt;2000&lt;/a&gt;, o primeiro &lt;a href="http://pt.wikipedia.org/wiki/Livro" title="Livro"&gt;livro&lt;/a&gt; em inglês, &lt;a class="external text" href="http://ruby-doc.org/docs/ProgrammingRuby/" rel="nofollow"&gt;Programming Ruby&lt;/a&gt;,
 foi impresso, sendo mais tarde liberado gratuitamente para o público, 
ajudando no processo de adoção de Ruby por falantes do inglês.&lt;br /&gt;

Por volta de &lt;a href="http://pt.wikipedia.org/wiki/2005" title="2005"&gt;2005&lt;/a&gt;, o interesse pela linguagem Ruby subiu em conjunto com o &lt;a href="http://pt.wikipedia.org/wiki/Ruby_on_Rails" title="Ruby on Rails"&gt;Ruby on Rails&lt;/a&gt;, um &lt;a href="http://pt.wikipedia.org/wiki/Framework" title="Framework"&gt;framework&lt;/a&gt;
 de aplicações web popular escrito em Ruby. Rails é frequentemente 
creditada como a aplicação que tornou Ruby "famosa" e a associação é tão
 forte que ambos são muitas vezes confundidos por programadores que são 
novos a Ruby.&lt;br /&gt;

&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt;&amp;nbsp;&lt;span class="mw-headline" id="Etimologia_do_nome_.22Ruby.22"&gt;Etimologia do nome "Ruby"&lt;/span&gt;&lt;/h3&gt;
O nome "Ruby", foi decidido durante uma &lt;a href="http://pt.wikipedia.org/wiki/Chat" title="Chat"&gt;sessão de bate-papo&lt;/a&gt; online entre Matsumoto (Matz) e &lt;i&gt;Keiju Ishitsuka&lt;/i&gt; em 24 de fevereiro de 1993, antes que qualquer linha de &lt;a href="http://pt.wikipedia.org/wiki/C%C3%B3digo_fonte" title="Código fonte"&gt;código&lt;/a&gt; tivesse sido escrita para a linguagem. Inicialmente foram propostos dois nomes: "Coral" e "Ruby", sendo esse último nome proposto escolhido mais tarde por Matz em um &lt;a href="http://pt.wikipedia.org/wiki/E-mail" title="E-mail"&gt;e-mail&lt;/a&gt; para Ishitsuka. Matsumoto explicou mais tarde que o motivo de ter escolhido o nome "Ruby" foi porque essa era a &lt;a href="http://pt.wikipedia.org/wiki/Pedras_zodiacais" title="Pedras zodiacais"&gt;pedra zodiacal&lt;/a&gt; de um de seus colegas.&lt;br /&gt;

&lt;h2&gt;
&lt;span class="editsection"&gt;&lt;/span&gt;&amp;nbsp;&lt;span class="mw-headline" id="Caracter.C3.ADsticas"&gt;Características&lt;/span&gt;&lt;/h2&gt;
Uma série de características foram definidas para atender às propostas do Ruby:&lt;br /&gt;

&lt;ul&gt;
&lt;li&gt;Todas as variáveis são objetos, onde até os "tipos primitivos" (tais como inteiro, real, entre outros) são &lt;a href="http://pt.wikipedia.org/wiki/Classe_%28programa%C3%A7%C3%A3o%29" title="Classe (programação)"&gt;classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Métodos de geração de código em tempo real, como os "attribute accessors"&lt;/li&gt;
&lt;li&gt;Através do &lt;a href="http://pt.wikipedia.org/wiki/RubyGems" title="RubyGems"&gt;RubyGems&lt;/a&gt;, é possível instalar e atualizar bibliotecas com uma linha de comando, de maneira similar ao &lt;a href="http://pt.wikipedia.org/wiki/Advanced_Packaging_Tool" title="Advanced Packaging Tool"&gt;APT&lt;/a&gt; do &lt;a href="http://pt.wikipedia.org/wiki/Debian" title="Debian"&gt;Debian&lt;/a&gt; Linux&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Code blocks&lt;/i&gt; (blocos de código) passados como parâmetros para métodos; permite a criação de &lt;a href="http://pt.wikipedia.org/wiki/Closure" title="Closure"&gt;closures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Mixins&lt;/i&gt;, uma forma de emular a &lt;a href="http://pt.wikipedia.org/wiki/Heran%C3%A7a_m%C3%BAltipla" title="Herança múltipla"&gt;herança múltipla&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tipagem dinâmica, mas forte. Isso significa que todas as variáveis 
devem ter um tipo (fazer parte de uma classe), mas a classe pode ser 
alterada dinamicamente&lt;/li&gt;
&lt;/ul&gt;
Ruby está disponível para diversas plataformas, como &lt;a href="http://pt.wikipedia.org/wiki/Microsoft_Windows" title="Microsoft Windows"&gt;Microsoft Windows&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Linux" title="Linux"&gt;Linux&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Solaris" title="Solaris"&gt;Solaris&lt;/a&gt; e &lt;a href="http://pt.wikipedia.org/wiki/Mac_OS_X" title="Mac OS X"&gt;Mac OS X&lt;/a&gt;, além de também ser executável em cima da &lt;a href="http://pt.wikipedia.org/wiki/M%C3%A1quina_virtual_Java" title="Máquina virtual Java"&gt;máquina virtual Java&lt;/a&gt; (através do &lt;a href="http://pt.wikipedia.org/wiki/JRuby" title="JRuby"&gt;JRuby&lt;/a&gt;) e haver um projeto para ser executável em cima da máquina virtual &lt;a href="http://pt.wikipedia.org/wiki/Microsoft_.NET" title="Microsoft .NET"&gt;Microsoft .NET&lt;/a&gt;, o &lt;a class="new" href="http://pt.wikipedia.org/w/index.php?title=IronRuby&amp;amp;action=edit&amp;amp;redlink=1" title="IronRuby (página não existe)"&gt;IronRuby&lt;/a&gt;.&lt;br /&gt;

&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt;&amp;nbsp;&lt;span class="mw-headline" id="Tipos_de_dados"&gt;Tipos de dados&lt;/span&gt;&lt;/h3&gt;
Não existem "tipos primitivos" em Ruby; todos os tipos são &lt;a href="http://pt.wikipedia.org/wiki/Classe_%28programa%C3%A7%C3%A3o%29" title="Classe (programação)"&gt;classes&lt;/a&gt;:&lt;br /&gt;

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Object&lt;/b&gt; é a classe mãe de todas as outras classes em Ruby
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Numeric&lt;/b&gt; é uma classe abstrata que representa números
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Integer&lt;/b&gt; é uma classe que representa números inteiros
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Fixnum&lt;/b&gt; representa números inteiros de precisão fixa&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bignum&lt;/b&gt; representa números inteiros de precisão infinita, dependente apenas da memória disponível&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Float&lt;/b&gt; é uma classe que representa números de ponto flutuante (números reais)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;String&lt;/b&gt; uma cadeia de caracteres. Pode ser delimitado por 
apóstrofes (') ou aspas ("). Tudo o que há entre apóstrofes é 
interpretado literalmente, entre aspas o programador deve se utilizar de
 símbolos para representar caracteres específicos, como em C. Exemplos: 
'azul', "a\nb\nc"&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Symbol&lt;/b&gt; é semelhante a uma string, mas dois símbolos iguais 
possuem o mesmo endereço de memória, sendo assim é ótimo para se 
utilizar como índice numa Hash. Porém, devido à sua natureza, o &lt;a href="http://pt.wikipedia.org/wiki/Coletor_de_lixo" title="Coletor de lixo"&gt;coletor de lixo&lt;/a&gt; do Ruby não os elimina. É definido com um sinal de dois pontos (:), por exemplo,&amp;nbsp;:nome&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Array&lt;/b&gt; são &lt;a href="http://pt.wikipedia.org/wiki/Array" title="Array"&gt;arrays&lt;/a&gt;
 dinâmicos, que podem ser usados para representar matrizes e vetores. É 
delimitado por colchetes ([]) e cada valor é separado por vírgula. 
Exemplo: [4, 'azul',&amp;nbsp;:termometro]&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hash&lt;/b&gt; representa um &lt;a href="http://pt.wikipedia.org/wiki/Vetor_associativo" title="Vetor associativo"&gt;vetor associativo&lt;/a&gt;,
 e, assim como as Arrays, é dinâmica. É delimitada por chaves ({}), e o 
índice precede o valor com um sinal '=&amp;gt;'. Exemplo: {:controller =&amp;gt;
 'user',&amp;nbsp;:action =&amp;gt; 'index'}. Qualquer objeto pode ser um índice, mas
 os mais usados são as Strings e os Symbols&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Regexp&lt;/b&gt; representa &lt;a href="http://pt.wikipedia.org/wiki/Express%C3%A3o_regular" title="Expressão regular"&gt;expressões regulares&lt;/a&gt;, delimitadas por //. Funciona de forma semelhante a Perl. Exemplo: /a|ae/&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Declara.C3.A7.C3.A3o_de_vari.C3.A1veis"&gt;Declaração de variáveis&lt;/span&gt;&lt;/h3&gt;
Um objeto em Ruby é declarado com uma atribuição comum:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;var1 = &lt;span class="nu0"&gt;2&lt;/span&gt;
var2 = Classe.&lt;span class="me1"&gt;new&lt;/span&gt;
var3 = Classe2.&lt;span class="me1"&gt;new&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;parametro&lt;span class="br0"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
Uma variável local é declarada normalmente. Uma variável de instância
 é declarada com um "@" no nome. Uma variável de classe é declarada com 
"@@", e uma variável global é declarada com "$". Variáveis que iniciam 
com uma letra maiúscula são consideradas constantes.&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;local = &lt;span class="st0"&gt;"local"&lt;/span&gt;
&lt;span class="re1"&gt;@instancia&lt;/span&gt; = &lt;span class="nu0"&gt;42&lt;/span&gt;
@@classe = &lt;span class="sy0"&gt;/&lt;/span&gt;f&lt;span class="sy0"&gt;+/&lt;/span&gt;
&lt;span class="re0"&gt;$Pi&lt;/span&gt; = &lt;span class="nu0"&gt;3.1415926&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Exemplos_de_c.C3.B3digo"&gt;Exemplos de código&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Programa_Ol.C3.A1_Mundo"&gt;Programa Olá Mundo&lt;/span&gt;&lt;/h3&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;div class="dablink noprint"&gt;
&lt;a href="http://pt.wikipedia.org/wiki/Programa_Ol%C3%A1_Mundo" title="Programa Olá Mundo"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw3"&gt;puts&lt;/span&gt; &lt;span class="st0"&gt;"Olá, Mundo!"&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Strings"&gt;Strings&lt;/span&gt;&lt;/h3&gt;
Há uma variedade de métodos para definir strings em Ruby. As definições a seguir são equivalentes e suportam interpolação:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;a = &lt;span class="st0"&gt;"&lt;span class="es0"&gt;\n&lt;/span&gt;Isto é uma string de aspas duplas&lt;span class="es0"&gt;\n&lt;/span&gt;"&lt;/span&gt;
a = &lt;span class="sy0"&gt;%&lt;/span&gt;Q&lt;span class="br0"&gt;{&lt;/span&gt;\nIsto é uma &lt;span class="kw3"&gt;string&lt;/span&gt; de aspas duplas\n&lt;span class="br0"&gt;}&lt;/span&gt;
a = &lt;span class="sy0"&gt;%&lt;/span&gt;&lt;span class="br0"&gt;{&lt;/span&gt;\nIsto é uma &lt;span class="kw3"&gt;string&lt;/span&gt; de aspas duplas\n&lt;span class="br0"&gt;}&lt;/span&gt;
a = &lt;span class="sy0"&gt;%/&lt;/span&gt;\nIsto é uma &lt;span class="kw3"&gt;string&lt;/span&gt; de aspas duplas\n&lt;span class="sy0"&gt;/&lt;/span&gt;
a = &lt;span class="co4"&gt;&amp;lt;&lt;bloco aspas="" bloco&lt;="" de="" duplas="" isto="" span="" string="" uma="" é=""&gt;
&lt;/bloco&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
O código a seguir define duas strings "cruas" que são equivalentes:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;a = &lt;span class="st0"&gt;'Isto é uma string de aspas simples'&lt;/span&gt;
a = &lt;span class="sy0"&gt;%&lt;/span&gt;q&lt;span class="br0"&gt;{&lt;/span&gt;Isto é uma &lt;span class="kw3"&gt;string&lt;/span&gt; de aspas simples&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Cole.C3.A7.C3.B5es"&gt;Coleções&lt;/span&gt;&lt;/h3&gt;
&lt;h4&gt;
&lt;span class="editsection"&gt;&lt;/span&gt;&lt;span class="mw-headline" id="Array"&gt;Array&lt;/span&gt;&lt;/h4&gt;
&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;a = &lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="st0"&gt;'oi'&lt;/span&gt;, &lt;span class="nu0"&gt;3.14&lt;/span&gt;, &lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="nu0"&gt;2&lt;/span&gt;, &lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;4&lt;/span&gt;, &lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
 
a&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;2&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;                      &lt;span class="co1"&gt;# =&amp;gt; 3.14&lt;/span&gt;
a.&lt;span class="me1"&gt;reverse&lt;/span&gt;                 &lt;span class="co1"&gt;# =&amp;gt; [[4, 5], 2, 1, 3.14, 'oi', 1]&lt;/span&gt;
a.&lt;span class="me1"&gt;flatten&lt;/span&gt;.&lt;span class="me1"&gt;uniq&lt;/span&gt;            &lt;span class="co1"&gt;# =&amp;gt; [1, 'oi', 3.14, 2, 4, 5]&lt;/span&gt;
a.&lt;span class="me1"&gt;push&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="nu0"&gt;23&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;                &lt;span class="co1"&gt;# a = [1, 'oi', 3.14, 1, 2, [4, 5], 23]&lt;/span&gt;
a &lt;span class="sy0"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nu0"&gt;22&lt;/span&gt;                   &lt;span class="co1"&gt;# a = [1, 'oi', 3.14, 1, 2, [4, 5], 23, 22]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Hash"&gt;Hash&lt;/span&gt;&lt;/h4&gt;
&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;hash = &lt;span class="br0"&gt;{&lt;/span&gt;&lt;span class="st0"&gt;'água'&lt;/span&gt; &lt;span class="sy0"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="st0"&gt;'molhada'&lt;/span&gt;, &lt;span class="st0"&gt;'fogo'&lt;/span&gt; &lt;span class="sy0"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="st0"&gt;'quente'&lt;/span&gt;&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;span class="kw3"&gt;puts&lt;/span&gt; hash&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="st0"&gt;'fogo'&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt; &lt;span class="co1"&gt;# "quente"&lt;/span&gt;
 
hash.&lt;span class="me1"&gt;each_pair&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt;chave, valor&lt;span class="sy0"&gt;|&lt;/span&gt;
  &lt;span class="kw3"&gt;puts&lt;/span&gt; &lt;span class="st0"&gt;"#{chave} é #{valor}"&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
 
&lt;span class="co1"&gt;# Imprime:&lt;/span&gt;
 
&lt;span class="co1"&gt;# água é molhada&lt;/span&gt;
&lt;span class="co1"&gt;# fogo é quente&lt;/span&gt;
 
hash.&lt;span class="me1"&gt;delete_if&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;span class="sy0"&gt;|&lt;/span&gt;chave, valor&lt;span class="sy0"&gt;|&lt;/span&gt; chave == &lt;span class="st0"&gt;'água'&lt;/span&gt;&lt;span class="br0"&gt;}&lt;/span&gt; &lt;span class="co1"&gt;# Apaga 'água' =&amp;gt; 'molhada'&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Blocos_e_iteradores"&gt;Blocos e iteradores&lt;/span&gt;&lt;/h3&gt;
Blocos de código (ou &lt;i&gt;code blocks&lt;/i&gt;) são trechos de código que são passados como parâmetros para métodos. Blocos são extremamente usados em Ruby.&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw1"&gt;class&lt;/span&gt; Paises
  &lt;span class="re1"&gt;@paises&lt;/span&gt; = &lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="st0"&gt;"Argentina"&lt;/span&gt;, &lt;span class="st0"&gt;"Brasil"&lt;/span&gt;, &lt;span class="st0"&gt;"Paraguai"&lt;/span&gt;, &lt;span class="st0"&gt;"Uruguai"&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
 
  &lt;span class="kw1"&gt;def&lt;/span&gt; &lt;span class="kw2"&gt;self&lt;/span&gt;.&lt;span class="me1"&gt;each&lt;/span&gt;
    &lt;span class="kw1"&gt;for&lt;/span&gt; pais &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="re1"&gt;@paises&lt;/span&gt;
      &lt;span class="kw1"&gt;yield&lt;/span&gt; pais
    &lt;span class="kw1"&gt;end&lt;/span&gt;
  &lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
 
Paises.&lt;span class="me1"&gt;each&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt;pais&lt;span class="sy0"&gt;|&lt;/span&gt;
  &lt;span class="kw3"&gt;puts&lt;/span&gt; &lt;span class="st0"&gt;"Olá, #{pais}!"&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;a href="http://pt.wikipedia.org/wiki/Iterator" title="Iterator"&gt;Iterando&lt;/a&gt; em arrays usando blocos:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt; = &lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="st0"&gt;'oi'&lt;/span&gt;, &lt;span class="nu0"&gt;3.14&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
 
&lt;span class="kw3"&gt;array&lt;/span&gt;.&lt;span class="me1"&gt;each&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt;item&lt;span class="sy0"&gt;|&lt;/span&gt;
  &lt;span class="kw3"&gt;puts&lt;/span&gt; item
&lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 'oi'&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 3.14&lt;/span&gt;
 
&lt;span class="co1"&gt;# Equivalente, usando chaves:&lt;/span&gt;
&lt;span class="kw3"&gt;array&lt;/span&gt;.&lt;span class="me1"&gt;each&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt;item&lt;span class="sy0"&gt;|&lt;/span&gt;
  &lt;span class="kw3"&gt;puts&lt;/span&gt; item
&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 'oi'&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 3.14&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
Em Ruby, a &lt;a href="http://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o" title="Estrutura de repetição"&gt;estrutura de repetição for&lt;/a&gt; é apenas &lt;a class="new" href="http://pt.wikipedia.org/w/index.php?title=A%C3%A7%C3%BAcar_sint%C3%A1tico&amp;amp;action=edit&amp;amp;redlink=1" title="Açúcar sintático (página não existe)"&gt;açúcar sintático&lt;/a&gt; para acessar o método each, existente em iteratores.&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt; = &lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="st0"&gt;'oi'&lt;/span&gt;, &lt;span class="nu0"&gt;3.14&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
 
&lt;span class="kw1"&gt;for&lt;/span&gt; item &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="kw3"&gt;array&lt;/span&gt;
  &lt;span class="kw3"&gt;puts&lt;/span&gt; item
&lt;span class="kw1"&gt;end&lt;/span&gt;
 
&lt;span class="co1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 'oi'&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; 3.14&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
Blocos funcionam com muitos métodos padrão; no exemplo a seguir, o uso de blocos com arquivos:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw4"&gt;File&lt;/span&gt;.&lt;span class="kw3"&gt;open&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="st0"&gt;'arquivo.txt'&lt;/span&gt;, &lt;span class="st0"&gt;'w'&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt;arquivo&lt;span class="sy0"&gt;|&lt;/span&gt;
  &lt;span class="kw1"&gt;for&lt;/span&gt; i &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;..&lt;span class="nu0"&gt;3&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;
    arquivo.&lt;span class="kw3"&gt;puts&lt;/span&gt; &lt;span class="st0"&gt;'Olá, Mundo!'&lt;/span&gt;
  &lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;                                  &lt;span class="co1"&gt;# O arquivo é fechado automaticamente aqui&lt;/span&gt;
 
&lt;span class="kw4"&gt;File&lt;/span&gt;.&lt;span class="kw3"&gt;readlines&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="st0"&gt;'arquivo.txt'&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;.&lt;span class="me1"&gt;each&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt;linha&lt;span class="sy0"&gt;|&lt;/span&gt;
  &lt;span class="kw3"&gt;puts&lt;/span&gt; linha
&lt;span class="kw1"&gt;end&lt;/span&gt;
 
&lt;span class="co1"&gt;# =&amp;gt; Olá, Mundo!&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; Olá, Mundo!&lt;/span&gt;
&lt;span class="co1"&gt;# =&amp;gt; Olá, Mundo!&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
Criando uma &lt;a class="new" href="http://pt.wikipedia.org/w/index.php?title=Fun%C3%A7%C3%A3o_an%C3%B4nima&amp;amp;action=edit&amp;amp;redlink=1" title="Função anônima (página não existe)"&gt;função anônima&lt;/a&gt;:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw3"&gt;proc&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;span class="sy0"&gt;|&lt;/span&gt;arg&lt;span class="sy0"&gt;|&lt;/span&gt; &lt;span class="kw3"&gt;print&lt;/span&gt; arg&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;span class="kw3"&gt;Proc&lt;/span&gt;.&lt;span class="me1"&gt;new&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;span class="sy0"&gt;|&lt;/span&gt;arg&lt;span class="sy0"&gt;|&lt;/span&gt; &lt;span class="kw3"&gt;print&lt;/span&gt; arg&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;span class="kw3"&gt;lambda&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;span class="sy0"&gt;|&lt;/span&gt;arg&lt;span class="sy0"&gt;|&lt;/span&gt; &lt;span class="kw3"&gt;print&lt;/span&gt; arg&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Classes"&gt;Classes&lt;/span&gt;&lt;/h3&gt;
O código a seguir define uma &lt;a href="http://pt.wikipedia.org/wiki/Classe_%28programa%C3%A7%C3%A3o%29" title="Classe (programação)"&gt;classe&lt;/a&gt; chamada Pessoa. Além de &lt;i&gt;initialize&lt;/i&gt;, o construtor para criar novos &lt;a href="http://pt.wikipedia.org/wiki/Objeto" title="Objeto"&gt;objetos&lt;/a&gt;, essa classe tem dois &lt;a href="http://pt.wikipedia.org/wiki/M%C3%A9todo_%28programa%C3%A7%C3%A3o%29" title="Método (programação)"&gt;métodos&lt;/a&gt;: um que &lt;a class="new" href="http://pt.wikipedia.org/w/index.php?title=Sobrecarga_de_operadores&amp;amp;action=edit&amp;amp;redlink=1" title="Sobrecarga de operadores (página não existe)"&gt;sobre-escreve o operador&lt;/a&gt; de comparação &lt;code&gt;&amp;gt;&lt;/code&gt; (maior), e sobre-escreve o método &lt;code&gt;to_s&lt;/code&gt; (assim o comando &lt;code&gt;puts&lt;/code&gt; pode formatar a saída). Aqui &lt;code&gt;attr_reader&lt;/code&gt; é um exemplo de metaprogramação em Ruby: &lt;code&gt;attr_reader&lt;/code&gt; define o método getter, &lt;code&gt;attr_writer&lt;/code&gt; define o método setter, e &lt;code&gt;attr_accessor&lt;/code&gt;
 define ambos. Em Ruby, todos os atributos são privados e todos os 
métodos públicos, por padrão. Ruby permite definir opcionalmente o tipo 
de acesso usando três palavras-chave: public (público), private 
(privado) e protected (protegido). Ruby não suporta &lt;a href="http://pt.wikipedia.org/wiki/Sobrecarga" title="Sobrecarga"&gt;sobrecarga de métodos&lt;/a&gt;, mas suporta &lt;a class="new" href="http://pt.wikipedia.org/w/index.php?title=Argumentos_padr%C3%A3o&amp;amp;action=edit&amp;amp;redlink=1" title="Argumentos padrão (página não existe)"&gt;argumentos padrão&lt;/a&gt;,
 que podem ser utilizados para o mesmo fim. Também, o último comando em 
um método é considerado o seu valor de retorno, permitindo a omissão de 
um explícito &lt;code&gt;return&lt;/code&gt;.&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw1"&gt;class&lt;/span&gt; Pessoa
  attr_reader &lt;span class="re3"&gt;:nome&lt;/span&gt;, &lt;span class="re3"&gt;:idade&lt;/span&gt;
 
  &lt;span class="kw1"&gt;def&lt;/span&gt; initialize&lt;span class="br0"&gt;(&lt;/span&gt;nome = &lt;span class="st0"&gt;"Desconhecido"&lt;/span&gt;, idade&lt;span class="br0"&gt;)&lt;/span&gt;
    &lt;span class="re1"&gt;@nome&lt;/span&gt;, &lt;span class="re1"&gt;@idade&lt;/span&gt; = nome, idade
  &lt;span class="kw1"&gt;end&lt;/span&gt;
 
  &lt;span class="kw1"&gt;def&lt;/span&gt; &lt;span class="sy0"&gt;&amp;gt;&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;pessoa&lt;span class="br0"&gt;)&lt;/span&gt;
    &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="kw2"&gt;self&lt;/span&gt;.&lt;span class="me1"&gt;idade&lt;/span&gt; &lt;span class="sy0"&gt;&amp;gt;&lt;/span&gt; pessoa.&lt;span class="me1"&gt;idade&lt;/span&gt;
      &lt;span class="kw2"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;true&lt;/span&gt;
    &lt;span class="kw1"&gt;else&lt;/span&gt;
      &lt;span class="kw2"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;false&lt;/span&gt;
    &lt;span class="kw1"&gt;end&lt;/span&gt;
  &lt;span class="kw1"&gt;end&lt;/span&gt;
 
  &lt;span class="kw1"&gt;def&lt;/span&gt; to_s &lt;span class="co1"&gt;# Método usado pelo método puts() para formatar a saída&lt;/span&gt;
    &lt;span class="st0"&gt;"#@nome (#@idade anos)"&lt;/span&gt;
  &lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
 
pessoas = &lt;span class="br0"&gt;[&lt;/span&gt;
            Pessoa.&lt;span class="me1"&gt;new&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="st0"&gt;"Ricardo"&lt;/span&gt;, &lt;span class="nu0"&gt;19&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;,
            Pessoa.&lt;span class="me1"&gt;new&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;idade = &lt;span class="nu0"&gt;25&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;
          &lt;span class="br0"&gt;]&lt;/span&gt;
 
&lt;span class="kw3"&gt;puts&lt;/span&gt; pessoas&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
&lt;span class="kw3"&gt;puts&lt;/span&gt; pessoas&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
&lt;span class="kw3"&gt;puts&lt;/span&gt; pessoas&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt; &lt;span class="sy0"&gt;&amp;gt;&lt;/span&gt; pessoas&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt; &lt;span class="co1"&gt;# O mesmo que: pessoas[0].&amp;gt;(pessoas[1])&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
O código acima irá imprimir:&lt;br /&gt;

&lt;pre&gt;Ricardo (19 anos)
Desconhecido (25 anos)
false
&lt;/pre&gt;
&lt;h4&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Classes_abertas"&gt;Classes abertas&lt;/span&gt;&lt;/h4&gt;
Em Ruby, as classes nunca são fechadas: você pode sempre adicionar 
novos métodos a uma classe. Isso se aplica tanto para classes criadas 
por você, quanto para as classes padrão. Um exemplo simples de adição de
 um novo método a classe padrão String:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw1"&gt;class&lt;/span&gt; &lt;span class="kw3"&gt;String&lt;/span&gt;
  &lt;span class="kw1"&gt;def&lt;/span&gt; iniciais
    ini = &lt;span class="kw3"&gt;String&lt;/span&gt;.&lt;span class="me1"&gt;new&lt;/span&gt;
 
    &lt;span class="kw1"&gt;for&lt;/span&gt; nome &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="kw2"&gt;self&lt;/span&gt;.&lt;span class="kw3"&gt;split&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;
      ini &lt;span class="sy0"&gt;+&lt;/span&gt;= nome&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;
    &lt;span class="kw1"&gt;end&lt;/span&gt;
 
    &lt;span class="kw2"&gt;return&lt;/span&gt; ini
  &lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
 
&lt;span class="kw3"&gt;puts&lt;/span&gt; &lt;span class="st0"&gt;"Ricardo Silva Veloso"&lt;/span&gt;.&lt;span class="me1"&gt;iniciais&lt;/span&gt; &lt;span class="co1"&gt;# Imprime RSV&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Heran.C3.A7a"&gt;Herança&lt;/span&gt;&lt;/h4&gt;
Ruby não suporta &lt;a href="http://pt.wikipedia.org/wiki/Heran%C3%A7a_m%C3%BAltipla" title="Herança múltipla"&gt;herança múltipla&lt;/a&gt;. Ao invés disso, Ruby usa Mixins para emular herança múltipla:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw1"&gt;class&lt;/span&gt; Pessoa &lt;span class="sy0"&gt;&amp;lt;&lt;/span&gt; Mamifero &lt;span class="co1"&gt;# Herança de Mamifero&lt;/span&gt;
  &lt;span class="kw1"&gt;include&lt;/span&gt; Humano &lt;span class="co1"&gt;# Emulando herança múltipla&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
No exemplo acima, "Humano" é um módulo (&lt;i&gt;module&lt;/i&gt;).&lt;br /&gt;

&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Modules"&gt;Modules&lt;/span&gt;&lt;/h3&gt;
Além das classes normais, Ruby possui os "Modules", que são classes de classes, permitindo &lt;a href="http://pt.wikipedia.org/wiki/Espa%C3%A7o_de_nomes" title="Espaço de nomes"&gt;espaço de nomes&lt;/a&gt;:&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw1"&gt;module&lt;/span&gt; Humano
  &lt;span class="kw1"&gt;class&lt;/span&gt; Classe1
    &lt;span class="kw1"&gt;def&lt;/span&gt; info
      &lt;span class="st0"&gt;"#{self.class} (&lt;span class="es0"&gt;\#&lt;/span&gt;#{self.object_id}): #{self.to_s}"&lt;/span&gt;
    &lt;span class="kw1"&gt;end&lt;/span&gt;
  &lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Tratamento_de_exce.C3.A7.C3.B5es"&gt;Tratamento de exceções&lt;/span&gt;&lt;/h3&gt;
Como a maioria das linguagens modernas, Ruby também possui suporte 
para tratamento de exceção. As palavras-chave para isto são "begin", 
"rescue" e "ensure". "Begin" inicia um trecho que pode cair em alguma 
exceção (opcional), "Rescue" determina o comportamento em caso de uma 
exceção específica ou não e, "Ensure" é o código que será executado 
independente de ter havido exceção ou não.&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw1"&gt;begin&lt;/span&gt;
&lt;span class="co1"&gt;# Faça algo&lt;/span&gt;
&lt;span class="kw1"&gt;rescue&lt;/span&gt;
&lt;span class="co1"&gt;# Trata alguma exceção&lt;/span&gt;
&lt;span class="kw1"&gt;else&lt;/span&gt;
&lt;span class="co1"&gt;# Faça isto se nehuma exceção for lançada&lt;/span&gt;
&lt;span class="kw1"&gt;ensure&lt;/span&gt;
&lt;span class="co1"&gt;# Faça isto se alguma ou nenhuma exceção for lançada&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Ruby_para_administradores_de_sistemas"&gt;Ruby para administradores de sistemas&lt;/span&gt;&lt;/h3&gt;
A maioria dos administradores de sistemas &lt;a href="http://pt.wikipedia.org/wiki/Unix" title="Unix"&gt;Unix&lt;/a&gt; utilizam &lt;a href="http://pt.wikipedia.org/wiki/Perl" title="Perl"&gt;Perl&lt;/a&gt; ou Shell Script como ferramenta para resolver os problemas. Mas é possível usar Ruby e &lt;a href="http://pt.wikipedia.org/wiki/Python" title="Python"&gt;Python&lt;/a&gt;
 para os mesmos fins. Abaixo, a idéia é fazer um pequeno script que 
verifica se o serviço da porta 80 (Web) de alguns servidores estavam 
ativos.&lt;br /&gt;

&lt;div class="mw-geshi" dir="ltr" style="text-align: left;"&gt;

&lt;div class="ruby source-ruby"&gt;

&lt;pre class="de1"&gt;&lt;span class="kw3"&gt;require&lt;/span&gt; &lt;span class="st0"&gt;'net/http'&lt;/span&gt;
 
&lt;span class="kw4"&gt;File&lt;/span&gt;.&lt;span class="kw3"&gt;open&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="st0"&gt;"hosts.txt"&lt;/span&gt;, &lt;span class="st0"&gt;"r"&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;.&lt;span class="me1"&gt;each_line&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; &lt;span class="sy0"&gt;|&lt;/span&gt; host &lt;span class="sy0"&gt;|&lt;/span&gt;
 
  conexao = &lt;span class="re2"&gt;Net::HTTP&lt;/span&gt;.&lt;span class="me1"&gt;new&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;host.&lt;span class="kw3"&gt;chomp&lt;/span&gt;, &lt;span class="nu0"&gt;80&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;
  resposta, conteudo = conexao.&lt;span class="me1"&gt;get&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="st0"&gt;"/"&lt;/span&gt;, &lt;span class="kw2"&gt;nil&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;
 
  &lt;span class="kw1"&gt;if&lt;/span&gt; resposta.&lt;span class="me1"&gt;code&lt;/span&gt;.&lt;span class="me1"&gt;to_i&lt;/span&gt; &lt;span class="sy0"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nu0"&gt;400&lt;/span&gt;
  &lt;span class="co1"&gt;# aqui vai a rotina pra enviar email...&lt;/span&gt;
  &lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;span class="kw1"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;
&lt;span class="editsection"&gt;&lt;/span&gt; &lt;span class="mw-headline" id="Reposit.C3.B3rios_e_bibliotecas"&gt;Repositórios e bibliotecas&lt;/span&gt;&lt;/h2&gt;
Ruby possui repositórios de &lt;a href="http://pt.wikipedia.org/wiki/Biblioteca_%28computa%C3%A7%C3%A3o%29" title="Biblioteca (computação)"&gt;bibliotecas&lt;/a&gt; disponíveis em sites como &lt;i&gt;Ruby Forge&lt;/i&gt; e &lt;i&gt;Ruby Application Archive (RAA)&lt;/i&gt;. Existe, ainda, uma ferramenta de instalação de bibliotecas, chamada &lt;a href="http://pt.wikipedia.org/wiki/RubyGems" title="RubyGems"&gt;RubyGems&lt;/a&gt;, semelhante aos gerenciadores de pacotes do &lt;a href="http://pt.wikipedia.org/wiki/Linux" title="Linux"&gt;Linux&lt;/a&gt;, como o &lt;a href="http://pt.wikipedia.org/wiki/Advanced_Packaging_Tool" title="Advanced Packaging Tool"&gt;APT&lt;/a&gt;. O projeto mais famoso desenvolvido em Ruby é o meta-framework &lt;a href="http://pt.wikipedia.org/wiki/Ruby_on_Rails" title="Ruby on Rails"&gt;Ruby on Rails&lt;/a&gt;.&lt;br /&gt;

Recentemente, muitas bibliotecas novas e existentes foram hospedadas no &lt;a href="http://pt.wikipedia.org/wiki/GitHub" title="GitHub"&gt;GitHub&lt;/a&gt;, que é focado em &lt;a href="http://pt.wikipedia.org/wiki/Git" title="Git"&gt;Git&lt;/a&gt; e tinha suporte nativo ao empacotamento do RubyGems.&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-4627412147504974996?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Q9dZw2IrpGsfYDIQtEhcYHf5VQg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Q9dZw2IrpGsfYDIQtEhcYHf5VQg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Q9dZw2IrpGsfYDIQtEhcYHf5VQg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Q9dZw2IrpGsfYDIQtEhcYHf5VQg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/9zhWuRPOs2Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/4627412147504974996/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/09/ruby-linguagem-de-programacao.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/4627412147504974996?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/4627412147504974996?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/9zhWuRPOs2Q/ruby-linguagem-de-programacao.html" title="Ruby (linguagem de programação)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/09/ruby-linguagem-de-programacao.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYGRHc7cSp7ImA9WhdXF04.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-3833244111673108791</id><published>2011-08-29T08:04:00.004-03:00</published><updated>2011-08-30T15:48:45.909-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-30T15:48:45.909-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programas" /><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><title /><content type="html">&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family: arial;"&gt;Smac - Programa que altera o MAC de sua placa de rede. &lt;br /&gt;
&lt;br /&gt;
Link para download aqui =&amp;gt; &lt;a href="http://www.mediafire.com/?4xo2i46h6oc12z6"&gt;Download&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Muito útil e bom. &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: lucida grande;"&gt;&lt;span style="font-weight: bold;"&gt;Serial Incluso.&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-3833244111673108791?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AurAUhTed0qc7myIRuAV06RhYv4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AurAUhTed0qc7myIRuAV06RhYv4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AurAUhTed0qc7myIRuAV06RhYv4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AurAUhTed0qc7myIRuAV06RhYv4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/266t5uAtj3s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/3833244111673108791/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/smac-programa-que-altera-o-mac-de-sua.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/3833244111673108791?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/3833244111673108791?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/266t5uAtj3s/smac-programa-que-altera-o-mac-de-sua.html" title="" /><author><name>FlashMaster</name><uri>http://www.blogger.com/profile/07169477119786543965</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_s9jwz1v02dI/S2QoMaA2NnI/AAAAAAAAAKM/51K1Rs6z674/S220/tri.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/smac-programa-que-altera-o-mac-de-sua.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4BRHk4eSp7ImA9WhdXE0o.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-960649697628503435</id><published>2011-08-24T23:35:00.001-03:00</published><updated>2011-08-26T13:42:35.731-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-26T13:42:35.731-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dicas de segurança" /><category scheme="http://www.blogger.com/atom/ns#" term="Programas" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas Hackers" /><category scheme="http://www.blogger.com/atom/ns#" term="Downloads" /><title>Wireshark  download</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;br /&gt;
&lt;div class="top_review_box"&gt;&lt;div class="program_description vcard clearfix"&gt;&lt;div class="title_div"&gt;&lt;h2&gt;&lt;b class="summary author_says"&gt;"Wireshark é uma Poderosa ferramenta para análise de protocolos”&lt;/b&gt;&lt;/h2&gt;&lt;div class="author"&gt;&lt;a href="http://wireshark.softonic.com.br/" title="Wireshark"&gt;&lt;br /&gt;
&lt;/a&gt;  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="description_l clearfix" id="prg_description"&gt;&lt;div class="description" id="desc_body"&gt;&lt;b&gt;O Wireshark é uma ferramenta profissional que auxilia quem precisa  resolver problemas de conexão e rede. O aplicativo disponibiliza diversas  informações para fazer uma análise apurada.&lt;/b&gt;&lt;br /&gt;
Analisar pacote de dados enviados e recebidos é uma forma de monitorar  possíveis problemas com a conexão. Do mesmo jeito também é possível detectar o  tráfego na rede. Mas como é que se pode controlar tais pacotes?&lt;br /&gt;
Todas as principais ferramentas para análise de dados estão presentes no  Wireshark. O Wireshark oferece informações sobre a &lt;b&gt;placa de rede,  Bluetooth, USB, Frame Relay&lt;/b&gt; e outras partes importantes da máquina  (depende da plataforma usada). Por ser desenvolvido em código aberto, os  desenvolvedores atualizam o Wireshark constantemente com melhoras e conserto de  pequenos bugs.&lt;br /&gt;
Se você não conhece muito de protocolos e deseja se aprofundar no tema, o  Wireshark possui um fórum bastante movimentado. Se já conhece de redes, mão na  massa porque o Wireshark é uma ótima utilidade.&lt;/div&gt;&lt;div class="clearfix" id="pros_cons"&gt;&lt;div class="pros"&gt;&lt;b&gt;Prós&lt;/b&gt;  &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Grátis&lt;/li&gt;
&lt;li&gt;Analisa centenas de protocolos&lt;/li&gt;
&lt;li&gt;Multiplataforma&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div class="cons"&gt;&lt;b&gt;Contras&lt;/b&gt;  &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Não tem versão em português&lt;/li&gt;
&lt;li&gt;Não recomendável para iniciantes&lt;/li&gt;
&lt;li&gt;Requer conhecimentos de análise de  protocolos&lt;/li&gt;
&lt;/ul&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.4shared.com/file/0CXPPABF/WireShark_by-ProgMastertk_.html" target="_blank"&gt;&lt;u&gt;&lt;b&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif; font-size: x-large;"&gt;Download &lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-960649697628503435?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vvdxMInO_ylexWIH7b6YIKE8Hh0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vvdxMInO_ylexWIH7b6YIKE8Hh0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vvdxMInO_ylexWIH7b6YIKE8Hh0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vvdxMInO_ylexWIH7b6YIKE8Hh0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/qVN0lzH0mRU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/960649697628503435/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/wireshark-download.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/960649697628503435?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/960649697628503435?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/qVN0lzH0mRU/wireshark-download.html" title="Wireshark  download" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/wireshark-download.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EDQHgycSp7ImA9WhdQFUg.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-8216595909103519017</id><published>2011-08-17T00:27:00.000-03:00</published><updated>2011-08-17T00:27:51.699-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-17T00:27:51.699-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C\C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Downloads" /><title>C / C++ e Orientação a Objetos em Ambiente Multiplataforma</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;Apostila muito completa e ilustrativa abordando a linguagem C e C++ com orientação a objetos&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.4shared.com/file/zDG4moly/C_C_e_Orientao_a_Objetos_Multi.html" target="_Blank"&gt;&lt;b&gt;&lt;span style="font-family: Georgia,&amp;quot;Times New Roman&amp;quot;,serif; font-size: x-large;"&gt;Download&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="font-family: Georgia,&amp;quot;Times New Roman&amp;quot;,serif; font-size: x-large;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="position: fixed;"&gt;&lt;div id="new_selection_block0.7956282578074287" style="background-color: transparent; border: medium none; color: black; overflow: hidden; text-align: left; text-decoration: none;"&gt;&lt;br /&gt;
&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-8216595909103519017?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1bI8zck1WIiArkUDr5k7MPuvTkc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1bI8zck1WIiArkUDr5k7MPuvTkc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1bI8zck1WIiArkUDr5k7MPuvTkc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1bI8zck1WIiArkUDr5k7MPuvTkc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/ag9DdYvU8-Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/8216595909103519017/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/c-c-e-orientacao-objetos-em-ambiente.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/8216595909103519017?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/8216595909103519017?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/ag9DdYvU8-Q/c-c-e-orientacao-objetos-em-ambiente.html" title="C / C++ e Orientação a Objetos em Ambiente Multiplataforma" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/c-c-e-orientacao-objetos-em-ambiente.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YAQ3s6fCp7ImA9WhdQFUg.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-6657734819836259353</id><published>2011-08-17T00:19:00.000-03:00</published><updated>2011-08-17T00:19:02.514-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-17T00:19:02.514-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C\C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Downloads" /><title>Apostila com exemplos de árvores binárias</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;Apostila com&amp;nbsp; alguns exemplos de árvores binárias&amp;nbsp; &lt;/b&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div style="font-family: Arial,Helvetica,sans-serif; text-align: center;"&gt;&lt;a href="http://www.4shared.com/file/GK-jlI_x/Apostila_com_exemplos_de_rvore.html" target="_blank"&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;Download&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-6657734819836259353?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tkdszepLKdY3ySh0EI4MEFvIXoo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tkdszepLKdY3ySh0EI4MEFvIXoo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tkdszepLKdY3ySh0EI4MEFvIXoo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tkdszepLKdY3ySh0EI4MEFvIXoo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/GCOLTsCJ6Tc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/6657734819836259353/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/apostila-com-exemplos-de-arvores.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/6657734819836259353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/6657734819836259353?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/GCOLTsCJ6Tc/apostila-com-exemplos-de-arvores.html" title="Apostila com exemplos de árvores binárias" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/apostila-com-exemplos-de-arvores.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEAQ3k6eSp7ImA9WhdQFUg.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-7299149542089014421</id><published>2011-08-17T00:05:00.001-03:00</published><updated>2011-08-17T00:10:42.711-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-17T00:10:42.711-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C\C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Downloads" /><title>Apostila completa sobre C/C++ em português</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;A linguagem C tornou-se uma das linguagens de programação mais usadas. Flexível, ainda que poderosa, a linguagem C tem sido utilizada na criação de alguns dos mais importantes produtos de software dos últimos anos. O C ou o C++ tem possibilidades quase que infinitas...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Leia mais na ProgMaster: Apostila completa sobre C/C++ em português&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;a href="http://www.4shared.com/file/mkAxN5Yo/linguagem_c.html" target="_blank"&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;Download&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-7299149542089014421?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/R_DvbWv0lta4zNucTkV2lnJpvMI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R_DvbWv0lta4zNucTkV2lnJpvMI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/R_DvbWv0lta4zNucTkV2lnJpvMI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R_DvbWv0lta4zNucTkV2lnJpvMI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/ERvzugrnZV0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/7299149542089014421/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/apostila-completa-sobre-cc-em-portugues.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/7299149542089014421?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/7299149542089014421?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/ERvzugrnZV0/apostila-completa-sobre-cc-em-portugues.html" title="Apostila completa sobre C/C++ em português" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/apostila-completa-sobre-cc-em-portugues.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUADQX0_fCp7ImA9WhdQFEs.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-3565690508907919798</id><published>2011-08-16T00:02:00.000-03:00</published><updated>2011-08-16T00:02:50.344-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-16T00:02:50.344-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 7)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;- Reproduzindo sons com o PC speaker&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As instruções assembler IN e OUT permitem ler e escrever em uma porta de&lt;br /&gt;
E/S respectivamente.&lt;br /&gt;
&lt;br /&gt;
Para ler de uma porta:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; IN acumulador, porta&lt;br /&gt;
&lt;br /&gt;
IN le um byte, word ou doubleword da porta especificada para o registro&lt;br /&gt;
acumulador, isto é, AL, AX, ou EAX para byte, word ou doubleword&lt;br /&gt;
respectivamente. O número de porta pode ser uma constante do tipo byte&lt;br /&gt;
(0..255) um o registro DX (para acesso a todas as portas de E/S).&lt;br /&gt;
&lt;br /&gt;
Para escrever em uma porta:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; OUT porta, acumulador&lt;br /&gt;
&lt;br /&gt;
OUT escreve o byte, word ou doubleword no registro acumulador para a&lt;br /&gt;
porta especificada. Novamente, o número da porta pode ser uma constate&lt;br /&gt;
do tipo byte ou o valor do registro DX.&lt;br /&gt;
&lt;br /&gt;
NOTA: Uma vez que IN e OUT implicam no acesso direto ao hardware, e&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sabendo que os Windows NT/2000/XP não permitem que aplicativos&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; do usuário acessem o hardware diretamente, essas instruções não&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; funcionarão (irão gerar exceções) nesses sistemas operacionais&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (a não ser que estejam rodando em modo protegido no anel 0, ou&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; modo kernel).&lt;br /&gt;
&lt;br /&gt;
Abaixo, veremos um exemplo do uso de assembler na leitura e escrita&lt;br /&gt;
às portas de E/S para programar os chips 8253/8254 Contador/Timer e&lt;br /&gt;
o 8255 Programmable Peripheral Interface (PPI) na placa-mãe de modo&lt;br /&gt;
a fazer o PC speaker reproduzir um som.&lt;br /&gt;
&lt;br /&gt;
Os passos para tocar um som usando os chips são os seguintes:&lt;br /&gt;
&lt;br /&gt;
1) Prepare os 8253/8254 para receber a freqüência. Isso é feito ao&lt;br /&gt;
&amp;nbsp;&amp;nbsp; escrever o valor $B6 no Timer Control Register (porta $43).&lt;br /&gt;
&lt;br /&gt;
2) Escrever a freqüência do som no Frequency Register do 8253/8254&lt;br /&gt;
&amp;nbsp;&amp;nbsp; (porta $42). Na verdade, não é a freqüência em Hertz que devemos&lt;br /&gt;
&amp;nbsp;&amp;nbsp; escrever no registro, mas o resultado de 1331000 dividido nesta&lt;br /&gt;
&amp;nbsp;&amp;nbsp; freqüência. Primeiramente devemos escrever o byte de mais baixa&lt;br /&gt;
&amp;nbsp;&amp;nbsp; ordem do resultado para, em seguida, o byte de mais alta ordem.&lt;br /&gt;
&lt;br /&gt;
3) Ligar o PC speaker e fazê-lo utilizar o 8253/8254 Counter/Timer.&lt;br /&gt;
&amp;nbsp;&amp;nbsp; Isso é feito ao definir os dois primeiros bits da Porta B do 8255&lt;br /&gt;
&amp;nbsp;&amp;nbsp; PPI (porta $61).&lt;br /&gt;
&lt;br /&gt;
4) Desligar o PC speaker quando o som finalizar. Isso é feito ao&lt;br /&gt;
&amp;nbsp;&amp;nbsp; zerar o segundo bit da porta B do 8255 PPI (porta $61).&lt;br /&gt;
&lt;br /&gt;
A função assembler inline abaixo implementa os passos listados acima:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure SpeakerSound(Frequency: word; Duration: longint);&lt;br /&gt;
&amp;nbsp; // Copyright (c) 2003 Ernesto De Spirito&lt;br /&gt;
&amp;nbsp; // Visit: http://www.latiumsoftware.com&lt;br /&gt;
&amp;nbsp; // Plays a tone thru the PC speaker using the 8253/8254&lt;br /&gt;
&amp;nbsp; // Counter/Timer chip and the 8255 Programmable Peripheral&lt;br /&gt;
&amp;nbsp; // Interface (PPI) chip on the motherboard.&lt;br /&gt;
&amp;nbsp; // NOTE: This code won't work under Windows NT/2000/XP.&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Push Duration on the stack (for Sleep)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov cx, ax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // CX := Frequency;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Prepare the 8253/8254 to receive the frequency data&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov al, $B6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Function: Expect frequency data&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; out $43, al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write to Timer Control Register&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Compute the frequency data&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov dx, $14&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // DX:AX = $144F38&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ax, $4F38&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 1331000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; div cx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AX := 1331000 / Frequency;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Send the frequency data to the 8253/8254 Counter/Timer chip&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; out $42, al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write low byte to the Frequency Address&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov al, ah&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL := High byte of AX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; out $42, al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write high byte to the Frequency Address&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Tell the 8255 PPI to start the sound&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; in al, $61&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Read Port B of the 8255 PPI&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; or al, $03&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Set bits 0 and 1:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // bit 0 --&amp;gt; use the 8253/8254&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // bit 1 --&amp;gt; turn speaker on&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; out $61, al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write to Port B of the 8255 PPI&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call Sleep&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Sleep(Duration); // requires Windows unit&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Tell the 8255 PPI to stop the sound&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; in al, $61&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Read Port B of the 8255 PPI&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; and al, NOT 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Clear bit 1 (turn speaker off)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; out $61, al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write to Port B of the 8255 PPI&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Exemplo de chamada:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure TForm1.Button1Click(Sender: TObject);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; i: integer;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Randomize;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; for i := 1 to 3 do&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SpeakerSound(Random(900)+100, 200);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
NOTA: Usar o PC speaker para gerar som é OBSOLETO. Aplicações devem usar&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sons MIDI ou WAVE ao invés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;a href="http://www.4shared.com/file/ixBpotIO/Delphi_e_Assembly__by_-_ProgMa.html" target="_blank"&gt;&lt;span style="font-size: x-large;"&gt;&lt;b&gt;Download dos sources&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-3565690508907919798?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/m-LHgXa3fKtYZGxs9wYVpVBF6Bc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/m-LHgXa3fKtYZGxs9wYVpVBF6Bc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/m-LHgXa3fKtYZGxs9wYVpVBF6Bc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/m-LHgXa3fKtYZGxs9wYVpVBF6Bc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/ZjmjOPVantw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/3565690508907919798/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-7.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/3565690508907919798?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/3565690508907919798?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/ZjmjOPVantw/delphi-com-assembly-parte-7.html" title="Delphi com assembly (Parte 7)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-7.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMBRH8zfyp7ImA9WhdQFEs.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-49694880040601938</id><published>2011-08-15T23:40:00.000-03:00</published><updated>2011-08-15T23:40:55.187-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-15T23:40:55.187-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 6)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;&amp;nbsp;Aritmética Inteira de 128 bits (3)&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Nessa terceira e última parte da série sobre inteiros de 128-bit (que&lt;br /&gt;
chamamos de inteiros gigantes, inteiros enormes ou inteiros largos)&lt;br /&gt;
vamos finalmente lidar com a aritimética propriamente dita- as quatro&lt;br /&gt;
operações fundamenteais (adição, subtração, multiplicação e divisão).&lt;br /&gt;
&lt;br /&gt;
Antes de iniciar, gostaria de avisar que as rotinas introduzidas nas&lt;br /&gt;
duas partes anteriores foram corrigidas e também otimizadas. Ainda&lt;br /&gt;
não pude testá-las tanto quanto gostarias. Se você encontrar erros ou&lt;br /&gt;
tiver algum comentário sobre os fontes, por favor me envie um e-mail.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Adição&lt;br /&gt;
======&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Como somamos dois números, cada um formado de quatro inteiros de 32-bit?&lt;br /&gt;
Bem, é bem fácil. Simplesmente somamos como faríamos com dois números de&lt;br /&gt;
quatro dígitos decimais (como 3597 e 0015, por exemplo), exceto que cada&lt;br /&gt;
dígito aqui pode ter aproximadamente 4 bilhões (2^32) de valores&lt;br /&gt;
distintos ao invés de apenas dez. O algoritmo é algo como:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function AddWithCarry(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Carry: Boolean): Longint; forward;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeAdd(x: Hugeint; y: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := x + y;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Carry: Boolean;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Carry := False;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[0] := AddWithCarry(x[0], y[0], Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[1] := AddWithCarry(x[1], y[1], Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[2] := AddWithCarry(x[2], y[2], Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[3] := AddWithCarry(x[3], y[3], Carry);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
AddWithCarry é uma função fictícia que retorna um inteiro com os 32 bits&lt;br /&gt;
de mais baixa ordem do resultado da adição dos dois argumentos, mais um&lt;br /&gt;
se Carry (o terceiro argumento) for True. A rotina também altera o valor&lt;br /&gt;
de Carry com True o False dependendo da adição ter gerado um excesso ou&lt;br /&gt;
não (ou se o carry é 1 ou 0, se você prefere ver dessa forma). Na&lt;br /&gt;
prática, essa função não precisa ser fictícia:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function AddWithCarry(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Carry: Boolean): integer;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if Carry then CF := 1 else CF := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; test byte ptr [ecx], -1&amp;nbsp;&amp;nbsp; // efeito colateral: CF := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jz @@NoCarry&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; stc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // CF := 1;&lt;br /&gt;
&amp;nbsp; @@NoCarry:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := x + y + CF;&amp;nbsp; CF := GeneratedCarry;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; adc eax, edx&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Carry := CF;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; setc byte ptr [ecx]&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
É mais eficiente codificar HugeAdd inteiramente em assembler:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeAdd(x: Hugeint; y: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := x + y;&lt;br /&gt;
&amp;nbsp; // Parameters: EAX = @x; EDX = @y; ECX = @Result&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push esi&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, [eax+_0_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := x[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add esi, [edx+_0_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := ESI + y[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_0_], esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[0] := ESI;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, [eax+_1_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := x[1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; adc esi, [edx+_1_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := ESI + y[1] + Carry;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_1_], esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[1] := ESI;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, [eax+_2_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := x[2];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; adc esi, [edx+_2_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := ESI + y[2] + Carry;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_2_], esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[2] := ESI;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, [eax+_3_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := x[3];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; adc esi, [edx+_3_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := ESI + y[3] + Carry;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_3_], esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[3] := ESI;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop esi&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Subtração&lt;br /&gt;
=========&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
A subtração acontece de forma semelhante à adição mas, ao invés de gerar&lt;br /&gt;
um excesso, a operação gera um "empréstimo" (também representado pelo&lt;br /&gt;
flag Carry) se o minuendo (primeiro operando) é menor que o subtraendo&lt;br /&gt;
(segundo operando):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function SubtractWithBorrow(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Borrow: Boolean): Longint; forward;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeSub(x: Hugeint; y: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := x - y;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Borrow: Boolean;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Borrow := False;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[0] := SubtractWithBorrow(x[0], y[0], Borrow);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[1] := SubtractWithBorrow(x[1], y[1], Borrow);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[2] := SubtractWithBorrow(x[2], y[2], Borrow);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[3] := SubtractWithBorrow(x[3], y[3], Borrow);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function SubtractWithBorrow(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Borrow: Boolean): Longint;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if Borrow then CF := 1 else CF := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; test byte ptr [ecx], -1&amp;nbsp;&amp;nbsp; // Side-effect: CF := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jz @@NoBorrow&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; stc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // CF := 1;&lt;br /&gt;
&amp;nbsp; @@NoBorrow:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := x - y - CF;&amp;nbsp; CF := NeededBorrow;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sbb eax, edx&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Borrow := CF;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; setc byte ptr [ecx]&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Você deve estar pronto para escrever uma versão de HugeSub inteiramente&lt;br /&gt;
em assembler já que é análoga à HugeAdd; tudo que você deverá fazer é&lt;br /&gt;
substituir ADD e ADC com SUB e SBB respectivamente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Número Oposto&lt;br /&gt;
=============&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Dado um número, essas implementações de HugeNeg retornam seu oposto&lt;br /&gt;
(complemento de dois):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeNeg(x: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := (Not x) + 1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := HugeAdd(HugeNot(x), IntToHuge(1));&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeNeg(x: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := 0 - x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := HugeSub(IntToHuge(0), x);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
A segunda é mais simples e rápida pois involve uma operação apenas e, já&lt;br /&gt;
que sabemos subtrair, podemos implementá-la em assembler:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeNeg(x: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := -x;&lt;br /&gt;
&amp;nbsp; // Parameters: EAX = @x; EDX = @Result&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := 0 - x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push esi&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor esi, esi&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, [eax+_0_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // x[0]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub esi, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 0 - x[0]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_0_], esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[0]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, [eax+_1_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // x[1]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sbb ecx, esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 0 - x[1] - Borrow&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_1_], ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[1]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, [eax+_2_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // x[2]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sbb esi, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 0 - x[2] - Borrow&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_2_], esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[2]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, [eax+_3_]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // x[3]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sbb ecx, esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 0 - x[3] - Borrow&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_3_], ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[3]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop esi&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Multiplicação&lt;br /&gt;
=============&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Uma forma de multiplicar números é através de um laço de adições:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeMul(x: Hugeint; y: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; SetZero(Result);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; while not HugeIsZero(y) do begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := HugeAdd(Result, x);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HugeSub(y, 1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Em termos computacionais, esse algoritmo é bastante pobre. Por exemplo,&lt;br /&gt;
se o valor de "y" for 4 milhões, o laço se repetiria 4 milhões de vezes!&lt;br /&gt;
De qualquer forma, a idéia ainda é boa se pudéssemos de alguma forma&lt;br /&gt;
acelerar o processo. Vamos então brincar um pouco com álgebra de bits:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; x * y = x * (y[3]*2^96 + y[2]*2^64 + y[1]*2^32 + y[0]*2^0)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = (x*y[3])*2^96 + (x*y[2])*2^64 + (x*y[1])*2^32 + (x*y[0])*2^0&lt;br /&gt;
&lt;br /&gt;
Agora nós reduzimos o problema de multiplicar dois inteiros gigantes&lt;br /&gt;
ao de multiplicar um inteiro gigante por um inteiro de 32-bit. Quando&lt;br /&gt;
multiplicamos o primeiro operando pelos quatro inteiros que compõem o&lt;br /&gt;
segundo operando, então deslocamos os resultados parciais por 0, 32,&lt;br /&gt;
64 e 96 bits (multiplicação por 2^0, 2^32, 2^64 e 2^96) e finalmente&lt;br /&gt;
somamos esses valores para obter o resultado final.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeMulInt(x: Hugeint; y: Longint): Hugeint; forward;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeMul(x: Hugeint; y: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := HugeShl(HugeMulInt(x, y[3]), 96)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + HugeShl(HugeMulInt(x, y[2]), 64)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + HugeShl(HugeMulInt(x, y[1]), 32)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HugeMulInt(x, y[0]);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Essa é a exata forma que multiplicamos números decimais quando usamos&lt;br /&gt;
papel, exceto que aqui a base é 2^32 ao invés de dez. Vejamos como&lt;br /&gt;
multiplicar um inteiro gigante por um inteiro:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function MultiplyWithCarry(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Carry: Longint): Longint; forward;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeMulInt(x: Hugeint; y: Longint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := x * y;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Carry: Longint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Carry := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[0] := MultiplyWithCarry(x[0], y, Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[1] := MultiplyWithCarry(x[1], y, Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[2] := MultiplyWithCarry(x[2], y, Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[3] := MultiplyWithCarry(x[3], y, Carry);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function MultiplyWithCarry(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Carry: Longint): integer;&lt;br /&gt;
&amp;nbsp; // Result := LoDWord(x * y + Carry);&lt;br /&gt;
&amp;nbsp; // Carry&amp;nbsp; := HiDWord(x * y + Carry);&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX:EAX := EAX * EDX;&amp;nbsp; // x * y&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mul edx&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Inc(EDX:EAX, Carry);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, [ecx]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; adc edx, 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Carry := EDX;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // High order 32 bits of the result&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx], edx;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
MultiplyWithCarry é muito semelhante a AddWithCarry mas realiza uma&lt;br /&gt;
multiplicação ao invés de uma adição, e gera um excesso de 32-bit ao&lt;br /&gt;
invés de um bit apenas (a multiplicação de dois valores de 32-bit gera&lt;br /&gt;
um valor de 64-bit enquanto sua soma gera um valor de 33-bit).&lt;br /&gt;
&lt;br /&gt;
MultiplyWithCarry primeiramente realiza a multiplicação sem sinal de&lt;br /&gt;
"x" (EAX) por "y" (EDX), usando o opcode MUL. O resultado de 64-bit&lt;br /&gt;
é um inteiro sem sinal contido em EDX:EAX, ao qual a função soma o&lt;br /&gt;
valor do parâmetro Carry. A função retorna os 32 bits mais baixos do&lt;br /&gt;
resultado final (localizado em EAX) e os 32 bits mais altos (EDX)&lt;br /&gt;
constituem o excesso para a próxima multiplicação, que é armazenado&lt;br /&gt;
no parâmetro Carry (passado por referência).&lt;br /&gt;
&lt;br /&gt;
Uma implementação em assembler de HugeMul e HugeMulInt encontra-se no&lt;br /&gt;
código em anexo. Por razões de simplificação, nos exemplos acima, as&lt;br /&gt;
funções consideram que os números não possuem sinais, mas o código&lt;br /&gt;
anexo considera os sinais. O código de HugeMul também não chama&lt;br /&gt;
HugeMulInt ou HugeShl e está bastante otimizado.&lt;br /&gt;
&lt;br /&gt;
Ao invés de considerar um inteiro gigante como quatro inteiros de&lt;br /&gt;
32-bit, podemos considerá-lo como 128 inteiros de 1-bit multiplicados&lt;br /&gt;
por 128 potências de 2:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; bit127 * 2^127 + bit126 * 2^126 + ... + bit1 * 2^1 + bit0 * 2^0&lt;br /&gt;
&lt;br /&gt;
Como cada bit só pode ser 0 ou 1, o algoritmo acima pode ser muito&lt;br /&gt;
simplificado:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeMul(x: Hugeint; y: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := x * y;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; i: Longint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; SetZero(Result);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; for i := 0 to 127 do&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if BitTest(y, i) then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := HugeAdd(Result, HugeShl(x, i));&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
A idéia é somar diferentes potências de 2 de "x", dependendo essas&lt;br /&gt;
potências nos bits de "y". Por exemplo, se "y" for 20, os bits 5 e&lt;br /&gt;
3 estariam ligados (20 em decimal é 10100 em binário), de modo que&lt;br /&gt;
apenas duas adições são realizadas e o resultado é HugeShl(x, 3)&lt;br /&gt;
mais HugeShl(x, 5).&lt;br /&gt;
&lt;br /&gt;
Esse algoritmo pode ser codificado de forma bastante eficiente em&lt;br /&gt;
assembler mas o primeiro algoritmo será ainda mais rápido. A razão de&lt;br /&gt;
mostrá-lo é que facilitará o entendimento do algoritmo que usaremos&lt;br /&gt;
para divisões.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Divisão&lt;br /&gt;
=======&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Vamos primeiro ver o caso da divisão de um Hugeint por um inteiro de&lt;br /&gt;
32-bit, que deve ser fácil de entender:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function DivideWithRemainder(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Remainder: Longint): Longint; forward;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeDivInt(x: Hugeint; y: Longint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := x div y;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Remainder: Longint;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Remainder := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[0] := DivideWithRemainder(x[3], y, Remainder);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[1] := DivideWithRemainder(x[2], y, Remainder);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[2] := DivideWithRemainder(x[1], y, Remainder);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[3] := DivideWithRemainder(x[0], y, Remainder);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, Remainder&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function DivideWithRemainder(x: Longint; y: Longint;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var Remainder: Longint): Longint;&lt;br /&gt;
&amp;nbsp; // Result&amp;nbsp;&amp;nbsp;&amp;nbsp; := Remainder:x div y;&lt;br /&gt;
&amp;nbsp; // Remainder := Remainder:x mod y;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push esi&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // y&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, [ecx]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Remainder&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EDX:EAX div ESI;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := EDX:EAX mod ESI;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; div esi&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Remainder := EDX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx], edx;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop esi&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
HugeDivInt deixa o resto da divisão em EDX, de modo que possa ser usado&lt;br /&gt;
em uma função que retorne o resto da divisão:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeModInt(dividend: Hugeint; divisor: Longint): Longint;&lt;br /&gt;
&amp;nbsp; // Result := dividend mod divisor;&lt;br /&gt;
&amp;nbsp; // Parameters: EAX = @dividend; EDX = @divisor;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub esp, TYPE(Hugeint) // Abrir espaço na pilha para um Hugeint&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, esp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // com o resultado da divisão&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call HugeDivInt&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Realizar a divisão&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add esp, TYPE(Hugeint) // Restaurar o ponteiro da pilha&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := Remainder;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // o resto foi deixado em EDX&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Para o caso de dois inteiros gigantes, temos que pensar no algoritmo que&lt;br /&gt;
usaríamos para dividir um número de quatro dígitos decimais no papel.&lt;br /&gt;
Mas esse procedimento é complexo e lento demais pois envolve além das&lt;br /&gt;
divisões, multiplicações, subtrações, antecipação de etapas, etc. Há&lt;br /&gt;
alternativa possível para o algoritmo? Sim:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeDiv(dividend: Hugeint; divisor: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := dividend div divisor;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if HugeIsZero(divisor) then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise EDivByZero.CreateRes(@sDivByZero);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; while HugeCmp(dividend, divisor) &amp;gt;= 0 do begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dividend := HugeSub(dividend, divisor);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := HugeAdd(Result, IntToHuge(1));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Claro, o algoritmo acaba sendo extremamente lento (se dividirmos&lt;br /&gt;
12 milhões por 3, o laço executará 4 milhões de vezes) mas podemos&lt;br /&gt;
acelerá-lo se subtrarimos do dividendo o divisor multiplicado por&lt;br /&gt;
diferentes potências de 2, da maior para a menor, definindo o bit&lt;br /&gt;
correspondente do resultado toda vez que efetuarmos a subtração (o&lt;br /&gt;
bit na posição da potência de 2 que foi usado). É o inverso do que&lt;br /&gt;
foi feito no caso da multiplicação acima. O processo de divisão seria&lt;br /&gt;
reduzido ao máximo de 128 subtrações.&lt;br /&gt;
&lt;br /&gt;
No exemplo a seguir, o dividendo é 20 (10100 em binário) e o divisor&lt;br /&gt;
é 3 (11 em binário):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp; 10100 - 11 * 2^2 = 10100 - 1100&amp;nbsp; = 1000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := 100&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; 1000 - 11 * 2^1 =&amp;nbsp; 1000 -&amp;nbsp; 110&amp;nbsp; = 10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := 110&lt;br /&gt;
&lt;br /&gt;
Inicialmente, 11 * 2^2 é o maior valor que é menor ou igual ao dividendo&lt;br /&gt;
então subtraímos esse valor do dividendo e definimos o bit 2 do&lt;br /&gt;
resultado pois subtraímos o divisor multiplicado por 2^2. Até o momento,&lt;br /&gt;
o resto da divisão é 8 (1000 em binário) e 11 * 2^1 é o maior valor que&lt;br /&gt;
é menor ou igual ao resto. Então subtraímos esse valor do resto e&lt;br /&gt;
definimos o bit 1 do resultado pois subtraímos o divisor multiplicado&lt;br /&gt;
por 2^1. O resto agora é 2 (10 em binátio) e como o divisor é maior que&lt;br /&gt;
esse valor, a divisão é interrompida. O resto da operação seria 2 (10 em&lt;br /&gt;
binário) e, como os bits 2 e 1 do resultado estão marcados, o resultado&lt;br /&gt;
é 110 em binário, ou 6 em notação decimal.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeDiv(dividend: Hugeint; divisor: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _r_: Hugeint;&amp;nbsp; // remainder&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _d_: Hugeint;&amp;nbsp; // divisor&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _q_: Hugeint;&amp;nbsp; // quotient&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BitPosR, BitPosD, count: integer;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _r_ := dividend;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _d_ := divisor;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; HugeSetZero(_q_);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BitPosD := HugeBitScanReverse(_d_);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if BitPosD = -1 then RaiseDivByZero;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BitPosR := HugeBitScanReverse(_r_);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; count := BitPosD - BitPosR;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if count &amp;gt; 0 then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _d_ := HugeShl(_d_, count);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; repeat&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if HugeCmp(_d_, _r_) &amp;lt;= 0 then begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _r_ := HugeSub(_r_, _d_);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HugeBitSet(_q_, count);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _d_ := HugeShr(_d_, 1);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dec(count);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; until count &amp;lt; 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := _q_;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lea edx, _r_&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
HugeBitScanReverse é a função que retorna a posição do primeiro bit não&lt;br /&gt;
zero, realizando a busca a partir do bit 127 até o bit 0. Se todos os&lt;br /&gt;
bits são zero, o resultado é -1. Usamos HugeBitScanReverse para&lt;br /&gt;
determinar a primeira potência de dois que devemos multiplicar o divisor&lt;br /&gt;
para iniciar a divisão.&lt;br /&gt;
&lt;br /&gt;
A implementação em assembler de HugeDiv no código anexo suporta inteiros&lt;br /&gt;
com sinais. É apenas uma primeira aproximação que pode ainda ser muito&lt;br /&gt;
melhorada.&lt;br /&gt;
&lt;br /&gt;
A função deixa em EDX o endereço do resto de modo que ele possa ser&lt;br /&gt;
usado por uma função que retorna o módulo da divisão:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function HugeMod(dividend: Hugeint; divisor: Hugeint): Hugeint;&lt;br /&gt;
&amp;nbsp; // Result := dividend Mod divisor;&lt;br /&gt;
&amp;nbsp; // Parameters: EAX = @dividend; EDX = @divisor; ECX = @Result&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // @Result&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call HugeDiv&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @remainder;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @Result;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call HugeMov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX^ := EDX^;&lt;br /&gt;
&amp;nbsp; end;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-49694880040601938?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LjWki0CUyQ838xSgRnN0HxJNsJw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LjWki0CUyQ838xSgRnN0HxJNsJw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LjWki0CUyQ838xSgRnN0HxJNsJw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LjWki0CUyQ838xSgRnN0HxJNsJw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/mQno6RRz-U4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/49694880040601938/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-6.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/49694880040601938?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/49694880040601938?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/mQno6RRz-U4/delphi-com-assembly-parte-6.html" title="Delphi com assembly (Parte 6)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-6.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQARn0zeCp7ImA9WhdQFEs.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-761097791438654733</id><published>2011-08-15T23:39:00.000-03:00</published><updated>2011-08-15T23:39:07.380-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-15T23:39:07.380-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 5)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;&amp;nbsp;-Aritmética Inteira de 128 bits (2)&lt;br /&gt;
==================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
No código-fonte exemplo (anexado) você encontrará a implementação de&lt;br /&gt;
algumas funções para operações com o tipo Hugeint que foi introduzido no&lt;br /&gt;
artigo passado. A proposta é exemplificar as instruções que nós vimos há&lt;br /&gt;
muito tempo com algumas novas:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; BT (Bit Test):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BT dword ptr [eax], edx&amp;nbsp;&amp;nbsp; --&amp;gt; CF = valor do EDX-ésimo bit na&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memória apontada por EAX&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; BTS (Bit Test and Set):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BTS dword ptr [eax], edx&amp;nbsp; --&amp;gt; atribui 1 para o EDX-ésimo bit na&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memória apontado por EAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF = valor anterior deste bit&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; BTR (Bit Test and Reset):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BTR dword ptr [eax], edx&amp;nbsp; --&amp;gt; atribui 0 para o EDX-ésimo bit na&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memória apontado por EAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF = valor anterior deste bit&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; BTC (Bit Test and Complement):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BTC dword ptr [eax], edx&amp;nbsp; --&amp;gt; inverte o valor do EDX-ésimo bit na&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memória apontada por EAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF = valor anterior deste bit&lt;br /&gt;
&lt;br /&gt;
Não reproduziremos as funções aqui, uma vez que você pode encontrá-los&lt;br /&gt;
no código-fonte anexo, mas mostraremos diferentes implementações da&lt;br /&gt;
função _IsNeg, simplesmente apresentando mais exemplos das instruções&lt;br /&gt;
que vimos tempos atrás:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function _IsNeg(x: Hugeint): boolean;&lt;br /&gt;
&amp;nbsp; // Resultado := x &amp;lt; 0;&lt;br /&gt;
&amp;nbsp; // Se x &amp;lt; 0 retorna True (1) senão retorna False (0)&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = @x&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [eax+_3_]&amp;nbsp; // EAX := 32 bits de alta ordem de x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; shr eax, 31&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL&amp;nbsp; := Bit de alta ordem de EAX (sign bit)&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function _IsNeg(x: Hugeint): boolean;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp dword ptr [eax+_3_], 0&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; if x[3] &amp;lt; 0 then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jl @@negative&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto @@negative&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov al, 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; Result := False;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; exit;&lt;br /&gt;
&amp;nbsp; @@negative:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // @@negative:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov al, 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; Result := True;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function _IsNeg(x: Hugeint): boolean;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // atribuir o Sign Flag e colocá-lo em AL&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [eax+_3_]&amp;nbsp; // EAX := 32 bits de alta ordem de x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; or eax, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // SF := Sign bit de EAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // alt.: add eax, 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: sub eax, 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: and eax, eax&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: and eax, -1&amp;nbsp;&amp;nbsp; // ou qq valor negativo&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: test eax, eax&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: test eax, -1&amp;nbsp; // ou qq valor negativo&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sets al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL := SF;&amp;nbsp; // Sign Flag&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // alt.: lahf; shr ax, 31&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; rol ax, 1; and al, $1&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function _IsNeg(x: Hugeint): boolean;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // atribui o Carry Flag com o Sign Bit e colocá-lo em AL&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [eax+_3_]&amp;nbsp; // EAX := 32 bits de alta ordem de x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; bt eax, 31&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // CF := Sign bit de EAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // alt.: shl/rol/rcl eax, 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; setc al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL := CF;&amp;nbsp; // Carry Flag&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // alt.: mov al, 0; rcl, 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: mov al, 0; adc al, al&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; mov al, ah; and al, $1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; ror/rcr/shr/sar ax, 1; shr al, 7&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; ror/shr/sar ax, 8; and al, $1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; rol ax, 8; and al, $1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; rcl ax, 9; and al, $1&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function _IsNeg(x: Hugeint): boolean;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // atribuir o Parity Flag e negá-lo em AL&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov al, [eax+_3_+3] // EAX := 8 bits de alta ordem de x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; or al, $7F&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // PF := Not Sign bit&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // alt.: and eax, $80000000&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; setnp al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL := Not PF;&amp;nbsp; // Not Parity Flag&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // alt.: lahf; rol/shl ax, 6 / rcl ax, 7;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xor al,-1 / not al; and al, $1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; ou: lahf; ror/shr/sar ax, 10 / rcr ax, 11;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xor al,-1 / not al; and al, $1;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Na próxima parte veremos funções para adicionar, subtrair, multiplicar e&lt;br /&gt;
dividir inteiro HugeInt.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-761097791438654733?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/t-_-YVDd2E5OZmbMDu3TzPLNUvY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t-_-YVDd2E5OZmbMDu3TzPLNUvY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/t-_-YVDd2E5OZmbMDu3TzPLNUvY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t-_-YVDd2E5OZmbMDu3TzPLNUvY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/zza0OGeih2Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/761097791438654733/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-5.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/761097791438654733?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/761097791438654733?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/zza0OGeih2Y/delphi-com-assembly-parte-5.html" title="Delphi com assembly (Parte 5)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUNSH4_eSp7ImA9WhdQFEs.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-1699226360728885410</id><published>2011-08-15T23:38:00.000-03:00</published><updated>2011-08-15T23:38:19.041-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-15T23:38:19.041-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 4)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;Aritmética Inteira de 128 bits (1)&lt;br /&gt;
&lt;br /&gt;
Introdução&lt;br /&gt;
==========&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Com 32 bits podemos representar 2^32 números diferentes, isto é,&lt;br /&gt;
4294967296 (~4 bilhões) números diferentes, tais como inteiros com sinal&lt;br /&gt;
de -2147483648 até +2147483647 ou inteiros sem sinal de 0 até 4294967295&lt;br /&gt;
(Longint e Longword respectivamente).&lt;br /&gt;
&lt;br /&gt;
Isso é suficiente para muitas finalidades como, por exemplo, guardar a&lt;br /&gt;
posição de um byte em um arquivo de 4GB. Mas às vezes precisamos&lt;br /&gt;
representar inteiros maiores e então podemos usar TLargeInteger&lt;br /&gt;
(Windows.pas) e Int64 (a partir do Delphi 4) para representar inteiros&lt;br /&gt;
de 64-bits (2^64 valores diferentes): 18446744073709551616 (~18&lt;br /&gt;
sestilhões) de valores, de -9223372036854775808 até +9223372036854775807&lt;br /&gt;
(~9 sestilhões, 17-18 dígitos).&lt;br /&gt;
&lt;br /&gt;
Essa quantidade de dígitos é muito mais do que eu preciso e não consigo&lt;br /&gt;
imaginar qualquer uso prático para mais do que isso- a não ser Bill&lt;br /&gt;
Gates que conta seu dinheiro em sestilhões! ;) Mas de tempos em tempos&lt;br /&gt;
eu vejo alguém no fórum perguntar por mais dígitos que o Int64&lt;br /&gt;
oferece...&lt;br /&gt;
&lt;br /&gt;
De qualquer maneira, se válido ou completamente inútil numa proposta&lt;br /&gt;
prática, veremos a implementação de várias procedures e functions&lt;br /&gt;
desenvolvidas para trabalhar com inteiros de 128-bits, que nos&lt;br /&gt;
servirão para mostrar exemplos de instruções básicas de assembler.&lt;br /&gt;
Este "inteiros longos", "inteiros grandes" ou "inteiros enormes" &lt;br /&gt;
podem manter 2^128 diferentes valores (38-39 dígitos).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Representação dos inteiros de 128-bits&lt;br /&gt;
======================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Eu chamo o novo tipo Hugeint mas, por exemplo, Bigint (big integer) ou&lt;br /&gt;
Int128 podem ser nomes igualmente bons. Largeint pode ser confundido com&lt;br /&gt;
o tipo da unit Windows.pas que refere-se ao inteiro de 64-bits.&lt;br /&gt;
&lt;br /&gt;
Quando precisamos representar o novo tipo, também existem várias formas&lt;br /&gt;
de fazê-lo. Eu optei pela representação mais simples- um array de 4&lt;br /&gt;
inteiros de 32 bits:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; type&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Hugeint: packed array [0..3] of longword;&lt;br /&gt;
&lt;br /&gt;
Também decidi pelo formato little-endian já que é o padrão na&lt;br /&gt;
arquitetura Intel e isto significa que o primeiro elemento do array&lt;br /&gt;
(endereço mais baixo) guardará os 32 bits de ordem mais baixa (menos&lt;br /&gt;
significativos) e o último elemento do array (endereço mais alto)&lt;br /&gt;
guardará os 32 bits de mais alta ordem (mais significativos).&lt;br /&gt;
&lt;br /&gt;
Abaixo é a forma que os números 5 e 5000000000 ($12A05F200) serão&lt;br /&gt;
representados:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +---- 32 bits de baixa ordem&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; v&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp; $00000005&amp;nbsp; |&amp;nbsp; $00000000&amp;nbsp; |&amp;nbsp; $00000000&amp;nbsp; |&amp;nbsp; $00000000&amp;nbsp; | = 5&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp; $2A05F200&amp;nbsp; |&amp;nbsp; $00000001&amp;nbsp; |&amp;nbsp; $00000000&amp;nbsp; |&amp;nbsp; $00000000&amp;nbsp; | = 5000000000&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&amp;nbsp;&amp;nbsp; $12A05F200&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ^&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 32 bits de alta ordem ----+&lt;br /&gt;
&lt;br /&gt;
Os próprios inteiros são armazenados no formato little-endian (primeiro&lt;br /&gt;
o byte de mais baixa ordem). Se você verificar a representação em bytes&lt;br /&gt;
de um número na memória, ela se pareceria com isso (valores em bytes&lt;br /&gt;
representados na notação hexadecimal):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $00000005&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&lt;br /&gt;
&amp;nbsp; | 05 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | = 5&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&lt;br /&gt;
&amp;nbsp; | 00 F2 05 2A | 01 00 00 00 | 00 00 00 00 | 00 00 00 00 | = 5000000000&lt;br /&gt;
&amp;nbsp; +-------------+-------------+-------------+-------------+&amp;nbsp;&amp;nbsp; $12A05F200&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $2A05F200&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $00000001&lt;br /&gt;
&lt;br /&gt;
Entretanto, para quase todas as operações, podemos abstrair a ordem do&lt;br /&gt;
byte e considerar que os inteiros de 32-bits são unidades atômicas,&lt;br /&gt;
desde que a ordem do byte seja mantida transparentemente.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
Algumas instruções úteis&lt;br /&gt;
========================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Antes de começarmos, vejamos algumas instruções úteis que usaremos neste&lt;br /&gt;
artigo (principalmente na continuação desta parte); antes, porém, é&lt;br /&gt;
preciso enfatizar que a proposta deste artigo não é ensiná-lo assembler.&lt;br /&gt;
Tudo que eu posso fazer neste espaço limitado é simplesmente mostrar&lt;br /&gt;
exemplos de algumas instruções. Como material de referência, recomendo&lt;br /&gt;
estes links:&lt;br /&gt;
&lt;br /&gt;
* Intel 80386 Reference Programmer's Manual&lt;br /&gt;
&amp;nbsp; Um versão HTML deste manual da Intel. O pseudocódigo ajuda a entender&lt;br /&gt;
&amp;nbsp; as instruções e seus efeitos sobre os flags. Excelente.&lt;br /&gt;
&amp;nbsp; http://people.freebsd.org/~jhb/386htm/toc.htm&lt;br /&gt;
&amp;nbsp; Existem alguns links quebrados, mas as páginas estão lá. Tente&lt;br /&gt;
&amp;nbsp; encontrá-los no diretório: http://people.freebsd.org/~jhb/386htm/&lt;br /&gt;
&lt;br /&gt;
* iAPx86 - Norton Guide&lt;br /&gt;
&amp;nbsp; Não é tão didático quanto o documento acima, mas contém todas as&lt;br /&gt;
&amp;nbsp; instruções do 8086 do Pentium e Pentium Pro, com informações de &lt;br /&gt;
&amp;nbsp; tamanho e tempo não inclusas no link acima.&lt;br /&gt;
&amp;nbsp; http://www.clipx.net/ng/iapx86/index.php&lt;br /&gt;
&lt;br /&gt;
* The IA-32 Intel Architecture Software Developer's Manual, Volume 2:&lt;br /&gt;
&amp;nbsp; Instruction Set Reference&lt;br /&gt;
&amp;nbsp; Manual em PDF descrevendo as instruções dos processadores IA-32&lt;br /&gt;
&amp;nbsp; (Pentium, Pentium Pro, Pentium II, Pentium III, Pentium 4 e Xeon).&lt;br /&gt;
&amp;nbsp; Inclui pseudocódigo que explica as instruções e como elas afetam os&lt;br /&gt;
&amp;nbsp; flags dos registradores.&lt;br /&gt;
&amp;nbsp; http://www.intel.com/design/pentium4/manuals/245471.htm&lt;br /&gt;
&lt;br /&gt;
* Otimização&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; - How to optimize for the Pentium family of microprocessors&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Excelente guia de otimização escrito por Agner Fog&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; http://fatphil.org/x86/pentopt/index.html&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; - Optimizations for Intel's 32-Bit Processors&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Outro excelente guia de otimização.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; http://x86.ddj.com/ftp/manuals/686/optimgd.pdf&lt;br /&gt;
&lt;br /&gt;
OK, agora vamos ver as instruções.&lt;br /&gt;
&lt;br /&gt;
Referência:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Z/ZF: Flag Zero &lt;br /&gt;
&amp;nbsp; S/SF: Flag de Sinal&lt;br /&gt;
&amp;nbsp; C/CF: Flag de Transporte (Carry)&lt;br /&gt;
&amp;nbsp; P/PF: Flag de Paridade&lt;br /&gt;
&amp;nbsp; A/AF: Flag Auxiliar&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; s: bit de sinal (bit de ordem mais alta)&lt;br /&gt;
&amp;nbsp; o: bit ímpar (bit de ordem mais baixa)&lt;br /&gt;
&amp;nbsp; x: valor do bit&lt;br /&gt;
&amp;nbsp; 0: o valor 0&lt;br /&gt;
&amp;nbsp; 1: o valor 1&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; r: bit invertido em relação ao valor anterior&lt;br /&gt;
&amp;nbsp; u: bit não alterado desde o valor anterior&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; XX: valor desconhecido&lt;br /&gt;
&lt;br /&gt;
Nos exemplos presumimos que o valor de AL antes de cada operação é&lt;br /&gt;
sxxxxxxo (bit de sinal, 6 bits desconhecidos e bit ímpar).&lt;br /&gt;
&lt;br /&gt;
Aqui temos algumas instruções para começar:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; SHL al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := xxxxxxo0&amp;nbsp; CF := s&amp;nbsp;&amp;nbsp; Deslocamento à esquerda&lt;br /&gt;
&amp;nbsp; SAL al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := xxxxxxo0&amp;nbsp; CF := s&amp;nbsp;&amp;nbsp; Mesmo que SHL&lt;br /&gt;
&amp;nbsp; SHR al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := 0sxxxxxx&amp;nbsp; CF := o&amp;nbsp;&amp;nbsp; Deslocamento à direita&lt;br /&gt;
&amp;nbsp; SAR al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := ssxxxxxx&amp;nbsp; CF := o&amp;nbsp;&amp;nbsp; Deslocamento aritmético à&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; direita&lt;br /&gt;
&amp;nbsp; SAR al,7&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := ssssssss&amp;nbsp; CF := x&amp;nbsp;&amp;nbsp; Reprodução do bit de sinal&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; ROL al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := xxxxxxos&amp;nbsp; CF := s&amp;nbsp;&amp;nbsp; Rotação à esquerda&lt;br /&gt;
&amp;nbsp; ROR al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := osxxxxxx&amp;nbsp; CF := o&amp;nbsp;&amp;nbsp; Rotação à direita&lt;br /&gt;
&amp;nbsp; RCL al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := xxxxxxoC&amp;nbsp; CF := s&amp;nbsp;&amp;nbsp; Rotação completa com transporte&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; à esquerda&lt;br /&gt;
&amp;nbsp; RCR al,1&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := Csxxxxxx&amp;nbsp; CF := o&amp;nbsp;&amp;nbsp; Rotação completa com transporte&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; à direita&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; AND al,al&amp;nbsp;&amp;nbsp; AL := uuuuuuuu&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; Define flags (veja abaixo)&lt;br /&gt;
&amp;nbsp; AND al,-1&amp;nbsp;&amp;nbsp; AL := uuuuuuuu&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; -1 = $FF = 1111111&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define flags (veja abaixo)&lt;br /&gt;
&amp;nbsp; AND al,$01&amp;nbsp; AL := 0000000u&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $01 = 00000001&lt;br /&gt;
&amp;nbsp; AND al,$80&amp;nbsp; AL := u0000000&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $80 = 10000000&lt;br /&gt;
&amp;nbsp; AND al,$5A&amp;nbsp; AL := 0u0uu0u0&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $5A = 01011010&lt;br /&gt;
&amp;nbsp; AND al,0&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := 00000000&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; XOR AL,AL ou MOV AL,0 são&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; melhores&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; TEST AL,XX&amp;nbsp; AL := uuuuuuuu&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TEST é como AND mas o resultado não é armazenado no&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; destino. O resultado é usado para definir as flags (veja&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; abaixo)&lt;br /&gt;
&amp;nbsp; TEST AL,-1&amp;nbsp; É melhor que AND AL,-1 e OR AL,AL porque não escreve em&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AL, o que permite certas otimizações em alguns casos.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; OR&amp;nbsp; al,al&amp;nbsp;&amp;nbsp; AL := uuuuuuuu&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; Define as flags (veja abaixo)&lt;br /&gt;
&amp;nbsp; OR&amp;nbsp; al,$01&amp;nbsp; AL := uuuuuuu1&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $01 = 00000001&lt;br /&gt;
&amp;nbsp; OR&amp;nbsp; al,$80&amp;nbsp; AL := 1uuuuuuu&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $80 = 10000000&lt;br /&gt;
&amp;nbsp; OR&amp;nbsp; al,$5A&amp;nbsp; AL := u1u11u1u&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $5A = 01011010&lt;br /&gt;
&amp;nbsp; OR&amp;nbsp; al,-1&amp;nbsp;&amp;nbsp; AL := 11111111&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; Mesmo que MOV AL,1&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; XOR al,al&amp;nbsp;&amp;nbsp; AL := 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; Utilize MOV AL,0 para preservar&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; as flags&lt;br /&gt;
&amp;nbsp; XOR al,$5A&amp;nbsp; AL := ururruru&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; $5A = 01011010&lt;br /&gt;
&amp;nbsp; XOR al,-1&amp;nbsp;&amp;nbsp; AL := rrrrrrrr&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp; Mesmo que NOT AL&lt;br /&gt;
&lt;br /&gt;
Exceto pelas instruções de rotação (ROL, RCL, ROR e RCR), todas acima&lt;br /&gt;
definem SF, ZF e PF baseados no resultado das operações:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; SF = valor do bit de mais alta ordem do resultado&lt;br /&gt;
&amp;nbsp; ZF = 1 ("definido") se o resultado for zero, 0 ("limpo") nos demais&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; casos&lt;br /&gt;
&amp;nbsp; PF = 1 ("definido") se o o byte de mais baixa ordem do resultado&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contém um número par de bits 1, senão 0 ("limpo")&lt;br /&gt;
&lt;br /&gt;
Veja mais algumas instruções:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; STC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define o flag de Transporte&lt;br /&gt;
&amp;nbsp; CLC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Limpa o flag de Transporte&lt;br /&gt;
&amp;nbsp; CMC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Complementa o flag de Transporte&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; LAHF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AH := SZxAxPxC&lt;br /&gt;
&amp;nbsp; SAHF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Presumindo que AH é SZxAxPxC:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ZF := S; ZF := Z; AF := A; PF := P; CF := C&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; SETc&amp;nbsp; AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := CF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se carry&lt;br /&gt;
&amp;nbsp; SETs&amp;nbsp; AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := SF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se sign&lt;br /&gt;
&amp;nbsp; SETz&amp;nbsp; AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := ZF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se zero&lt;br /&gt;
&amp;nbsp; SETe&amp;nbsp; AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := ZF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se equal (sinônimo de SETZ)&lt;br /&gt;
&amp;nbsp; SETp&amp;nbsp; AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := PF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se paridade&lt;br /&gt;
&amp;nbsp; SETpe AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := PF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se a paridade é par&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (sinônimo de SETP)&lt;br /&gt;
&amp;nbsp; SETo&amp;nbsp; AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := OF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se overflow&lt;br /&gt;
&amp;nbsp; SETnc AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT CF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se não carry&lt;br /&gt;
&amp;nbsp; SETns AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT SF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se não sign&lt;br /&gt;
&amp;nbsp; SETnz AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT ZF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se não zero&lt;br /&gt;
&amp;nbsp; SETne AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT ZF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se não equal (sinônimo de SETNZ)&lt;br /&gt;
&amp;nbsp; SETnp AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT PF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se não paridade&lt;br /&gt;
&amp;nbsp; SETpo AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT PF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se a paridade é ímpar&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (sinônimo de SETNP)&lt;br /&gt;
&amp;nbsp; SETno AL&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := NOT OF&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Define se não overflow&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; SETa (ou SETNbe), SETae (ou SETnb), SETb (ou SETnae), SETbe (SETna),&lt;br /&gt;
&amp;nbsp; SETg (ou SETNle), SETge (ou SETnl), SETl (ou SETnge) e SETle (SETng) &lt;br /&gt;
&amp;nbsp; definem o byte de destino para 1 ou 0 dependendo da condição&lt;br /&gt;
&amp;nbsp; específica ser satisfeita ou não.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; ADD AL,XX&amp;nbsp;&amp;nbsp; AL := AL+XX&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := 1 se a operação gera transporte;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 outros casos&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; SUB AL,XX&amp;nbsp;&amp;nbsp; AL := AL-XX&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := 1 se a operação precisa de um&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; empréstimo; 0 outros casos&lt;br /&gt;
&amp;nbsp; SUB AL,0&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := uuuuuuuu&amp;nbsp; Define os flags baseados no AL&lt;br /&gt;
&amp;nbsp; SUB AL,AL&amp;nbsp;&amp;nbsp; AL := 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Mesmo que XOR AL,AL ou MOV AL,0&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; CMP AL,XX&amp;nbsp;&amp;nbsp; CMP é como SUB mas o resultado não é armazenado no&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; destino. A operação simplesmente define os flags.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; ADC AL,XX&amp;nbsp;&amp;nbsp; AL := AL+XX+C&amp;nbsp;&amp;nbsp; CF := 1 se a operação gera um transporte;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 outros casos&lt;br /&gt;
&amp;nbsp; SBB AL,XX&amp;nbsp;&amp;nbsp; AL := AL-C-XX&amp;nbsp;&amp;nbsp; CF := 1 se a operação necessitade um&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; empréstimo; 0 outros casos&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; NEG AL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := -AL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CF := 1 se previamente AL &amp;lt;&amp;gt; 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NOT AL; INC AL é o mesmo&lt;br /&gt;
&amp;nbsp; NOT AL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AL := rrrrrrrr&amp;nbsp; CF := u&amp;nbsp;&amp;nbsp;&amp;nbsp; Mesmo que XOR AL,-1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Funções de Conversão&lt;br /&gt;
====================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Estas funções nos ajudarão a entender a representação dos inteiros&lt;br /&gt;
128-bits.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Longword para Hugeint&lt;br /&gt;
---------------------&lt;br /&gt;
&lt;br /&gt;
Vamos começar convertendo de Longword para HugeInt. Os 32 bits de mais&lt;br /&gt;
baixa ordem do resultado serão os 32 bits do parâmetro e os 96 bits de&lt;br /&gt;
mais alta ordem serão zerados.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function UToHugeint(const x: Longword): Hugeint; overload;&lt;br /&gt;
&amp;nbsp; // Result := Hugeint(x);&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = x; EDX = @Result;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor ecx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_0_], eax&amp;nbsp;&amp;nbsp; // Result[0] := x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_1_], ecx&amp;nbsp;&amp;nbsp; // Result[1] := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_2_], ecx&amp;nbsp;&amp;nbsp; // Result[2] := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_3_], ecx&amp;nbsp;&amp;nbsp; // Result[3] := 0;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Comentários:&lt;br /&gt;
&lt;br /&gt;
* "_0_", "_1_", "_2_", e "_3_"? O que são?&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; São constantes que representam os deslocamentos dos quatro elementos&lt;br /&gt;
&amp;nbsp; do vetor, permitindo-nos escrever um código mais limpo.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _0_ = 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _1_ = 4;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _2_ = 8;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _3_ = 12;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
Longint para Hugeint&lt;br /&gt;
--------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Os 32 bits inferiores do resultado serão os 32 bits do parâmetro. Se o&lt;br /&gt;
número for positivo ou zero, então os 96 bits superiores serão 0, senão&lt;br /&gt;
os 96 bits superiores serão 1.&lt;br /&gt;
&lt;br /&gt;
Isso nos força a fazer uma comparação ou teste do sinal e então executar&lt;br /&gt;
um jump condicional baseado no resultado:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ToHugeint(const x: Longint): Hugeint; overload;&lt;br /&gt;
&amp;nbsp; // Result := Hugeint(x);&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = x; EDX = @Result;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; or&amp;nbsp; eax, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EAX or EAX; // EAX não é alterado&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Efeito colateral:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SF (Flag de Sinal) := EAX &amp;lt; 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jns @@not_negative&amp;nbsp; // if not SF then goto @@not_negative;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; dec ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := ECX - 1; // 0 - 1 = -1 = $FFFFFFFF&lt;br /&gt;
&amp;nbsp; @@not_negative:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_0_], eax&amp;nbsp; // Result[0] := x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_1_], ecx&amp;nbsp; // Result[1] := ECX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_2_], ecx&amp;nbsp; // Result[2] := ECX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_3_], ecx&amp;nbsp; // Result[3] := ECX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Comentários:&lt;br /&gt;
&lt;br /&gt;
* Observe o uso do "MOV ECX, 0" no lugar de "XOR ECX, ECX" para evitar&lt;br /&gt;
&amp;nbsp; alterar o estado do Flag de Sinal (SF) definido na instrução anterior&lt;br /&gt;
&amp;nbsp; (OR) e então usado no jump condicional que aparece na instrução&lt;br /&gt;
&amp;nbsp; seguinte (JNS). É claro que era desnecessário trocar a ordem das&lt;br /&gt;
&amp;nbsp; operações para isto.&lt;br /&gt;
&lt;br /&gt;
* Em vez de:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; or eax, eax&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jns @@not_negative&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; os pares de instruções abaixo realizariam o mesmo: &lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; * and eax, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX mantém o valor, mas SF recebe o sinal&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jns @@not_negative&amp;nbsp;&amp;nbsp; // se SF = 0 então goto @@not_negative&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; * test eax, $80000000&amp;nbsp; // somente zero se o bit de sinal (bit 31) é 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jz @@not_negative&amp;nbsp;&amp;nbsp;&amp;nbsp; // se ZF então goto @@not_negative&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; * test eax, $87654321&amp;nbsp; // qualquer valor com o bit 31 definido&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jns @@not_negative&amp;nbsp;&amp;nbsp; // se SF = 0 então goto @@not_negative&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; * cmp eax, 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // compara eax com 0&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jge @@not_negative&amp;nbsp;&amp;nbsp; // se maior ou igual então goto @@not_negative&lt;br /&gt;
&lt;br /&gt;
* Observe o uso de "DEC ECX" para alterar o valor de ECX de $00000000&lt;br /&gt;
&amp;nbsp; para $FFFFFFFF (decrementando o valor do registro). "NOT ECX" faz a&lt;br /&gt;
&amp;nbsp; mesma coisa invertendo os bits, na mesma velocidade, e com o mesmo&lt;br /&gt;
&amp;nbsp; número de bytes para codificar a instrução, mas não é uma instrução&lt;br /&gt;
&amp;nbsp; par como o DEC. Por esta razão NOT é normalmente evitado e substituido&lt;br /&gt;
&amp;nbsp; por: &lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; - Se você sabe de antemão que o valor é zero, utilize DEC Dest&lt;br /&gt;
&amp;nbsp; - Se você sabe de antemão que o valor é 1, use INC Dest&lt;br /&gt;
&amp;nbsp; - Se você não conhece o valor, use XOR Dest, -1&lt;br /&gt;
&lt;br /&gt;
* Também preste atenção na ordem das instruções para jamais utilizar um&lt;br /&gt;
&amp;nbsp; registro que foi definido por um instrução imediatamente anterior.&lt;br /&gt;
&amp;nbsp; Essa é uma das condições para que ocorra o pareamento. Você encontrará&lt;br /&gt;
&amp;nbsp; mais informações sobre instruções de pareamento nos documentos sobre&lt;br /&gt;
&amp;nbsp; otimização recomendados anteriormente.&lt;br /&gt;
&lt;br /&gt;
Podemos simplificar a função obrigando a instrução CDQ que estende o&lt;br /&gt;
sinal de EAX para EDX. Veja o funcionamento (simplificado) de CDQ:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; if EAX &amp;gt;= 0 then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; EDX := $0&lt;br /&gt;
&amp;nbsp; else&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; EDX := $FFFFFFFF;&lt;br /&gt;
&lt;br /&gt;
Aqui é uma pequena e simples implementação usando CDQ:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ToHugeint(const x: Longint): Hugeint; overload;&lt;br /&gt;
&amp;nbsp; // Result := Hugeint(x);&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = x; EDX = @Result;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := @Result;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cdq&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := IIF(x&amp;gt;=0, 0, $FFFFFFFF);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_0_], eax&amp;nbsp; // Result[0] := x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_1_], edx&amp;nbsp; // Result[1] := EDX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_2_], edx&amp;nbsp; // Result[2] := EDX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx+_3_], edx&amp;nbsp; // Result[3] := EDX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
CDQ é usualmente substituído usando MOV e SAR, que oferecem a vantagem&lt;br /&gt;
de que a origem não precisa ser EAX e o destino não precisa ser EDX (mas&lt;br /&gt;
são instruções pareadas). Vejamos um exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ToHugeint(const x: Longint): Hugeint; overload;&lt;br /&gt;
&amp;nbsp; // Result := Hugeint(x);&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = x; EDX = @Result;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sar ecx, 31&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := IIF(x&amp;gt;=0, 0, $FFFFFFFF);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_0_], eax&amp;nbsp; // Result[0] := x;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_1_], ecx&amp;nbsp; // Result[1] := EDX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_2_], ecx&amp;nbsp; // Result[2] := EDX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+_3_], ecx&amp;nbsp; // Result[3] := EDX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
Hugeint para Longint&lt;br /&gt;
--------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Um Hugeint pode ser convertido para Longint simplesmente pegando os&lt;br /&gt;
32 bits de mais baixa ordem. Os 96 bits altos do Hugeint podem ser todos&lt;br /&gt;
definidos para 0 ou 1 igualando o bit de sinal para que o resultado (bit&lt;br /&gt;
31) do Hugeint esteja dentro dos limites do Longint, mas a função não&lt;br /&gt;
checa isto e executa a conversão cegamente (da mesma forma que um&lt;br /&gt;
Longint é convertido para um Shortint, por exemplo).&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ToLongint(const x: Hugeint): Longint; overload;&lt;br /&gt;
&amp;nbsp; // Result := Longint(x);&lt;br /&gt;
&amp;nbsp; // Nenhuma exceção é gerada se o valor não estiver dentro dos limites&lt;br /&gt;
&amp;nbsp; // (os 96 bits de mais alta ordem são descartados).&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = @x;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [eax+_0_]&amp;nbsp; // Result := x[0];&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Int64 para Hugeint&lt;br /&gt;
------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Parâmetros Int64 são passados para a pilha; assim, funções com&lt;br /&gt;
parâmetros Int64 automaticamente criam um quadro de pilha (stack frame).&lt;br /&gt;
Os 64 bits mais baixos do resultado serão os 64 bits do parâmetro&lt;br /&gt;
enquanto os 64 bits mais altos serão obtidos a partir do bit de sinal&lt;br /&gt;
do inteiro (32 bits) de mais alta ordem do Int64.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; {$IFDEF DELPHI4}&lt;br /&gt;
&amp;nbsp; function ToHugeint(const x: Int64): Hugeint; overload;&lt;br /&gt;
&amp;nbsp; // Result := Hugeint(x);&lt;br /&gt;
&amp;nbsp; // Parâmetros: x na pilha; EAX = @Result;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, dword[x+_0_]&amp;nbsp; // EDX := x[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, dword[x+_1_]&amp;nbsp; // ECX := x[1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [eax+_0_], edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[0] := x[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [eax+_1_], ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[1] := x[1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sar ecx, 31&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := IIF(x[1]&amp;gt;=0, 0, $FFFFFFFF);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [eax+_2_], ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[2] := ECX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [eax+_3_], ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result[3] := ECX; // 0 or $FFFFFFFF&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; {$ENDIF}&lt;br /&gt;
&lt;br /&gt;
Valores Int64 são armazenados no formato little-endian; assim, o&lt;br /&gt;
inteiro inferior é o primeiro, com um deslocamento 0 do endereço base&lt;br /&gt;
da variável e o inteiro superior é o segundo, com um deslocamento 4 do&lt;br /&gt;
endereço base da variável. Nesse caso, o endereço base da variável é&lt;br /&gt;
EBP+8 (veja o primeiro capítulo desta série de artigos) e, assim, o&lt;br /&gt;
primeiro elemento está em EBP+8 (EBP+8+0) e o segundo elemento está em&lt;br /&gt;
EBP+12 (EBP+8+4). Eu poderia usar EBP+8 e EBP+12 para endereçar estes&lt;br /&gt;
elementos mas "x+_0_" e "x+_1_" referem-se aos endereços de forma mais&lt;br /&gt;
transparente. O especificador de tamanho (DWORD) é já que o assembler&lt;br /&gt;
recebe "x+_0_" e "x+_1_" como ponteiros para dados de 64 bits ("x" é&lt;br /&gt;
considerado um ponteiro de dados de 64-bits) e não permite mover o&lt;br /&gt;
valor referenciado para um registrador de 32-bits.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Hugeint para Int64&lt;br /&gt;
------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Um Hugeint pode ser convertido para um Int64 simplesmente pegando os 64&lt;br /&gt;
bits inferiores. Os 64 bits superiores do HugeInt podem ser definidos&lt;br /&gt;
como 0 ou 1 para igualar o bit de sinal para que o resultado (bit 32)&lt;br /&gt;
do valor Hugeint fique dentro dos limites de um Int64, mas a função não&lt;br /&gt;
checa isto e executa a conversão cegamente:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; {$IFDEF DELPHI4}&lt;br /&gt;
&amp;nbsp; function ToInt64(const x: Hugeint): Int64; overload;&lt;br /&gt;
&amp;nbsp; // Result := Int64(x)&lt;br /&gt;
&amp;nbsp; // Nenhuma exceção é gerada se o valor não estiver dentro dos limites&lt;br /&gt;
&amp;nbsp; // (os 64 bits de mais alta ordem são descartados).&lt;br /&gt;
&amp;nbsp; // Parâmetros: EAX = @x;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, [eax+_1_]&amp;nbsp; // EDX := x[1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [eax+_0_]&amp;nbsp; // EAX := x[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result = EDX:EAX = x[1]:x[0]&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; {$ENDIF}&lt;br /&gt;
&lt;br /&gt;
Commentários:&lt;br /&gt;
&lt;br /&gt;
* Int64 retorna valores colocados em EDX (32 bits de alta ordem) e &lt;br /&gt;
&amp;nbsp; EAX (32 bits de baixa ordem).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por enquanto é isso. Nas próximas edições veremos funções que executam &lt;br /&gt;
funções lógicas e matemáticas com inteiros gigantes.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-1699226360728885410?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2IW-VPUBvLSwVmhuYHaiSwBMCCQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2IW-VPUBvLSwVmhuYHaiSwBMCCQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2IW-VPUBvLSwVmhuYHaiSwBMCCQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2IW-VPUBvLSwVmhuYHaiSwBMCCQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/sSL_sy8WJuQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/1699226360728885410/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-4.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/1699226360728885410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/1699226360728885410?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/sSL_sy8WJuQ/delphi-com-assembly-parte-4.html" title="Delphi com assembly (Parte 4)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-4.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYMSXo9fSp7ImA9WhdQFEw.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-8359493754189208834</id><published>2011-08-15T11:23:00.000-03:00</published><updated>2011-08-15T11:23:08.465-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-15T11:23:08.465-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 3)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;Objetos são registros&lt;br /&gt;
=====================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Do ponto de vista do assembler, um objeto é como um registro, cujos&lt;br /&gt;
campos são seus próprios campos mais os campos de seus ancestrais,&lt;br /&gt;
mais um ponteiro à VMT (Virtual Methods Table - Tabela de Métodos&lt;br /&gt;
Virtuais). Vejamos isto através de um exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; type&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TClass1 = class&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FieldA: integer;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FieldB: string;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TClass2 = class(TClass1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FieldC: integer;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
No exemplo, TClass2 é de certo modo como um registro com quatro&lt;br /&gt;
campos:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; TClass2 = record&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; VMT: pointer;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // campo invisível, sempre o primeiro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; FieldA: integer;&amp;nbsp;&amp;nbsp;&amp;nbsp; // herdado de TClass1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; FieldB: string;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // herdado de TClass1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; FieldC: integer;&amp;nbsp;&amp;nbsp;&amp;nbsp; // declarado em TClass2&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Variáveis objeto são ponteiros&lt;br /&gt;
==============================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Uma variável objeto é somente um ponteiro para um objeto, ou seja, um&lt;br /&gt;
ponteiro para um registro.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a, b: TClass2;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a := TClass2.Create;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; b := a;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // somente uma declaração de ponteiro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a.Free;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Um construtor aloca memória para uma instância (objeto) de sua classe,&lt;br /&gt;
inicializa-a e retorna um ponteiro para a memória alocada. Assim,&lt;br /&gt;
após a chamada a TClass.Create a variável "a" aponta para o registro&lt;br /&gt;
(o objeto):&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; +---+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&amp;nbsp; | a | ----------&amp;gt; |&amp;nbsp;&amp;nbsp; VMT&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +---+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | FieldA |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | FieldB |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | FieldC |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&lt;br /&gt;
A declaração "b := a" não cria um novo objeto, cópia do primeiro,&lt;br /&gt;
mas realmente faz com que ambas as variáveis apontem para o mesmo&lt;br /&gt;
objeto:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; +---+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +---+&lt;br /&gt;
&amp;nbsp; | a | ----------&amp;gt; |&amp;nbsp;&amp;nbsp; VMT&amp;nbsp; | &amp;lt;---------- | b |&lt;br /&gt;
&amp;nbsp; +---+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +---+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | FieldA |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | FieldB |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | FieldC |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +--------+&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Métodos assembler&lt;br /&gt;
=================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Os métodos recebem um primeiro parâmetro invisível, chamado Self, que&lt;br /&gt;
é um ponteiro para o objeto sobre o qual o método deve operar.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; type&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TTest = class&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FCode: integer;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; procedure SetCode(NewCode: integer);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure TTest.SetCode(NewCode: integer);&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; FCode := NewCode;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a: TTest;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a.SetCode(2);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
O código em Objetc Pascal acima é traduzido para para o Pascal padrão&lt;br /&gt;
como segue:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; type&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TTest = record&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VMT: pointer;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FCode: integer;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure SetCode(Self: TTest; NewCode: integer);&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Self.FCode := NewCode;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a: ^TTest;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; SetCode(a, 2);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
O exemplo serve para explicar que os métodos recebem o ponteiro Self&lt;br /&gt;
como seu primeiro parâmetro, ou seja, eles recebem o ponteiro Self no&lt;br /&gt;
registrador EAX e o primeiro parâmetro declarado é passado como um&lt;br /&gt;
segundo parâmetro em EDX etc. (o segundo parâmetro declarado é passado&lt;br /&gt;
como terceito em ECX e o resto dos parâmetros são passados em pilha).&lt;br /&gt;
O método SetCod pode ser escrito em assembler como:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure TTest.SetCode(NewCode: integer);&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = Self = endereço da instância TTest&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX = parâmetro NewCode&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // FCode := NewCode;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov TTest[eax].FCode, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TTest(EAX)^.FCode := EDX;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Como se pode ver, os campos de objeto são acessados da mesma forma que&lt;br /&gt;
os campos de registro.&lt;br /&gt;
&lt;br /&gt;
NOTA: Propriedades não são campos e não podem ser acessadas diretamente&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a partir do assembler inline.&lt;br /&gt;
&lt;br /&gt;
Eis um exemplo de um método chamando outro método:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure TTest.Increment;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // SetCode(Code+1);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, TTest[eax].FCode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := TTest(EAX)^.FCode;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; inc edx&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call TTest.SetCode;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Não fixamos o valor de EAX antes de fazer a chamada já que EAX já&lt;br /&gt;
contém o valor desejado (Self), assim o método chamado vai operar no&lt;br /&gt;
mesmo objeto.&lt;br /&gt;
&lt;br /&gt;
NOTAS:&lt;br /&gt;
&lt;br /&gt;
* Métodos virtuais podem ser chamados somente estaticamente, já que&lt;br /&gt;
&amp;nbsp; uma referência à classe é necessária na declaração de chamada.&lt;br /&gt;
&lt;br /&gt;
* Métodos sobrecarregados não podem ser distinguidos em assembler&lt;br /&gt;
&amp;nbsp; inline.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Construtores assembler&lt;br /&gt;
======================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Construtores são métodos muito especiais. Os construtores podem ser&lt;br /&gt;
chamados para criar uma instância de uma classe (isto é, para alocar&lt;br /&gt;
a memória para o objeto e inicializá-lo), ou simplesmente para&lt;br /&gt;
reinicializar um objeto já criado:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; a := TTest.Create;&amp;nbsp;&amp;nbsp; // aloca memória&lt;br /&gt;
&amp;nbsp; a.Create;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // apenas reinicializa um objeto existente&lt;br /&gt;
&lt;br /&gt;
Para distinguir entre estas duas situações, os construtores passam&lt;br /&gt;
um segundo parâmetro invisível do tipo byte (ou seja, no registrador&lt;br /&gt;
DL) que pode ser positivo ou negativo respectivamente (o compilador&lt;br /&gt;
usa 1 e -1 respectivamente).&lt;br /&gt;
&lt;br /&gt;
Se temos de chamar um construtor a partir do código assembler com&lt;br /&gt;
DL = $01 (para alocar memória para o objeto), temos de passar uma&lt;br /&gt;
referência à classe em EAX. Já que não há nenhum símbolo para acessá-lo&lt;br /&gt;
diretamente do assembler, temos que fazer algo similar ao que fizemos&lt;br /&gt;
com o tipo de informação dos registros:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TTest_TypeInfo: pointer;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; :&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; initialization&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TTest_TypeInfo := TTest;&lt;br /&gt;
&lt;br /&gt;
Agora que inicializamos uma variável global com a referência à classe a&lt;br /&gt;
partir do nosso código Pascal, podemos usa-la em nosso código assembler:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a: TTest;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // a := TTest.Create(2);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, TTest_TypeInfo&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov dl, 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, 2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call TTest.Create&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov a, eax&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Chamar um construtor para reinicializar o objeto é mais simples já que&lt;br /&gt;
não precisamos de uma referência à classe:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a: TTest;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // a.Create(2);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, a&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov dl, -1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, 2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call TTest.Create&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Não temos nada com que nos preocupar se temos que escrever um construtor&lt;br /&gt;
assembler já que o Delphi manuseia a alocação para nós na entrada do&lt;br /&gt;
construtor e, após isso, o registrador EAX aponta para o objeto, como&lt;br /&gt;
acontece com qualquer outro método. O que é relevante é que se o&lt;br /&gt;
construtor tem parâmetros, o primeiro parâmetro declarado será&lt;br /&gt;
internamente passado como terceito, ou seja, em ECX (ao invés de&lt;br /&gt;
segundo, em EDX, como acontece com outros métodos) e o resto dos&lt;br /&gt;
parâmetros serão passados em ordem, na pilha.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; constructor TTest.Create(NewCode: integer);&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // FCode := NewCode&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov TTest[eax].FCode, ecx&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
__________________&lt;br /&gt;
&lt;br /&gt;
NOTA: Um exemplo com código fonte completo está anexado &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Funções API e a convenção de chamada Stdcall&lt;br /&gt;
============================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As funções API são chamadas de forma transparente a partir do assembler&lt;br /&gt;
nativo com a declaração CALL. Contudo, devemos levar em consideração que&lt;br /&gt;
passar parâmetros para funções API é diferente já que elas normalmente&lt;br /&gt;
usam o convenção de chamada Stdcall, ao invés da convenção de chamada&lt;br /&gt;
Register, que é a que vimos em várias ocasiões anteriores já que ela é a&lt;br /&gt;
convenção padrão.&lt;br /&gt;
&lt;br /&gt;
Na convenção de chamada Stdcall, todos os parâmetros são passados para a&lt;br /&gt;
pilha, da direita para a esquerda, ou seja, o último parâmetro (o mais à&lt;br /&gt;
direita) é enviado primeiro e o primeiro (o mais à esquerda) é enviado&lt;br /&gt;
por último, e, portanto, ele será o primeiro no topo da pilha. Eis um&lt;br /&gt;
exemplo de um procedimento que chama uma função API:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure HideForm(Handle: THandle);&lt;br /&gt;
&amp;nbsp; // Windows.ShowWindow(Handle, SW_HIDE);&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push SW_HIDE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // push 0&amp;nbsp;&amp;nbsp; // passa o segundo parâmetro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push Handle&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // push eax // passa o primeiro parâmetro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call Windows.ShowWindow&amp;nbsp; // chama a API ShowWindow&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Se temos que chamar um método que usa a convenção Stdcall, devemos&lt;br /&gt;
lembrar que o ponteiro Self é o primeiro parâmetro invisível, logo ele&lt;br /&gt;
será passado por último na pilha.&lt;br /&gt;
&lt;br /&gt;
Se temos que escrever funções que usam a convenção Stdcall, não há nada&lt;br /&gt;
de especial para nos preocuparmos. O compilador sempre criará uma pilha&lt;br /&gt;
e referências aos nomes dos parâmetros serão convertidas em endereços&lt;br /&gt;
relativos ao ponteiro base:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function AddAndMultiply(i1, i2, i3: integer): integer; stdcall;&lt;br /&gt;
&amp;nbsp; asm&amp;nbsp; // ==&amp;gt; push ebp; mov ebp, esp&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := (i1 + i2) * i3;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, i1&amp;nbsp;&amp;nbsp; // mov eax, [ebp+8]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, i2&amp;nbsp;&amp;nbsp; // add eax, [ebp+12]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; imul i3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // imul [ebp+16]&lt;br /&gt;
&amp;nbsp; end; // ==&amp;gt; pop ebp; ret 12&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Este é um exemplo de chamada para a função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // a := AddAndMultiply(1, 2, 3); // o resultado seria 9&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 3&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call AddAndMultiply&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov a, eax&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Após a entrada na função, a pilha se pareceria com isto:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp; Old EBP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP], [ESP]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; | Return Address |&amp;nbsp; [EBP+4]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i1 = 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP+8]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i2 = 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP+12]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i3 = 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP+16]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Bibliotecas C/C++ e a convenção de chamada Cdecl&lt;br /&gt;
================================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Algumas vezes precisamos acessar funções em arquivos objeto (.OBJ),&lt;br /&gt;
bibliotecas estáticas (.LIB) ou bibliotecas dinâmicas (.DLL) escritas&lt;br /&gt;
em C ou C++ e, muito freqüentemente, estas funções usam a convenção de&lt;br /&gt;
chamada Cdecl. Ela é muito parecida com a convenção Stdcall, mas a pilha&lt;br /&gt;
deve ser limpa por quem a chama, isto é, quem a chama deve invocar os&lt;br /&gt;
parâmetros que ela inicia ou- ainda melhor- incrementar o ponteiro da&lt;br /&gt;
pilha.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function AddAndMultiply(i1, i2, i3: integer): integer; cdecl;&lt;br /&gt;
&amp;nbsp; asm&amp;nbsp; // ==&amp;gt; push ebp; mov ebp, esp&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := (i1 + i2) * i3;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, i1&amp;nbsp;&amp;nbsp; // mov eax, [ebp+8]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, i2&amp;nbsp;&amp;nbsp; // add eax, [ebp+12]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; imul i3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // imul [ebp+16]&lt;br /&gt;
&amp;nbsp; end; // ==&amp;gt; pop ebp; ret&lt;br /&gt;
&lt;br /&gt;
Note-se no comentário da última linha que a função não move o ponteiro&lt;br /&gt;
da pilha como ocorreu no exemplo anterior que usou a convenção Stdcall;&lt;br /&gt;
logo, quem chamar esta função é que será o responsável por isso. Este é&lt;br /&gt;
um exemplo de chamada para esta função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // a := AddAndMultiply(1, 2, 3); // seria 9&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 3&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call AddAndMultiply&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add esp, 12&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // limpa a pilha&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov a, eax&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Note-se que se os parâmetros fossem do tipo Byte ao invés de Integer,&lt;br /&gt;
moveríamos ainda o ponteiro da pilha de 12 bytes já que cada parâmetro&lt;br /&gt;
usaria 32 bits (4 bytes) nos dois casos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;A convenção de chamada Pascal&lt;br /&gt;
=============================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Muitos programadores C/C++ preferem a convenção de chamada Pascal ao&lt;br /&gt;
invés da Cdecl porque ela é mais compacta e também mais rápida já que a&lt;br /&gt;
função chamada limpa a pilha na declaração RET, como ocorre na convenção&lt;br /&gt;
Stdcall. A convenção Pascal é como a Stdcall, mas os parâmetros são&lt;br /&gt;
passados da esquerda para a direita ao invés da direita para a esquerda,&lt;br /&gt;
isto é, o primeiro parâmetro (o mais a esquerda) é passado primeiro e o&lt;br /&gt;
último (o mais a direita) é passado por último:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function AddAndMultiply(i1, i2, i3: integer): integer; pascal;&lt;br /&gt;
&amp;nbsp; asm&amp;nbsp; // ==&amp;gt; push ebp; mov ebp, esp&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result := (i1 + i2) * i3;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, i1&amp;nbsp;&amp;nbsp; // mov eax, [ebp+16]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, i2&amp;nbsp;&amp;nbsp; // add eax, [ebp+12]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; imul i3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // imul [ebp+8]&lt;br /&gt;
&amp;nbsp; end; // ==&amp;gt; pop ebp; ret 12&lt;br /&gt;
&lt;br /&gt;
Note-se como os endereços dos parâmetros são traduzidos de modo&lt;br /&gt;
diferente que nos exemplos anteriores.&lt;br /&gt;
&lt;br /&gt;
Este é um exemplo de chamada desta função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // a := AddAndMultiply(1, 2, 3); // seria 9&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push 3&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call AddAndMultiply&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov a, eax&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Após a chamada da função, a pilha se pareceria com isto:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EBP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP], [ESP]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; | Return Address |&amp;nbsp; [EBP+4]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i3 = 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP+8]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i2 = 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP+12]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i1 = 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp; [EBP+16]&lt;br /&gt;
&amp;nbsp; +----------------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-8359493754189208834?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/unC60Zrdz8UeZXBQ4VuJkHbwMIA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/unC60Zrdz8UeZXBQ4VuJkHbwMIA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/unC60Zrdz8UeZXBQ4VuJkHbwMIA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/unC60Zrdz8UeZXBQ4VuJkHbwMIA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/yjTeW_69Wlw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/8359493754189208834/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-3.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/8359493754189208834?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/8359493754189208834?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/yjTeW_69Wlw/delphi-com-assembly-parte-3.html" title="Delphi com assembly (Parte 3)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEABRH49eSp7ImA9WhdQE0U.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-2359678838181797551</id><published>2011-08-15T02:39:00.000-03:00</published><updated>2011-08-15T02:39:15.061-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-15T02:39:15.061-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 2)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;Passando arrays estáticas como parâmetros&lt;br /&gt;
=========================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Parâmetros de arrays estáticas são passados como ponteiros ao primeiro&lt;br /&gt;
elemento do array, independentemente do parâmetro ser passado por valor&lt;br /&gt;
ou por referência (como "var" ou como "const").&lt;br /&gt;
&lt;br /&gt;
Dadas as seguintes declarações...&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; const&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ARRAY_MAX = 5;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; type&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TArrayOfInt = packed array [0..ARRAY_MAX] of longint;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a, b: TArrayOfInt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure InitializeArray(var a: TArrayOfInt);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; i: integer;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; for i := 0 to ARRAY_MAX do&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a[i] := i;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
... a chamada à procedure InitializeArray em assembler seria:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Em Object Pascal:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; InitializeArray(a);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Em Assembler Inline:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, offset a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @a;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call InitializeArray&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // InitializeArray;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
OFFSET é um operador unário assembler que retorna o endereço de um&lt;br /&gt;
símbolo. O OFFSET não é aplicável para símbolos locais. Deve-se usar o&lt;br /&gt;
opcode LEA (veja abaixo), que é mais "universal".&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Arrays estáticas passadas por valor&lt;br /&gt;
-----------------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Se o array é passado por valor, é responsabilidade da função chamada&lt;br /&gt;
preservar o array. Quando a função precisa mudar os valores de um ou&lt;br /&gt;
mais elementos de um array passado por valor, normalmente ela cria uma&lt;br /&gt;
cópia local e trabalha com a cópia. O compilador cria uma cópia para nós&lt;br /&gt;
no "begin" das procedures e funções Pascal, mas em procedures e funções&lt;br /&gt;
em assembler puro temos de fazer isto nós mesmos. Um modo de se fazer&lt;br /&gt;
isto seria o seguinte:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure OperateOnArrayPassedByValue(a: TArrayOfInt);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _a: TArrayOfInt;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Copia os elementos de "a" (parâmetro) em "_a" (cópia local)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Salva ESI na pilha&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push edi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Salva EDI na pilha&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := EAX; // @a&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea edi, _a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDI := @_a;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, edi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EDI; // @_a&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, type TArrayOfInt&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := sizeof(TArrayOfInt);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; rep movsb&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Move(ESI^, EDI^, ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop edi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Restaura EDI da pilha&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Restaura ESI da pilha&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Aqui vai o resto da função. Trabalharemos sobre o "_a" (a&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // cópia local), cujo primeiro elemento está agora apontado por EAX.&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
O que encontramos de novo aqui são os opcods LEA e MOVSB, o prefixo REP&lt;br /&gt;
e o operador TYPE, descritos abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
LEA (Load Effective Address)&lt;br /&gt;
----------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Move para o primeiro operando o endereço do segundo. Aqui comparamos LEA&lt;br /&gt;
com MOV:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp; Instrução&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Traduzida como&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Efeito&lt;br /&gt;
&amp;nbsp; -------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp; lea eax, localvar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, [ebp-$04]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX := @localvar;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX := EBP - $04;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp; mov eax, localvar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [ebp-$04]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX := localvar;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX := (EBP - $04)^;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;MOVSB (MOVe String Byte)&lt;br /&gt;
------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Copia o byte apontado por ESI ao local apontado por EDI, e incrementa&lt;br /&gt;
ESI e EDI de tal forma que eles apontem para o próximo byte. O trabalho&lt;br /&gt;
do MOVSB pode ser descrito como segue:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; ESI^ := EDI^;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Assume que ESI e EDI são do tipo PChar&lt;br /&gt;
&amp;nbsp; Inc(ESI);&lt;br /&gt;
&amp;nbsp; Inc(EDI);&lt;br /&gt;
&lt;br /&gt;
Notas:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;* MOVSW e MOVSD são as versões Word (16-bit) e DWord (32-bit)&lt;br /&gt;
&amp;nbsp;&amp;nbsp; respectivamente (ESI e EDI são incrementadas de 2 e 4&lt;br /&gt;
&amp;nbsp;&amp;nbsp; respectivamente).&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;* Os registradores são decrementados se o Direction Flag é setado.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;REP&lt;br /&gt;
---&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
O prefixo REP é usado em operações de string para repetir a operação&lt;br /&gt;
de decremento ECX até que ECX seja zero. O trabalho do REP poderia ser&lt;br /&gt;
descrito como segue:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; // rep string_instruction&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; @@rep:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string_instruction&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; loop @@rep&lt;br /&gt;
&lt;br /&gt;
Notas:&lt;br /&gt;
&lt;br /&gt;
* O REP não é um atalho para um código como o acima. Ele trabalha muito&lt;br /&gt;
&amp;nbsp; mais rápido.&lt;br /&gt;
&lt;br /&gt;
* O valor de ECX não é checado no começo do loop (se ECX fosse zero, a&lt;br /&gt;
&amp;nbsp; instrução seria repetida 2^32 vezes, mas geraria um extenso AV antes&lt;br /&gt;
&amp;nbsp; disto, tão logo ESI ou EDI apontassem para uma localição de memória&lt;br /&gt;
&amp;nbsp; inválida).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;TYPE&lt;br /&gt;
----&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
O operador TYPE é um operador unário avaliado em tempo de compilação que&lt;br /&gt;
retorna o tamanho em bytes de um operando, que deve ser um tipo de dados.&lt;br /&gt;
Por exemplo, TYPE WORD retornará 2 e TYPE INTEGER retornará 4.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Acessando os elementos de um array&lt;br /&gt;
==================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Para acessar um elemento a[i] precisamos dos valores "@a[0]" e "i" nos&lt;br /&gt;
registradores (como EDX e ECX, por exemplo) para então podermos usar o&lt;br /&gt;
endereçamento de memória como segue:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; lea edx, a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @a;&lt;br /&gt;
&amp;nbsp; mov ecx, i&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := i;&lt;br /&gt;
&amp;nbsp; mov ax, [edx+ecx*type integer]&amp;nbsp; // AX := EDX[ECX];&amp;nbsp; // a[i];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // PWord(EDX + ECX * SizeOf(integer))^&lt;br /&gt;
&lt;br /&gt;
No exemplo, presumimos que os elementos têm 2 bytes (movemos o valor de&lt;br /&gt;
a[i] para AX, um registrador de 16 bits), que a array não é agrupada&lt;br /&gt;
(cada elemento realmente ocupa 4 bytes, o tamanho de um inteiro, logo&lt;br /&gt;
este valor foi usado para calcular a posição do elemento) e que o array&lt;br /&gt;
não começa pelo elemento 0, ou seja, não é um array "zero-based". Por&lt;br /&gt;
exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; var a: array [0..N] of word = (1, 2, 3, 6, ...);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; +------ EDX = @a&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; v&lt;br /&gt;
&amp;nbsp; +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--&lt;br /&gt;
&amp;nbsp; | 1 | 0 |&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp; | 2 | 0 |&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp; | 3 | 0 |&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp; | 6 | 0 |&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a[0]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a[1]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a[2]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a[3]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [edx]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [edx+04]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [edx+08]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [edx+12]&lt;br /&gt;
&lt;br /&gt;
Se o array não é zero-based, temos que ajustar o valor do índice para&lt;br /&gt;
torná-lo zero-based antes de endereçarmos o elemento. Exemplos:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; // a[1..100]&lt;br /&gt;
&amp;nbsp; :&lt;br /&gt;
&amp;nbsp; mov ecx, i&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := i;&lt;br /&gt;
&amp;nbsp; dec ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Dec(ECX); // Ajusta ECX&lt;br /&gt;
&amp;nbsp; :&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; // a[-10..10]&lt;br /&gt;
&amp;nbsp; :&lt;br /&gt;
&amp;nbsp; mov ecx, i&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := i;&lt;br /&gt;
&amp;nbsp; add ecx, 10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Inc(ECX, 10); // Ajusta ECX&lt;br /&gt;
&amp;nbsp; :&lt;br /&gt;
&lt;br /&gt;
A procedure InitializeArray (apresentada acima) pode ser implementada em&lt;br /&gt;
assembler do seguinte modo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure InitializeArray(var a: TArrayOfInt);&lt;br /&gt;
&amp;nbsp; asm&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = PByte(@a[0]);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor ecx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := 0;&lt;br /&gt;
&amp;nbsp; @@loop:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [eax+ecx*type integer], ecx&amp;nbsp; // PInteger(EAX+ECX*4)^ := ECX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; ...or&amp;nbsp; EAX[ECX] := ECX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; inc ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := ECX + 1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp ecx, ARRAY_MAX&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if ECX &amp;lt;= ARRAY_MAX then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jle @@loop&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; goto @@loop;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Ou assim:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure InitializeArray(var a: TArrayOfInt);&lt;br /&gt;
&amp;nbsp; asm&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = @a[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor ecx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := 0;&lt;br /&gt;
&amp;nbsp; @@loop:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [eax], ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX^ := ECX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; inc ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Inc(ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, type integer&amp;nbsp; // Inc(EAX); // Aponta para o próximo elemento&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp ecx, ARRAY_MAX&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if ECX &amp;lt;= ARRAY_MAX then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jle @@loop&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; goto @@loop;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Valores de retorno de arrays&lt;br /&gt;
============================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As funções que retornam arrays recebem um último parâmetro adicional que&lt;br /&gt;
é o ponteiro para a locação de memória onde deveam colocar seu valor de&lt;br /&gt;
retorno (a memória é alocada e liberada se necessário por quem acessou).&lt;br /&gt;
Por exemplo, consideremos a seguinte função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ReverseArray(const a: TArrayOfInt): TArrayOfInt;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; i: integer;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; for i := 0 to ARRAY_MAX do&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result[i] := a[ARRAY_MAX-i];&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
A função recebe dois parâmetros:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; 1) EAX = endereço do primeiro elemento da array "a"&lt;br /&gt;
&amp;nbsp; 2) EDX = endereço do primeiro elemento de Result&lt;br /&gt;
&lt;br /&gt;
A função pode ser reescrita em assembler como segue:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ReverseArray(const a: TArrayOfInt): TArrayOfInt;&lt;br /&gt;
&amp;nbsp; asm&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = @a[0]; EDX = @Result[0];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push ebx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Save EBX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ebx, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EBX := EAX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor ecx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := 0;&lt;br /&gt;
&amp;nbsp; @@loop:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, ARRAY_MAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub eax, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := ARRAY_MAX-ECX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, [ebx+eax*type integer]&amp;nbsp; // EAX := EBX[EAX];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx+ecx*type integer], eax&amp;nbsp; // EDX[ECX] := EAX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; inc ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := ECX + 1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp ecx, ARRAY_MAX&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if ECX &amp;lt;= ARRAY_MAX then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jle @@loop&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; goto @@loop;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop ebx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Restore EBX&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Bem, isto é tudo por enquanto. No próximo artigo veremos como trabalhar&lt;br /&gt;
com registros.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Passando records como parâmetros&lt;br /&gt;
================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Como arrays estáticos, records são internamente passados como ponteiros&lt;br /&gt;
para os dados, independentemente se o parâmetro é passado por valor ou&lt;br /&gt;
por referência (também como "var" ou como "const").&lt;br /&gt;
&lt;br /&gt;
Dada as seguintes declarações...&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; type&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TRecord = record&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id: integer;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name: string;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; a, b: TRecord;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure InitRecord(var r: TRecord; Id: integer; const Name: string);&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; r.Id := Id;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; r.Name := Name;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
...uma chamada para a procedure InitRecord em assembler seria assim:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Em Object Pascal:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; InitRecord(a, n, s);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Em Inline Assembler:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @a; // 1st parameter in EAX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, n&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := n;&amp;nbsp; // 2nd parameter in EDX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := s;&amp;nbsp; // 3rd parameter in ECX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call InitRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // InitRecord;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Acessando os campos de um record&lt;br /&gt;
================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Campos de records estão localizados em um certo offset de um endereço do&lt;br /&gt;
record (o endereço do primeiro campo). No exemplo, assumindo que nós&lt;br /&gt;
temos o endereço do record do tipo TRecord no registrador EAX, o campo&lt;br /&gt;
Id está localizado em [EAX+0] (ou simplesmente [EAX]), e o campo Name&lt;br /&gt;
está localizado em [EAX+4], mas normalmente nós não escrevemos código&lt;br /&gt;
usando números explicitamente. Ao invés disto, para produzir código&lt;br /&gt;
auto-explicável e de fácil manutenção, nós temos cinco alternativas:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov edx, [eax + TRecord.Name]&lt;br /&gt;
&amp;nbsp; mov edx, (TRecord PTR [eax]).Name&lt;br /&gt;
&amp;nbsp; mov edx, (TRecord [eax]).Name&lt;br /&gt;
&amp;nbsp; mov edx, TRecord[eax].Name&lt;br /&gt;
&amp;nbsp; mov edx, [eax].TRecord.Name&lt;br /&gt;
&lt;br /&gt;
As cinco sentenças anteriores seriam montadas como:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov edx, [eax + 4]&lt;br /&gt;
&lt;br /&gt;
No lugar de um registrador (como EAX), as sintaxes também se aplicam&lt;br /&gt;
para nome de variáveis locais ou globais.&lt;br /&gt;
&lt;br /&gt;
Você pode deduzir da primeira sintaxe que em inline assembler a&lt;br /&gt;
expressão RecordType.Field é avaliada em tempo de compilação como&lt;br /&gt;
uma constante representando o offset no qual o campo está localizado&lt;br /&gt;
no RecorType. Por exemplo, a seguinte sentença é válida:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov ecx, TRecord.Name&amp;nbsp;&amp;nbsp; // mov ecx, 4&lt;br /&gt;
&lt;br /&gt;
Voltando ao assunto, a procedure InitRecord (apresentada acima) pode ser&lt;br /&gt;
implementada em assembler desta forma:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure InitRecord(var r: TRecord; Id: integer; const Name: string);&lt;br /&gt;
&amp;nbsp; asm // EAX = @r;&amp;nbsp; EDX = Id;&amp;nbsp; ECX = @Name[1]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov (TRecord PTR [eax]).Id, edx&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX^.Id := EDX;&amp;nbsp; // Id&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // _LStrAsg(@EAX^.Name, @Name) --&amp;gt; EAX^.Name := Name&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, (TRecord PTR [eax]).Name&amp;nbsp; // EAX := @(EAX^.Name);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @Name[1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@LStrAsg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // _LStrAsg(EAX, EDX)&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Na entrada da procedure, nós temos EAX apontando para o registro&lt;br /&gt;
(primeiro parâmetro), EDX contendo o Id (segundo parâmetro), EDX&lt;br /&gt;
apontando para o dado da string Name (terceiro parâmetro). Atribuir&lt;br /&gt;
um inteiro é bem simples, mas atribuir uma string é um pouco mais&lt;br /&gt;
complicado.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Se a string destino não é uma string vazia então&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Decremente a contagem de referência da string destino;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Se a contagem de referência da string destino chegou a zero então&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Libere a string destino;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Se a String Origem não for uma string vazia então&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Incremente a contagem de referência da String origem;&lt;br /&gt;
&amp;nbsp; Designe origem para o destino;&lt;br /&gt;
&lt;br /&gt;
A procedure _LStrAsg (da Unit System) implementa esta lógica para nós. A&lt;br /&gt;
procedure recebe dois parâmetros: o primeiro (em EAX) é a string destino&lt;br /&gt;
passada por referência e o segundo (em EDX) é a string origem passada&lt;br /&gt;
por valor (o que é passado na verdade é o ponteiro, visto que strings&lt;br /&gt;
são ponteiros para os caracteres de fato). Então, no nosso caso, EAX&lt;br /&gt;
deveria ser o endereço de uma variável string que será atribuída (isto é&lt;br /&gt;
@r.Name), enquanto EDX deveria ser o valor a ser atribuído:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX&amp;nbsp; --&amp;gt; r.Name --&amp;gt; r.Name[1]&amp;nbsp;&amp;nbsp; ==&amp;gt;&amp;nbsp;&amp;nbsp; EAX = @r.Name&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; EDX&amp;nbsp; --&amp;gt; Name[1]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ==&amp;gt;&amp;nbsp;&amp;nbsp; EDX = @Name[1]&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Ref.: "--&amp;gt;" significa "aponta para"&lt;br /&gt;
&lt;br /&gt;
Então, preparamos EAX e EDX e então chamamos _LStrAsg:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, (TRecord PTR [eax]).Name&amp;nbsp; // EAX := @(EAX^.Name);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @Name[1];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@LStrAsg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // _LStrAsg(EAX, EDX)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
Funções de baixo nível para trabalhar com records&lt;br /&gt;
=================================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Como arrays estáticos, se o record é passado por valor, é&lt;br /&gt;
responsabilidade da função chamada preservar o record. Quando uma função&lt;br /&gt;
precisa trocar o valor de um ou mais campos do record passado por valor,&lt;br /&gt;
normalmente ela cria uma cópia local e trabalha com a cópia. O&lt;br /&gt;
compilador cria uma cópia para nós no "begin" das funções Pascal, mas&lt;br /&gt;
nas funções puramente assembler temos que fazê-lo nós mesmos. Um jeito&lt;br /&gt;
de fazer isto é como mostrado na parte III com arrays estáticos. Aqui&lt;br /&gt;
está outro modo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure OperateOnRecordPassedByValue(r: TRecord);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _r: TRecord;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Copia os elementos de "r" (parâmetros) em "_r" (cópia local)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Move(r, _r, sizeof(TRecord));&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea edx, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, type TRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := sizeof(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call Move&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Move(EAX^, EDX^, ECX);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := TRecord_TypeInfo;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@AddRefRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._AddRefRecord(EAX,EDX);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r; // optional&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Aqui vai o resto da função. Nós trabalharemos no&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // record "_r" (a cópia local), agora apontada por EAX.&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Desta vez nós chamamos a procedure Move ao invés de copiarmos os dados&lt;br /&gt;
com REP MOVSB. Deste modo, nós escrevemos menos código.&lt;br /&gt;
&lt;br /&gt;
IMPORTANTE: Copiar os valores da memória apenas funciona com records que&lt;br /&gt;
não contém campos do tipo reference-counted tais como strings, arrays&lt;br /&gt;
dinâmicos ou variantes do tipo string ou arrays dinâmicos.&lt;br /&gt;
&lt;br /&gt;
Se nós tivermos um ou mais campos string, ou campos de algum outro tipo&lt;br /&gt;
reference-counted, depois de copiar os valores de memória, nós temos que&lt;br /&gt;
incrementar seus respectivos contadores de referência. A procedure&lt;br /&gt;
_AddRefRecord (da Unit System) realiza isto. Ela possui dois parâmetros:&lt;br /&gt;
um ponteiro para o record (em EAX) e um ponteiro para informação do tipo&lt;br /&gt;
de dado para o record gerado pelo compilador (em EDX).&lt;br /&gt;
&lt;br /&gt;
A informação de tipo para o record é basicamente uma estrutura de dados&lt;br /&gt;
que contém as posições e tipos de campos reference-counted do registro.&lt;br /&gt;
As procedures que trabalham com records declaradas na Unit System,&lt;br /&gt;
(_InitializeRecord, _AddRefRecord, _CopyRecord, e _FinalizeRecord)&lt;br /&gt;
requerem um ponteiro para a informação do tipo de dado como seu último&lt;br /&gt;
parâmetro.&lt;br /&gt;
&lt;br /&gt;
Mas, onde estão os dados? Bem, infelizmente, não há um símbolo para&lt;br /&gt;
acessar sua localização diretamente. Nós temos que conseguir seu&lt;br /&gt;
endereço através de uma chamada para a função TypeInfo, mas não há uma&lt;br /&gt;
função que nós possamos chamar através do código assembler porque não é&lt;br /&gt;
uma função verdadeira, e sim uma função interna que o compilador resolve&lt;br /&gt;
em tempo de compilação.&lt;br /&gt;
&lt;br /&gt;
Um possível contorno é inicializar uma variável global, chamando a&lt;br /&gt;
função TypeInfo de nosso código Pascal:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TRecord_TypeInfo: pointer;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; :&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; initialization&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; TRecord_TypeInfo := TypeInfo(TRecord);&lt;br /&gt;
&lt;br /&gt;
E então podemos usá-la como:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure OperateOnRecordPassedByValue(r: TRecord);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _r: TRecord;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Copiar os elementos de "r" (parâmetro) para "_r" (cópia local)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Move(_r, r, sizeof(TRecord));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea edx, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, TYPE TRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := sizeof(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call Move&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Move(EAX^, EDX^, ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._AddRefRecord(@_r, TypeInfo(TRecord));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := TypeInfo(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@AddRefRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._AddRefRecord(EAX, EDX);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r; // opcional&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Aqui vai o resto da função. Nós trabalharemos no&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // record "_r" (a cópia local), agora apontada em EAX.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Nós temos que finalizar a cópia local antes de retornarmos&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._FinalizeRecord(@_r, TypeInfo(TRecord));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := TypeInfo(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@FinalizeRecord&amp;nbsp;&amp;nbsp; // System._FinalizeRecord(EAX, EDX);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note que antes da função retornar, nós temos que fazer a chamada a&lt;br /&gt;
_FinalizeRecord para destruir o record local (por exemplo, isto&lt;br /&gt;
decrementará a contagem de referência de strings apontadas por campos&lt;br /&gt;
string).&lt;br /&gt;
&lt;br /&gt;
Chamar Move e então _AddRefRecord é um jeito válido de copiar records&lt;br /&gt;
se e apenas se o record de destino tenha sido inicializado (depois de&lt;br /&gt;
chamar _AddRefRecord, o record é inicializado). Se o record de destino&lt;br /&gt;
já estiver inicializado, então nós temos que chamar _CopyRecord ao invés&lt;br /&gt;
disto.&lt;br /&gt;
&lt;br /&gt;
Por Exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure proc(const r: TRecord);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _r: TRecord;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // _r := r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := @r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp; // ECX := TypeInfo(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@CopyRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._CopyRecord(EAX, EDX, ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Note que como isto é uma função Pascal normal (não uma função Assembler&lt;br /&gt;
completa), o compilador automaticamente gera código para inicializar&lt;br /&gt;
e finalizar a variável record local (no "begin" e "end" da procedure&lt;br /&gt;
respectivamente).&lt;br /&gt;
&lt;br /&gt;
A combinação Move mais _AddRefRecord é idêntica em efeito a&lt;br /&gt;
_InitializeRecord mais _CopyRecord:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure OperateOnRecordPassedByValue(r: TRecord);&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _r: TRecord;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Copiar os elementos de "r" (parâmetro) para "_r" (cópia local)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Move(_r, r, sizeof(TRecord));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._InitializeRecord(@_r, TypeInfo(TRecord));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Push(EAX); // @r&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := TypeInfo(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@InitializeRecord // System._InitializeRecord(EAX, EDX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // _r := r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := Pop(); // @r&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := TypeInfo(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@CopyRecord&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._CopyRecord(EAX, EDX, ECX);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r; // optional&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Aqui vai o resto da função. Nós trabalharemos no&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // record "_r" (a cópia local), agora apontada em EAX.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Nós temos que finalizar a cópia local antes de retornarmos&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // System._FinalizeRecord(@_r, TypeInfo(TRecord));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, _r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := @_r;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, TRecord_TypeInfo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX := TypeInfo(TRecord);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@FinalizeRecord&amp;nbsp;&amp;nbsp; // System._FinalizeRecord(EAX, EDX);&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Como _AddRefRecord, a procedure _InitializeRecord é apenas destinada&lt;br /&gt;
para ser usada com records não inicializados.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
Retornando valores de records&lt;br /&gt;
=============================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Retornar valores de records é exatamente o mesmo que retornar valores de&lt;br /&gt;
array estático. Funções que retornam records recebem um último parâmetro&lt;br /&gt;
adicional que é o ponteiro para a localização em memória onde o valor de&lt;br /&gt;
retorno deve ser armazenado, isto é, o valor do último parâmetro é&lt;br /&gt;
@Result. A memória para o record de resultado deveria ser alocada,&lt;br /&gt;
inicializada e liberada pelo chamador (não é de responsabilidade da&lt;br /&gt;
função chamada). Por exemplo, vamos considerar a seguinte função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function MakeRecord(Id: integer; const Name: string): TRecord;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result.Id := Id;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result.Name := Name;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
A função é declarada para receber dois parâmetros e retornar um record,&lt;br /&gt;
mas internamente é como uma procedure com três parâmetros:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; 1) EAX = O Id para o novo record&lt;br /&gt;
&amp;nbsp; 2) EDX = O nome para o novo record&lt;br /&gt;
&amp;nbsp; 3) ECX = O endereço do record de resultado (@Result)&lt;br /&gt;
&lt;br /&gt;
A função pode ser reescrita em assembler como segue :&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function MakeRecord(Id: integer; const Name: string): TRecord;&lt;br /&gt;
&amp;nbsp; asm // EAX = Id;&amp;nbsp; EDX = @Name[1];&amp;nbsp; ECX = @Result&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov (TRecord PTR [ecx]).Id, eax&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX^.Id := EAX;&amp;nbsp; // Id&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // (@Result)^.Id := EAX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result.Id := EAX;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Result.Name := Name;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // System.@LStrAsg(@(Result.Name), @Name[1])&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // System.@LStrAsg(@(ECX^.Name), @Name[1])&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea eax, (TRecord PTR [ecx]).Name&amp;nbsp; // EAX := @(ECX^.Name);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@LStrAsg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // _LStrAsg(EAX, EDX)&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; NOTA: Nós não designamos o valor EDX antes de chamar _LStrAsg&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; porque EDX já contém o valor desejado (passado como parâmetro)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
Chamando funções que retornam records&lt;br /&gt;
=====================================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Considere o seguinte código:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; a := MakeRecord(n, s);&lt;br /&gt;
&lt;br /&gt;
Alguém seria tentado a pensar que o compilador traduz como:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, n&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, s&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lea ecx, a&amp;nbsp;&amp;nbsp; // ECX := @a;&amp;nbsp; // @Result&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call MakeRecord&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Mas as coisas não acontecem deste jeito, ao menos no Delphi 5. O&lt;br /&gt;
compilador aloca e inicializa uma variável local que armazena o&lt;br /&gt;
resultado e então copia o resultado do record para o record de destino.&lt;br /&gt;
Nós não temos apenas ineficiência realizando uma cópia que seria&lt;br /&gt;
desnecessária se usássemos um código como o acima, mas- como nós temos&lt;br /&gt;
visto acima- a cópia por si mesma não é tão inocente como uma chamada&lt;br /&gt;
para a procedure Move (_CopyRecord checa a informação de tipo de dado&lt;br /&gt;
em runtime para localizar os campos que requerem tratamento especial).&lt;br /&gt;
É claro, a variável local invisível é primeiro inicializada e&lt;br /&gt;
eventualmente finalizada. Este modo é extremamente ineficiente. Se&lt;br /&gt;
você precisa de velocidade, chame funções record-returning usando&lt;br /&gt;
assembler como mostrado acima, passando diretamente o endereço da&lt;br /&gt;
variável que irá guardar o resultado como o último parâmetro (@Result).&lt;br /&gt;
&lt;br /&gt;
Bem, é isto por enquanto. Na próxima parte, veremos algumas coisas&lt;br /&gt;
básicas sobre o trabalho com objetos.&lt;br /&gt;
&lt;br /&gt;
__________________&lt;br /&gt;
&lt;br /&gt;
NOTA: O Código fonte e a aplicação DEMO estaram anexados no último post desse artigo.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-2359678838181797551?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pXX6o2rBVdZEyKTR3ndrUs9-_3U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pXX6o2rBVdZEyKTR3ndrUs9-_3U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pXX6o2rBVdZEyKTR3ndrUs9-_3U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pXX6o2rBVdZEyKTR3ndrUs9-_3U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/VpzJH2T91xc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/2359678838181797551/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-2.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/2359678838181797551?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/2359678838181797551?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/VpzJH2T91xc/delphi-com-assembly-parte-2.html" title="Delphi com assembly (Parte 2)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQGSXk6eSp7ImA9WhdQE0g.&quot;"><id>tag:blogger.com,1999:blog-967430253837456983.post-1588777217374894306</id><published>2011-08-14T17:34:00.001-03:00</published><updated>2011-08-14T17:38:48.711-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-14T17:38:48.711-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Delphi" /><category scheme="http://www.blogger.com/atom/ns#" term="Assembly" /><title>Delphi com assembly (Parte 1)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;b&gt;Este artigo irá introduzir os conceitos de assembler em linha (inline&lt;br /&gt;
assembler) no Delphi. O artigo dará uma noção básica do assunto mas não&lt;br /&gt;
pretende oferecer, em hipótese alguma, detalhes da programação assembler&lt;br /&gt;
que, por si só, precisariam de um livro inteiro ou mais...&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Por que e Quando&lt;br /&gt;
================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Se você der uma olhada no código fonte da RTL e da VCL, você encontrará&lt;br /&gt;
declarações assembler inline em vários pontos. Por que a Borland optou&lt;br /&gt;
por escrever partes do código da RTL e da VCL em assembler? A resposta&lt;br /&gt;
é bem simples: para alcançar velocidade na execução. Nós sabemos que o&lt;br /&gt;
compilador produz código rápido mas um compilador jamais será tão bom&lt;br /&gt;
quanto um programador assembler profissional.&lt;br /&gt;
&lt;br /&gt;
Agora, se o assembler é tão bom, por que não foi utilizado em toda a RTL&lt;br /&gt;
e VCL? A resposta é igualmente simples: porque na programação de mais&lt;br /&gt;
alto nível, é mais fácil codificar, depurar, ler e manter o código, de&lt;br /&gt;
modo que o sacrifício em velocidade fica compensado pelas conveniências&lt;br /&gt;
decorrentes. Isso ajuda a explicar quando o assembler deve ser&lt;br /&gt;
utilizado. Para ser curto, além do acesso ao sistema em baixo nível, o&lt;br /&gt;
assembler inline deve ser utilizado quando a diferença na velocidade de&lt;br /&gt;
execução justifica o trabalho adicional da codificação em assembler. Por&lt;br /&gt;
exemplo, na unidade Math.pas, há muito assembler, basicamente para&lt;br /&gt;
chamadas de sistema em baixo nível (para acesso às funções do&lt;br /&gt;
coprocessador); em System.pas, SysUtils.pas e Classes.pas há também&lt;br /&gt;
diversos blocos em assembler, desta vez para priorizar velocidade; no&lt;br /&gt;
é estranho já que essas podem ser consideradas as unidades centrais da&lt;br /&gt;
RTL e VCL.&lt;br /&gt;
&lt;br /&gt;
Em geral, procedimentos e funções que tendem a ser chamadas de forma&lt;br /&gt;
repetida por um programa devem ser altamente otimizadas, mas codificação&lt;br /&gt;
em assembler deve ser evitada tanto quanto possível. Se desejamos ganhos&lt;br /&gt;
em velocidade, antes de optar por assembler devemos otimizar o algoritmo&lt;br /&gt;
propriamente dito; depois, otimizamos o código Pascal. Se optarmos por&lt;br /&gt;
assembler, o código Pascal otimizado pode servir como documentação e&lt;br /&gt;
pode ser utilizado como "código de contigência" no caso de problemas com&lt;br /&gt;
a manutenção do código assembler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Os Registradores da CPU&lt;br /&gt;
=======================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Os registradores da CPU são como variáveis predefinidas residindo na CPU&lt;br /&gt;
e, por vezes, têm tarefas especiais. Eles não têm tipo e podem ser&lt;br /&gt;
vistos como inteiros de 32 bits com ou sem sinal ou como ponteiros,&lt;br /&gt;
dependendo da situação.&lt;br /&gt;
&lt;br /&gt;
Como estão na própria CPU, é muito mais rápido acessar valores contidos&lt;br /&gt;
nos registradores do que na memória, fazendo dos registros ideais para&lt;br /&gt;
fazer cache de valores.&lt;br /&gt;
&lt;br /&gt;
Como variáveis, os registradores também possuem nomes. Os nomes daqueles&lt;br /&gt;
que usaremos são EAX, EBX, ECX, EDX, ESI, EDI, EBP e ESP. Cada&lt;br /&gt;
registrador tem uma particularidade que o distingue dos demais:&lt;br /&gt;
&lt;br /&gt;
- Para algumas instruções, a CPU foi otimizada para utilizar o&lt;br /&gt;
&amp;nbsp; registrador EAX (também conhecido como acumulador) ou ao menos os&lt;br /&gt;
&amp;nbsp; opcodes são menores. EAX é usado nas multiplicações e as divisões,&lt;br /&gt;
&amp;nbsp; intructions de string, instruções de I/O, instruções de ajuste ASCII&lt;br /&gt;
&amp;nbsp; e decimal, e em algumas instruções especiais (como CDQ, LAHF, SAHF e&lt;br /&gt;
&amp;nbsp; XLAT).&lt;br /&gt;
- EBX é um registrador de uso geral, e é usado implicitamente por XLAT.&lt;br /&gt;
- ECX (também conhecido como contador) tem emprego especial nas&lt;br /&gt;
&amp;nbsp; instruções LOOP, de rotação e deslocamento de bits e de manipulação&lt;br /&gt;
&amp;nbsp; de literais.&lt;br /&gt;
- EDX é utilizado para armazenar os 32 bits mais altos do resultado de&lt;br /&gt;
&amp;nbsp; uma multiplicação ou os os 32 bits mais altos do dividendo e do resto&lt;br /&gt;
&amp;nbsp; de uma divisão.&lt;br /&gt;
- ESI e EDI (conhecidos como índice de origem (source index) e índice&lt;br /&gt;
&amp;nbsp; de destino ("destination index") respectivamente) são como ponteiros&lt;br /&gt;
&amp;nbsp; utilizados em instruções envolvendo strings.&lt;br /&gt;
- EBP (conhecido como ponteiro base) é normalmente usado para endereçar&lt;br /&gt;
&amp;nbsp; valores na pilha (parâmetros e variáveis locais).&lt;br /&gt;
- ESP (conhecido como ponteiro da pilha) é utilizado para controlar a&lt;br /&gt;
&amp;nbsp; pilha. É alterado automaticamente por instruções como PUSH, POP, CALL&lt;br /&gt;
&amp;nbsp; e RET.&lt;br /&gt;
&lt;br /&gt;
Os registradores EBX, ESI, EDI, EBP e ESP devem ser preservados, o que&lt;br /&gt;
significa que antes de usá-los, devemos salvar seus valores em algum&lt;br /&gt;
lugar (normalmente na pilha ou outro registradores) e, quando&lt;br /&gt;
terminarmos de usá-los, devemos restaurar seus valores originais (essas&lt;br /&gt;
operações implicam no uso de instruções e perda de algum tempo) de modo&lt;br /&gt;
que o uso desses registradores será feito somente quando justificável ou&lt;br /&gt;
quando houver uma necessidade inevitável.&lt;br /&gt;
&lt;br /&gt;
Provavelmente você percebeu que os nomes dos registradores iniciam com&lt;br /&gt;
a letra "E". O "E" representa "Extended", estendido. Nos tempos do Intel&lt;br /&gt;
80286, os registradores tinham 16 bits e eram chamados AX, BX, CX, etc.&lt;br /&gt;
Esses registradores ainda existem e são exatamente os 16 bits menos&lt;br /&gt;
significativos dos registradores EAX, EBX, ECX, etc., respectivamente. A&lt;br /&gt;
propósito disso, os registradores AX, BX, CX e DX são divididos em dois&lt;br /&gt;
registradores de 8 bits. AL, BL, CL e DL são os bytes menos&lt;br /&gt;
significativos de AX, BX, CX e DX respectivamente, enquanto AH, BH, CH e&lt;br /&gt;
DH são os bytes mais significativos de AX, BX, CX e DX respectivamente.&lt;br /&gt;
Por exemplo, se o valor de EAX é $7AFD503C, então o valor de AX é $503C,&lt;br /&gt;
o valor de AH é $50 e o valor de AL é $3C:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7A&amp;nbsp; FD&amp;nbsp; 50&amp;nbsp; 3C&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AH&amp;nbsp; AL&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /----/&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /------------/&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX&lt;br /&gt;
&lt;br /&gt;
Se, na situação acima, armazenarmos o valor $99 em AH, então EAX&lt;br /&gt;
passaria a ter o valor $7AFD993C.&lt;br /&gt;
&lt;br /&gt;
Existe um registrador especial, o registrador de indicadores (flags),&lt;br /&gt;
que armazena indicadores binários alterados por instruções matemáticas&lt;br /&gt;
e lógicas ou explicitamente por código, e que são normalmente usados&lt;br /&gt;
em instruções de desvio condicional. O indicador carry também é usado&lt;br /&gt;
em algumas instruções de rotação e o indicador de direção é utilizado&lt;br /&gt;
em instruções envolvendo literais.&lt;br /&gt;
&lt;br /&gt;
Esse registrador não é acessível por nome como os demais registradores;&lt;br /&gt;
mas pode ser copiado e restaurado através da pilha, utilizando PUSHF e&lt;br /&gt;
POPF respectivamente, e pode também ser copiado e restaurado&lt;br /&gt;
parcialmente através do registrador AH, utilizando LAHF e SAHF&lt;br /&gt;
respectivamente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Instruções Assembler&lt;br /&gt;
====================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Instruções assembler são dispostas em blocos asm..end blocks e têm a&lt;br /&gt;
seguinte forma:&lt;br /&gt;
&lt;br /&gt;
[identificador:] [prefixo] opcode [operando1 [, operando2 [, ...]]]&lt;br /&gt;
&lt;br /&gt;
Onde opcode é o nome da instrução como MOV, ADD, PUSH, etc.&lt;br /&gt;
&lt;br /&gt;
Instruções podem ser separadas por ponto e vírgula, quebras de linhas&lt;br /&gt;
ou comentários. A propósito, comentários são no formato do Object&lt;br /&gt;
Pascal, isto é, o ponto e vírgula não é considerado o início de um&lt;br /&gt;
comentário até o final da linha, como no assembler tradicional.&lt;br /&gt;
&lt;br /&gt;
A seguir, um exemplo de bloco asm..end com vários dos possíveis tipos de&lt;br /&gt;
instruções e separadores de comentários:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xchg ebx, edx; add eax, [ebx]; {ponto e vírgula separa declaração}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // quebra de linha separa declaração&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ebx, p&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub eax, [ebx] (*comentário separa declaração*) mov ebx, edx&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
A convenção é utilizar quebras d elinhas para separação:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xchg ebx, edx&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, [ebx]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ebx, p&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub eax, [ebx]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ebx, edx&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
No código da VCL, você verá que os opcodes e nomes de registradores são&lt;br /&gt;
escritos em maiúsculas e que instruções são indentadas em uma tabulação&lt;br /&gt;
(normalmente equivalente a oito caracteres), mas utilizaremos outra&lt;br /&gt;
convenção neste artigo.&lt;br /&gt;
&lt;br /&gt;
Blocos asm..end podem ocorrer em qualquer ponto do código fonte onde uma&lt;br /&gt;
declaração Pascal ordinária puder aparecer; além disso, é possível&lt;br /&gt;
termos rotinas 100% assembler se, ao invés de "begin", utilizarmos&lt;br /&gt;
"asm":&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; procedure teste;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // declarações assembler&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Note que as duas implementações abaixo não são equivalentes:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function f(parâmetros): tipo;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // declarações assembler&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function f(parâmetros): tipo;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // declarações assembler&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
A razão disso é que o compilador realiza certas otimizações quando&lt;br /&gt;
implementamos rotinas inteiramente em assembler, sem utilizar um bloco&lt;br /&gt;
begin..end.&lt;br /&gt;
&lt;br /&gt;
As etiquetas devem ser declaradas em uma seção Label, como em qualquer&lt;br /&gt;
código Object Pascal, a menos que foram prefixadas por "@@":&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function ENumeroMagico(x: integer): boolean;&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp eax, NumeroMagico&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; je @@Bingo&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor eax, eax&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp; @@Bingo:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, 1&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
As etiquetas prefixadas por "@@" são locais ao bloco asm..end em que são&lt;br /&gt;
usadas. Isto gerará um erro da compilaçao:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @@destino:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jnz @@destino&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Error&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Para corrigi-lo, necessitamos usar uma etiqueta convencional, local ao&lt;br /&gt;
procedimento ou à função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; label&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; destino;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; destino:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jnz destino&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Correto&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Operandos&lt;br /&gt;
=========&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Certas vezes, um ou mais operandos são implícitos. Por exemplo, a&lt;br /&gt;
instrução CDQ (Converta Dword para Qword) parece não utilizar operando&lt;br /&gt;
algum; entretanto, essa instrução utiliza EDX e EAX: o bit mais alto&lt;br /&gt;
de EAX, o bit de sinal, é copiado para EDX de forma que, EDX:EAX passa&lt;br /&gt;
a representar o inteiro em EAX convertido para Int64, onde EAX carrega&lt;br /&gt;
os 32 bits menos significativos e EDX os 32 bits mais significativos.&lt;br /&gt;
&lt;br /&gt;
Para a maioria das instruções, os operandos são registradores. Por&lt;br /&gt;
exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov eax, ecx&lt;br /&gt;
&lt;br /&gt;
copia o valor de ECX para EAX.&lt;br /&gt;
&lt;br /&gt;
Operandos podem conter valores imediatos:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov eax, 5&lt;br /&gt;
&amp;nbsp; mov eax, 2 + 3&amp;nbsp; // expressão constante, resolvida na compilação&lt;br /&gt;
&amp;nbsp; mov al, 'A'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // o código ASCII de 'A' é $41 (65)&lt;br /&gt;
&amp;nbsp; mov eax, 'ABC'&amp;nbsp; // equivalente a MOV EAX, $00414243&lt;br /&gt;
&lt;br /&gt;
Operandos também podem conter referências de memória:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov [ebx], eax&amp;nbsp; // EBX^ := EAX;&lt;br /&gt;
&lt;br /&gt;
Referências de memória aparecem de várias formas:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov eax, [$000FFFC]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Endereço absoluto&lt;br /&gt;
&amp;nbsp; mov eax, [ebx]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Registrador&lt;br /&gt;
&amp;nbsp; mov eax, [ebp-12]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Registrador mais/menos deslocamento&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // constante&lt;br /&gt;
&amp;nbsp; mov eax, [ebp+ebx]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Registrador mais deslocamento em registro&lt;br /&gt;
&amp;nbsp; mov eax, [ebp+ebx+8]&amp;nbsp;&amp;nbsp;&amp;nbsp; // Registrador mais deslocamento em registro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // mais/menos deslocamento constante&lt;br /&gt;
&amp;nbsp; mov eax, [ebp+ebx*4]&amp;nbsp;&amp;nbsp;&amp;nbsp; // Registrador mais deslocamento em registro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // multiplicado por constante&lt;br /&gt;
&amp;nbsp; mov eax, [ebp+ebx*4+8]&amp;nbsp; // Registrador mais deslocamento em registro&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // multiplicado por constante, mais/menos&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // deslocamento constante&lt;br /&gt;
&lt;br /&gt;
Os identificadores usuais do Pascal são traduzidos para uma das formas:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov eax, parâmetro&amp;nbsp;&amp;nbsp;&amp;nbsp; // mov eax, [ebp + deslocamento_constante]&lt;br /&gt;
&amp;nbsp; mov eax, varlocal&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // mov eax, [ebp - deslocamento_constante]&lt;br /&gt;
&amp;nbsp; mov eax, varglobal&amp;nbsp;&amp;nbsp;&amp;nbsp; // mov eax, [endereço_absoulto]&lt;br /&gt;
&amp;nbsp; call procname&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // chama endereço absoluto&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Primeiro Exemplo&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Agora que estamos prontos para aprender alguns opcodes, vamos aos&lt;br /&gt;
exemplos. Podemos começar com uma função simples:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function f(x: integer; y: integer): integer;&lt;br /&gt;
&amp;nbsp; // f(x,y) = (-x-y+5)*7&lt;br /&gt;
&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := (-x - y + 5) * 7;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // os parâmetros são passados em EAX (x) e EDX (y);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; neg eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := -EAX;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = -x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub eax, edx&amp;nbsp; // EAX := EAX - EDX;&amp;nbsp; // EAX = -x-y&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, 5&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EAX + 5;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = -x-y+5&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; imul 7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EAX * 7;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = (-x-y+5)*7&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Os três primeiros parâmetros (da esquerda para a direita) são passados&lt;br /&gt;
em EAX, EDX e ECX. Para métodos, o primeiro parâmetro é Self (passado&lt;br /&gt;
em EAX) e o primeiro parâmetro explicitamente declarado é, de fato, o&lt;br /&gt;
segundo parâmetro (passado em EDX) e o segundo parâmetro explícito é&lt;br /&gt;
de fato o terceiro parâmetro (passado em ECX).&lt;br /&gt;
&lt;br /&gt;
O valor de retorno deve ser armazenado em EAX para valores ordinais de&lt;br /&gt;
32 bits (AX e AL devem ser utilizados para retornar valores de 16 e 8&lt;br /&gt;
bits respectivamente).&lt;br /&gt;
&lt;br /&gt;
Os comentários explicam os opcodes de forma clara mas, para IMUL, temos&lt;br /&gt;
que acrescentar duas explicações:&lt;br /&gt;
&lt;br /&gt;
* IMUL considera os operandos (EAX e 7 no exemplo) como inteiros com&lt;br /&gt;
&amp;nbsp; sinal (devemos utilizar MUL quando os operandos não possuírem sinal).&lt;br /&gt;
&lt;br /&gt;
* O resultado da multiplicação é um inteiro de 64 bits sendo que os 32&lt;br /&gt;
&amp;nbsp; bits mais significativos do resultado são armazenados em EDX.&lt;br /&gt;
&lt;br /&gt;
Multiplicações são relativamente caras em termos de tempo de CPU e, por&lt;br /&gt;
vezes, é mais fácil substitui-las por deslocamentos de bits (quando a&lt;br /&gt;
multiplicação ou divisão operarem com potências de dois), somas e&lt;br /&gt;
subtrações. Por exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; a * 7 = a * (8 - 1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = a * 8 - a&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = a * 2^3 - a&lt;br /&gt;
&amp;nbsp; a * 7 = a shl 3 - a&lt;br /&gt;
&lt;br /&gt;
Ao invés de IMUL 7, podemos fazer o seguinte:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, eax&amp;nbsp; // ECX := EAX;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX = -x-y+5&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; shl eax, 3&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EAX shl 3;&amp;nbsp; // EAX = (-x-y+5)*8&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub eax, ecx&amp;nbsp; // EAX := EAX - ECX;&amp;nbsp; // EAX = (-x-y+5)*8 - (-x-y+5)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX = (-x-y+5)*7&lt;br /&gt;
&lt;br /&gt;
Vejamos outro exemplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function resto(x: integer; y: integer): integer;&lt;br /&gt;
&amp;nbsp; // Retorna o resto de x dividido por y&lt;br /&gt;
&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := x mod y;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // os parâmetros são passados em EAX (x) e EDX (y);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, edx&amp;nbsp;&amp;nbsp; // ECX := EDX; // EDX = y&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cdq&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX:EAX := Int64(EAX); // EAX = x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; idiv ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // divisão inteira com sinal em 32 bits:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; EAX := Int64(EDX:EAX) div integer(ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; EDX := Int64(EDX:EAX) mod integer(ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, edx&amp;nbsp;&amp;nbsp; // Result := EDX; // resto&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;A Pilha&lt;br /&gt;
=======&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Quando um programa é carregado, ele receve uma pilha, que é uma região&lt;br /&gt;
de memória utilizada como uma estrutura LIFO, "Last In, First Out"&lt;br /&gt;
(último a chegar, primeiro a sair), controlada pelo registrador ESP&lt;br /&gt;
que aponta para o topo dessa pilha. ESP inicia apontando para o final&lt;br /&gt;
da região de modo que, cada vez que empilhamos um novo valor de 32 bits,&lt;br /&gt;
o registrador ESP é decrementado em 4 (bytes) e o valor é armazenado no&lt;br /&gt;
local apontado por ESP.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $01234567 | &amp;lt;- ESP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; PUSH $89ABCDEF&amp;nbsp;&amp;nbsp; // SUB ESP,4; MOV [ESP],$89ABCDEF&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $89ABCDEF | &amp;lt;- ESP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $01234567 |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
De forma análoga, quando retiramos um valor de 32 bits da pilha, o valor&lt;br /&gt;
é recuperado do local apontado por ESP e ESP é incrementado em 4 (bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; POP EAX&amp;nbsp;&amp;nbsp; // MOV EAX,[ESP]; ADD ESP,4&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $89ABCDEF |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EAX | $89ABCDEF |&lt;br /&gt;
&amp;nbsp; +-----------+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $01234567 | &amp;lt;- ESP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
A pilha é utilizada para armazenar endereços de retorno de rotinas,&lt;br /&gt;
parâmetros, variáveis locais e resultados intermediários. No exemplo&lt;br /&gt;
a seguir, utilizamos a pilha para salvar o valor de um registrador&lt;br /&gt;
para uso posterior:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function IntDiv(x: integer; y: integer; r: pinteger = NIL): integer;&lt;br /&gt;
&amp;nbsp; // Retorna o quociente inteiro x / y e o resto em r&lt;br /&gt;
&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := x div y;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if r &amp;lt;&amp;gt; NIL then r^ := x mod y;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // os parâmetros são passados em EAX (x), EDX (y) e ECX (r)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Salve ECX (r) para uso posterior&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := EDX; // ECX = y&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cdq&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX:EAX := Int64(EAX); // EAX = x&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; idiv ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // divisão inteira com sinal em 32 bits:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; EAX := Int64(EDX:EAX) div integer(ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; EDX := Int64(EDX:EAX) mod integer(ECX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Restaura ECX (ECX := r)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp ecx, 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if ECX = NIL then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jz @@end&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp; goto @@end;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [ecx], edx&amp;nbsp;&amp;nbsp; // ECX^ := EDX; // resto&lt;br /&gt;
&amp;nbsp; @@end:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // identificador local (precedido por "@@")&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Note que, para cada PUSH que executamos, temos que executar um POP&lt;br /&gt;
correspondente de modo que ESP fique inalterado (ESP é um dos&lt;br /&gt;
registradores que temos que preservar).&lt;br /&gt;
&lt;br /&gt;
A instrução CMP subtrai o segundo operador do primeiro (ECX-0 nesse&lt;br /&gt;
caso), como a instrução SUB, mas o resultado não é armazenado em lugar&lt;br /&gt;
algum, ainda que o indicador de Zero (Zero flag) seja marcado (ligado)&lt;br /&gt;
ou limpo (desligado) dependendo do resultado ser zero ou não, como em&lt;br /&gt;
qualquer instrução lógica ou matemática (com a exceção de certos casos).&lt;br /&gt;
Podemos então tirar vantagem desse fato e, ao invés de escrevermos&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp ecx, 0&lt;br /&gt;
&lt;br /&gt;
podemos escrever&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; or ecx, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := ECX or ECX;&lt;br /&gt;
&lt;br /&gt;
O resultado de ECX Or ECX é o próprio ECX; portanto, o valor armazenado&lt;br /&gt;
em ECX é o mesmo de antes, e como dissemos anteriormente o indicador de&lt;br /&gt;
Zero será marcado se o resultado for zero (isto é, se ECX era zero).&lt;br /&gt;
&lt;br /&gt;
A instrução JZ, "Jump if Zero" (Desvie se Zero), desvia (salta) para o&lt;br /&gt;
identificador indicado como operando se o valor do indicador de Zero&lt;br /&gt;
estiver marcado (ligado) ou continua normalmente com o fluxo de execução&lt;br /&gt;
se o indicador de Zero estiver desmarcado (desligado).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Passando Parâmetros para a Pilha&lt;br /&gt;
--------------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Voltemos para a pilha. Dissemos que os três primeiros parâmetros de&lt;br /&gt;
uma rotina são passados em EAX, EDX e ECX; mas, o que acontece quando&lt;br /&gt;
temos mais de três parâmetros? Parâmetros adicionais são passados na&lt;br /&gt;
pilha, da esquerda para a direita, de forma que o último parâmetro será&lt;br /&gt;
sempre o primeiro da pilha.&lt;br /&gt;
&lt;br /&gt;
Suponha que temos a seguinte função&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function Soma(a, b, c, d, e: integer): integer;&lt;br /&gt;
&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := a + b + c + d + e;&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
e queremos fazer a chamada&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Sum(1,2,3,4,5);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Em assembler, faríamos da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; mov eax, 1&lt;br /&gt;
&amp;nbsp; mov edx, 2&lt;br /&gt;
&amp;nbsp; mov ecx, 3&lt;br /&gt;
&amp;nbsp; push 4&lt;br /&gt;
&amp;nbsp; push 5&lt;br /&gt;
&amp;nbsp; call Sum&lt;br /&gt;
&lt;br /&gt;
A instrução CALL empilha o endereço de retorno na pilha e salta para&lt;br /&gt;
(inicia a execução) da função. A instrução RET (RETorna) gerada pelo&lt;br /&gt;
compilador quando o final de uma função é alcançado desempilha esse&lt;br /&gt;
endereço da pilha e salta para ele para continuar a execução a partir&lt;br /&gt;
desse ponto.&lt;br /&gt;
&lt;br /&gt;
Note que quando empilhamos parâmetros na pilha mas não os desempilhamos.&lt;br /&gt;
Isso acontece pois limpar a pilha é responsabilidade da função chamada e&lt;br /&gt;
não da função que chama (exceto na convenção de chamada CDECL). Para&lt;br /&gt;
limpar os parâmetros, a instrução RET é utilizada com um operando que&lt;br /&gt;
indica o número de bytes que ESP deve ser incrementado (8 nesse caso já&lt;br /&gt;
que ESP foi decrementado em 4 bytes para cada parâmetro empilhado). O&lt;br /&gt;
compilador fica encarregado dessa tarefa portanto não temos com que nos&lt;br /&gt;
preocupar; mas, se você utilizar a janela de depuração da CPU e&lt;br /&gt;
encontrar uma instrução RET $08, agora você já sabe do que se trata.&lt;br /&gt;
&lt;br /&gt;
Na entrada para Soma, a pilha estaria, em teoria, da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | Ret_Addr&amp;nbsp; | &amp;lt;- ESP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $00000005 | (parâmetro e)&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $00000004 | (parâmetro d)&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
Quando uma função tem parâmetros na pilha (ou variáveis locais), o&lt;br /&gt;
compilador gera algumas instruções chamadas de "stack frame", quadro&lt;br /&gt;
da pilha. Na entrada da função (em "asm"), EBP é empilhado de modo a&lt;br /&gt;
ser preservado e ESP é atribuído a ele; e, antes de deixar a função,&lt;br /&gt;
(em "end"), o valor original de EBP é desempilhado:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function Soma(a, b, c, d, e: integer): integer;&lt;br /&gt;
&amp;nbsp; asm // push ebp; mov ebp, esp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ....&lt;br /&gt;
&amp;nbsp; end; // pop ebp; ret 8;&lt;br /&gt;
&lt;br /&gt;
Assim, quando entramos em Soma, a pilha estaria de fato da seguinte&lt;br /&gt;
forma:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | Orig. EBP | &amp;lt;- EBP, ESP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | Ret_Addr&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $00000005 | &amp;lt;- EBP+8&amp;nbsp;&amp;nbsp; (parâmetro e)&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | $00000004 | &amp;lt;- EBP+12&amp;nbsp; (parâmetro d)&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
Em [EBP] encontramos o valor original de EBP que foi empilhado para&lt;br /&gt;
ser preservado quando da construção do quadro de pilha; em [EBP+4]&lt;br /&gt;
encontramos o endereço de retorno da rotina; em [EBP+8] encontramos&lt;br /&gt;
o último parâmetro (o último parâmetro é empilhado por último e, por&lt;br /&gt;
isso, é o primeiro da pilha). O parâmetro seguinte (da direita para&lt;br /&gt;
a esquerda) fica em [EBP+12], e assim por diante se houvesse outros&lt;br /&gt;
parâmetros.&lt;br /&gt;
&lt;br /&gt;
Agora vamos escrever a rotina Soma em assembler:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function Soma(a, b, c, d, e: integer): integer;&lt;br /&gt;
&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := a + b + c + d + e;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, b&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, c&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, d&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, e&lt;br /&gt;
&amp;nbsp; end;&lt;br /&gt;
&lt;br /&gt;
Note que no bloco asm..end nós utilizamos "b", "c", "d" e "e" ao invés&lt;br /&gt;
de "EDX", "ECX", "[EBP+12]" e "[EBP+8]" respectivamente. Nós podemos&lt;br /&gt;
fazer assim já que o compilador fará as substituições adequadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Variáveis Locais na Pilha&lt;br /&gt;
-------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Se nossa função assembler inline tiver variáveis locais, o compilador&lt;br /&gt;
criará espaço para essas variáveis na pilha, movendo o ponteiro da pilha&lt;br /&gt;
de modo que o quadro da pilha para uma função com duas variáveis locais&lt;br /&gt;
inteiras seria:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; push ebp&lt;br /&gt;
&amp;nbsp; mov ebp, esp&lt;br /&gt;
&amp;nbsp; sub esp, 8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Desloca ESP como se empilhássemos 8 bytes&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; ...&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; add esp, 8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Desloca ESP como se desempilhássemos 8 bytes&lt;br /&gt;
&amp;nbsp; pop ebp&lt;br /&gt;
&lt;br /&gt;
Para o propósito do exemplo, aqui vai uma variação da rotina Soma acima,&lt;br /&gt;
utilizando duas variáveis locais:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function SomaL(a, b, c, d, e: integer): integer;&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; f, g: integer;&lt;br /&gt;
&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; f := b + c;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; g := d + e;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result := a + f + g;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
&amp;nbsp; asm // push ebp; mov ebp, esp; sub esp, 8;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add edx, ecx&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov f, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // b + c&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, d&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add edx, e&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov g, edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // d + e&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, f&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, g&lt;br /&gt;
&amp;nbsp; end; // add esp, 8; pop ebp; ret 8&lt;br /&gt;
&lt;br /&gt;
Nessa função, a pilha teria o seguinte aspecto:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp; var.&amp;nbsp; g&amp;nbsp; | &amp;lt;- EBP-8, ESP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp; var.&amp;nbsp; f&amp;nbsp; | &amp;lt;- EBP-4&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | Orig. EBP | &amp;lt;- EBP&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; | Ret_Addr&amp;nbsp; |&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp; Param e&amp;nbsp; | &amp;lt;- EBP+8&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp; Param d&amp;nbsp; | &amp;lt;- EBP+12&lt;br /&gt;
&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;O Que Vem Agora?&lt;br /&gt;
================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Na continuação deste artigo, aprenderemos mais instruções e veremos&lt;br /&gt;
como passar e retornar outros tipos de parâmetros, como trabalhar com&lt;br /&gt;
arrays, como acessar campos de registros e objetos, como chamar métodos&lt;br /&gt;
e mais.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nesse capítulo iremos aprender algumas novas instruções assembler e o&lt;br /&gt;
básico da manipulação de strings ANSI, também chamadas de strings longas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Novos opcodes&lt;br /&gt;
=============&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Abaixo os opcodes introduzidos neste atrigo:&lt;br /&gt;
&lt;br /&gt;
* JL (Jump if Lower, desvie se menor): A descrição mais adequada levaria&lt;br /&gt;
&amp;nbsp; muito tempo para ser explicada, então vamos dizer que JL salta (desvia)&lt;br /&gt;
&amp;nbsp; para o label especificado desde que na operação CMP (ou SUB) anterior&lt;br /&gt;
&amp;nbsp; o primeiro operando seja menor que o segundo numa comparação com sinal:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if signed(op1) &amp;lt; signed(op2) then goto @@label;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp op1, op2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jl @@label&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; JG (Jump if Greater, desvie se maior), JLE (Jump if Lower or Equal,&lt;br /&gt;
&amp;nbsp; desvie se menor ou igual) e JGE (Jump if Greater or Equal, desvie se&lt;br /&gt;
&amp;nbsp; maior ou igual) completa a família de desvios condicionais para&lt;br /&gt;
&amp;nbsp; comparações com sinal.&lt;br /&gt;
&lt;br /&gt;
* JA (Jump if Above, desvie se maior): salta (desvia) para o label&lt;br /&gt;
&amp;nbsp; especificado desde que na operação CMP (ou SUB) anterior o primeiro&lt;br /&gt;
&amp;nbsp; operando seja maior que o segundo numa comparação sem sinal:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if unsigned(op1) &amp;gt; unsigned(op2) then goto @@label;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp op1, op2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ja @@label&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; JB (Jump if Below, desvie se menor), JBE (Jump if Below or Equal,&lt;br /&gt;
&amp;nbsp; desvie se menor ou igual) e JAE (Jump if Above or Equal, desvie se&lt;br /&gt;
&amp;nbsp; maior ou igual) completam a família de desvios condicionais para&lt;br /&gt;
&amp;nbsp; comparações sem sinais.&lt;br /&gt;
&lt;br /&gt;
* LOOP: Decrementa ECX e, se não for zero, desvia para o label indicado.&lt;br /&gt;
&amp;nbsp; LOOP @@label é o equivalente mais curto e rápido de:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; dec ecx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := ECX - 1;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jnz @@label&amp;nbsp;&amp;nbsp; // if ECX &amp;lt;&amp;gt; 0 then goto @@label&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Examplo:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; xor eax, eax&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EAX xor EAX;&amp;nbsp; // EAX := 0;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, 5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := 5;&lt;br /&gt;
&amp;nbsp; @@label:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, ecx&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := EAX + ECX; // Executado 5 vezes&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; loop @@label&amp;nbsp;&amp;nbsp;&amp;nbsp; // Dec(ECX); if ECX &amp;lt;&amp;gt; 0 then goto @@label;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX seria 15 (5+4+3+2+1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Trabalhando com strings ANSI&lt;br /&gt;
============================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Uma variável string é representada por um ponteiro de 32 bits. Se a&lt;br /&gt;
string é vazia (''), então o ponteiro é nil (zero), caso contrário,&lt;br /&gt;
esse ponteiro aponta para o primeiro caractere dessa string. O tamanho&lt;br /&gt;
da string e a contagem de referência são dois inteiros em deslocamentos&lt;br /&gt;
negativos a partir do primeiro byte da string:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +-----------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | s: string |-------------------+&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; +-----------+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; V&lt;br /&gt;
&amp;nbsp; --+-----------+-----------+-----------+---+---+---+---+---+---+---+--&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; | allocSiz&amp;nbsp; |&amp;nbsp;&amp;nbsp; refCnt&amp;nbsp; |&amp;nbsp; length&amp;nbsp;&amp;nbsp; | H | e | l | l | o | ! | #0|&lt;br /&gt;
&amp;nbsp; --+-----------+-----------+-----------+---+---+---+---+---+---+---+--&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (longint)&amp;nbsp;&amp;nbsp; (longint)&amp;nbsp;&amp;nbsp; (longint)&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; \-----------------v-----------------/&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StrRec record&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const skew = sizeof(StrRec); // 12&lt;br /&gt;
&lt;br /&gt;
Quando passamos uma string como um parâmetro para uma função, o que de&lt;br /&gt;
fato é passado é o ponteiro de 32 bits. Os valores string são um pouco&lt;br /&gt;
mais complicados de explicar. A rotina que chamou a rotina que retorna&lt;br /&gt;
a string deve passar- como último e invisível parâmetro da chamada, um&lt;br /&gt;
tipo PString-o endereço de uma variável string que receberá o resultado&lt;br /&gt;
da função.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; d := Uppercase(s);&amp;nbsp; // Internamente convertido para: Uppercase(s, @d);&lt;br /&gt;
&lt;br /&gt;
Se o resultado da função é usado em uma expressão ao invés de ser&lt;br /&gt;
atribuído diretamente à variável, a rotina que chama deve utilizar uma&lt;br /&gt;
variável temporária incializada com nil (string vazia). O compilador faz&lt;br /&gt;
tudo isso automaticamente no nosso código Object Pascal mas, se temos&lt;br /&gt;
que fazer isso por conta própria se optarmos por escrever código&lt;br /&gt;
assembler que chame rotinas que retornam strings.&lt;br /&gt;
&lt;br /&gt;
Para algumas tarefas, não podemos chamar as clássicas funções de string&lt;br /&gt;
diretamente. Por exemplo, a função Length não é o nome de uma função de&lt;br /&gt;
verdade,. É uma construção interna do próprio compilador e o compilador&lt;br /&gt;
gera o código para a função apropriada, dependendo do parâmetro ser uma&lt;br /&gt;
string ou um array dinâmico. Em assembler, ao invés de Lenght, teríamos&lt;br /&gt;
que usar a função&amp;nbsp; LStrLen (declarada na unidade System) para obter o&lt;br /&gt;
tamanho da string.&lt;br /&gt;
&lt;br /&gt;
Existem mais coisas que deveríamos saber a respeito das strings mas o&lt;br /&gt;
que temos já é suficiente para um primeiro exemplo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Versão Assembler de Uppercase&lt;br /&gt;
=============================&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Eis a declaração da função:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; function AsmUpperCase(const s: string): string;&lt;br /&gt;
&lt;br /&gt;
O parâmetro "s" será passado em EAX e o endereço de "Result" será&lt;br /&gt;
passado como o segundo parâmetro, ou seja, em EDX.&lt;br /&gt;
&lt;br /&gt;
Basicamente a função deve fazer:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; 1) Obter o comprimento da string a converter&lt;br /&gt;
&amp;nbsp; 2) Alocar memória para a string convertida&lt;br /&gt;
&amp;nbsp; 3) Copiar os caracteres um a um, convertidos para maiúsculas&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;1) Obter o comprimento da string a converter&lt;br /&gt;
--------------------------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Faremos isso através de uma chamada a System.@LStrLen. A função espera&lt;br /&gt;
a string em EAX (ela já está lá) e o resultado será colocado em EAX;&lt;br /&gt;
então, temos que salvar o valor de EAX (o parâmetro "s") em algum lugar&lt;br /&gt;
antes de chamar a função de modo que "s" não seja perdido. Podemos salvar&lt;br /&gt;
numa variável local "src". Já que funções são livres para utilizar os&lt;br /&gt;
registradores EAX, ECX e EDX, presumimos que o valor em EDX ("@Result")&lt;br /&gt;
poderia também ser destruído após uma chamada a System.@LStrLen, de modo&lt;br /&gt;
que é útil salvar esse valor numa variável local, por exemplo, "psrc".&lt;br /&gt;
O resultado da chamada a System.@LStrLen, deixado em EAX, servirá como&lt;br /&gt;
parâmetro da chamada a System.@LStrSetLength (para alocar memória para&lt;br /&gt;
o conteúdo da string de resultado), como contador dos bytes a copiar, de&lt;br /&gt;
modo que esse valor também deve ser salvo, por exemplo, na variável "n":&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pdst: Pointer;&amp;nbsp; // Endereço da string resultado&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; src: PChar;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // String de origem&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; n: Integer;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Comprimento da string de origem&lt;br /&gt;
&amp;nbsp; asm&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // O endereço da string de resultado é passado em EDX.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Salvamos esse valor na variável pdst:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov pdst, edx&amp;nbsp;&amp;nbsp; // pdst := EDX;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Salvamos EAX (s) na variável local (src)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov src, eax&amp;nbsp;&amp;nbsp;&amp;nbsp; // src := EAX;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // n := Length(s);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@LStrLen&amp;nbsp;&amp;nbsp; // EAX :=&amp;nbsp; LStrLen(EAX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov n, eax&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // n := EAX;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;2) Alocar memória para a string convertida&lt;br /&gt;
------------------------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
A alocação é realizada através de uma chamada a System.@LStrSetLength.&lt;br /&gt;
O procedimento espera dois parâmetros: o endereço da string (que&lt;br /&gt;
salvamos em "pdst") e o comprimento da string (que está em EAX).&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // SetLength(pdst^, n);&amp;nbsp; // Alocar a string de resultado&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, eax&amp;nbsp; // EDX := n;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Segundo parâmetro p/LStrSetLength&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, pdst // EAX := pdst; // Primeiro parâmetro p/LStrSetLength&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; call System.@LStrSetLength&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; LStrSetLength(EAX, EDX);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;3) Copiar os caracteres um a um, convertidos para maiúsculas&lt;br /&gt;
------------------------------------------------------------&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Se o comprimento da string era zero, já terminamos:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if n = 0 then exit;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov ecx, n&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ECX := n;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; test ecx, ecx&amp;nbsp; // Fazer and de ECX com ECX para definir flags&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // (ECX inalterado)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jz @@end&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Ir para @@end se o flag zero está marcado (ECX=0)&lt;br /&gt;
&lt;br /&gt;
Não sendo esse o caso, devemos copiar os caracteres de uma string para&lt;br /&gt;
a outra, convertendo-os para maiúsculas conforme necessário. Nós vamos&lt;br /&gt;
utilizar ESI e EDX para apontar para os caracteres da string de origem&lt;br /&gt;
e destino respectivamente, AL para carregar os caracteres da string de&lt;br /&gt;
origem e realizar a mudança antes de armazená-los na string de destino e&lt;br /&gt;
ECX para controlar a instrução de LOOP que contará os caracteres. Já que&lt;br /&gt;
ESI é um registro que tem que ser preservado, devemos salvar seu valor&lt;br /&gt;
para restaurá-lo mais tarde. Decidi salvar ESI colocando-o na pilha.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; push esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Salve ESI na pilha&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Inicializar ESI e EDX&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov eax, pdst&amp;nbsp;&amp;nbsp;&amp;nbsp; // EAX := pdst;&amp;nbsp; // Endereço da string de resultado&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov esi, src&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ESI := src;&amp;nbsp;&amp;nbsp; // String de origem&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov edx, [eax]&amp;nbsp;&amp;nbsp; // EDX := pdst^; // String de resultado&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; @@cycle:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov al, [esi]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL := ESI^;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if Shortint(AL) &amp;lt; Shortint(Ord('a')) then goto @@nochange&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp al, 'a'&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; jl @@nochange&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL in ['a'..#127]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // if Byte(AL) &amp;gt; Byte(Ord('a')) then goto @@nochange&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmp al, 'z'&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ja @@nochange&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // AL in ['a'..'z']&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sub al, 'a'-'A'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Dec(AL, Ord('a')-Ord('A'));&lt;br /&gt;
&amp;nbsp; @@nochange:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; mov [edx], al&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // EDX^ := AL;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; inc esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Inc(ESI);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; inc edx&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Inc(EDX);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; loop @@cycle&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Dec(ECX); if ECX &amp;lt;&amp;gt; 0 then goto cycle&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; pop esi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Restaurar ESI da pilha&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; @@end:&lt;br /&gt;
&amp;nbsp; end;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/967430253837456983-1588777217374894306?l=blogprogramadores.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PKUCUES1YRQ-1_iidU6BGOw2qKc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PKUCUES1YRQ-1_iidU6BGOw2qKc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PKUCUES1YRQ-1_iidU6BGOw2qKc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PKUCUES1YRQ-1_iidU6BGOw2qKc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/Otim/~4/CfhyBmXOR2s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blogprogramadores.blogspot.com/feeds/1588777217374894306/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-1.html#comment-form" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/1588777217374894306?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/967430253837456983/posts/default/1588777217374894306?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/Otim/~3/CfhyBmXOR2s/delphi-com-assembly-parte-1.html" title="Delphi com assembly (Parte 1)" /><author><name>Jefferson</name><uri>http://www.blogger.com/profile/01446587263370792889</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/-Clf9dP-RRrI/TiG_gtauBQI/AAAAAAAAANo/B4KrOFzlIBs/s220/bleach-hollow-mask.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blogprogramadores.blogspot.com/2011/08/delphi-com-assembly-parte-1.html</feedburner:origLink></entry></feed>

