永不相信 發表於 2023-10-19 14:16:00

汇编语言

<h2 id="概述">概述</h2>
<p><strong>语言</strong></p>
<p><strong>进制</strong></p>
<p><strong>进制如何运算</strong></p>
<p><strong>二进制</strong></p>
<p><strong>数据宽度</strong></p>
<p><strong>有符号数和无符号数</strong></p>
<p><strong>原码反码补码</strong></p>
<p><strong>位运算</strong></p>
<p><strong>位运算计算</strong></p>
<p><strong>汇编</strong></p>
<p><strong>寄存器</strong></p>
<p><strong>内存</strong></p>
<p><strong>汇编指令</strong></p>
<p><strong>内存复制</strong></p>
<p><strong>堆栈的指令</strong></p>
<p><strong>汇编如何写函数</strong></p>
<p><strong>堆栈传参</strong></p>
<p><strong>堆栈平衡</strong></p>
<p><strong>外挂</strong></p>
<h2 id="机器语言">机器语言</h2>
<p>人和人沟通?语言!         学习计算机的语言</p>
<p><strong>什么是机器语言?</strong></p>
<pre><code class="language-bash">#我们目前主流的电子计算机!
状态: 0和1
#最早的程序员,穿孔卡带!
加01000000
减01001000
乘01001000   01001000
除01001000   11001000
</code></pre>
<p>这些复杂的机器语言,能简化吗?助记符!汇编语言! 人能够理解的语言转换成为机器能够理解的语言!</p>
<pre><code class="language-shell">加   INC-编译器-&gt;01000000
减   DEC-编译器-&gt;01001000
乘   MUL-编译器-&gt;0100100001001000
除   DIV-编译器-&gt;0100100011001000
</code></pre>
<p>离程序的本质:隔阂!   汇编一般用于底层的编写,单片机...</p>
<p><strong>C语言</strong></p>
<pre><code class="language-shell">加A+B-编译器-&gt;01000000
减A-B-编译器-&gt;01001000
乘A*B-编译器-&gt;0100100001001000
除A/B-编译器-&gt;0100100011001000
</code></pre>
<p><img alt="1678848653159" loading="lazy"></p>
<p><img alt="1678849759581" loading="lazy"></p>
<h2 id="进制">进制</h2>
<p><strong>二进制</strong>   01</p>
<p><strong>学习进制的障碍?</strong></p>
<p>10进制!<br>
人类天然的选择的就是10进制,10个指头。跳出固有思维的方法! "屈指可数"</p>
<p><strong>二进制</strong></p>
<p>思想:每一种进制都是完美的,都有自己的计算方式!</p>
<p><strong>进制?</strong></p>
<p>1进制:一进一, 结绳记事。 1   1</p>
<p>2进制: 二进制,计算机</p>
<p>八进制:八进一。8个符号组成:012345 6 7</p>
<p>10进制:10进一。 10个符号组成: 0123 4 5 6 7 8 9</p>
<p>16进制:16进一。 16个符号组成: 0123 4 5 6 7 8 9 a b c d e f</p>
<p>进制远远没有大家想的那么复杂。<strong>查数</strong></p>
<blockquote>
<p>测试</p>
</blockquote>
<pre><code class="language-shell">#一进制
1
1 1
1 1 1
1 1 1 1
.....

# 三进制1~20
十进制:01345678910
三进制: 012 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122
#二进制
      0110111001101111000


#七进制1~20
01   23   456
10111212141516
20212223242526
</code></pre>
<p>问题:你真的理解进制了吗? 1 + 1 = 3 对吗?! 如果你可以使用进制来解答这个问题,那么你就学会了!</p>
<p>十进制: 01234567 89</p>
<p>狂神的十进制: 02   479e gs   fq,可以自己随便定义的,学习,创造者!</p>
<p>加密解密: 程序员,破解程序的人!<strong>进制的加密</strong></p>
<p>数字量一大,总是有规律的!</p>
<h2 id="进制怎么运算">进制怎么运算</h2>
<pre><code class="language-shell">#八进制计算下面的结果
2+3=5
2*3=6
4+5=11
4*5=24

#运算的额本质就是查数
012345671011   1213141516172021222324252627

# 八进制计算下面的结果   
277+333 = 632
276*54 =20250
237-54 = 163
234/4 = 47

</code></pre>
<p><strong>八进制乘法表</strong></p>
<table>
<thead>
<tr>
<th>1*1=1</th>
<th>1*2=2</th>
<th>1*3=3</th>
<th>1*4=4</th>
<th>1*5=5</th>
<th>1*6=6</th>
<th>1*7=7</th>
</tr>
</thead>
<tbody>
<tr>
<td>2*2=4</td>
<td>2*3=6</td>
<td>2*4=10</td>
<td>2*5=12</td>
<td>2*6=14</td>
<td>2*7=16</td>
<td></td>
</tr>
<tr>
<td>3*3=11</td>
<td>3*4=14</td>
<td>3*5=17</td>
<td>3*6=22</td>
<td>3*7=25</td>
<td></td>
<td></td>
</tr>
<tr>
<td>4*4=20</td>
<td>4*5=24</td>
<td>4*6=30</td>
<td>4*7=34</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>5*5=31</td>
<td>5*6=36</td>
<td>5*7=43</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>6*6=44</td>
<td>6*7=52</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>7*7=61</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><strong>八进制加法表</strong></p>
<table>
<thead>
<tr>
<th>1+1=2</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>1+2=3</td>
<td>2+2=4</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1+3=4</td>
<td>2+3=5</td>
<td>3+3=6</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1+4=5</td>
<td>2+4=6</td>
<td>3+4=7</td>
<td>4+4=10</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1+5=6</td>
<td>2+5=7</td>
<td>3+5=10</td>
<td>4+5=11</td>
<td>5+5=12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>1+6=7</td>
<td>2+6=10</td>
<td>3+6=11</td>
<td>4+6=12</td>
<td>5+6=13</td>
<td>6+6=14</td>
<td></td>
</tr>
<tr>
<td>1+7=10</td>
<td>2+7=11</td>
<td>3+7=12</td>
<td>4+7=13</td>
<td>5+7=14</td>
<td>6+7=15</td>
<td>7+7=16</td>
</tr>
</tbody>
</table>
<pre><code class="language-shell">#运算的本质就是查数

   277
+333
--------
   632
   
   
    276
*    54
----------
   1370
+ 1666
----------
20250


# 减法的本质其实就是加法!   237-54 = 237 + (-54)
---------
# 除法的本质,除数乘以那个数最接近结果即可!
234
4
-------
47

</code></pre>
<p><strong>结论:无论是什么进制,本身都是有一套完美的运算体系的,我们都可以通过列表的方式将他计算出来!</strong></p>
<h2 id="二进制">二进制</h2>
<p>计算机使用二进制 01!状态!电子!   物理极限:摩尔定律!硬操作! 追求语言的极限!并发语言!软操作!</p>
<p><strong>量子计算机:</strong></p>
<p>可以实现量子计算的机器</p>
<p>传统的计算机:集成电路!01。硅晶片</p>
<p>量子计算机的单位:昆比特。 (量子比特!) 量子的两态来表示。</p>
<p>光子:正交偏振方向。</p>
<p>磁场:电子的自旋方向。</p>
<p>21世纪。计算力。 快到尽头了!【落伍】本质问题!</p>
<p>量子计算机!提高计算机的计算力。</p>
<p>量子比特、量子叠加态、量子纠缠、量子并行原理....</p>
<p>2019年,Google研究人员展示其最新54比特量子计算机,该计算机只用200秒便可计算完毕当前世界最大的超级计算机需1万年进行的运算。</p>
<p>2020年,6.18、量子体积64的量子计算机!!</p>
<p>霍尼韦尔华还表示,将在一年之内得到至少10个有效量比特,相当于1024个量子体积。量产!</p>
<p>自担自己算计 == 量子计算机!</p>
<p>回到我们的电子计算机! 01!</p>
<pre><code class="language-shell">二进制:
01101110010111011110001001101010111100110111101111
</code></pre>
<p>二进制这么写很麻烦!二进制能否简写!</p>
<pre><code class="language-shell">012   3   4    5   6    7   8    9         a      b   c   d   e   f
</code></pre>
<p>这就是我们的16进制。</p>
<p><strong>课程上的教学!2进制转换为10进制。然后计算</strong></p>
<p><strong>为什么要学习理解二进制?</strong></p>
<p>寄存器、内存、位!底层的每一个位都是有含义的。汇编入门理解的基础!</p>
<p>汇编高级:了解程序的深层! 操作系统的内核?</p>
<h2 id="数据宽度">数据宽度</h2>
<p>计算机: 内存! 给数据增加数据宽度。</p>
<p><img alt="1678954481437" loading="lazy"></p>
<p>C和C++Java都需要定于数据的类型。计算机底层需要我们给这些数据定义宽度。</p>
<p>位   0    1</p>
<p>字节   0~0xFF</p>
<p>字   0~0xFFFF</p>
<p>双字   0~0xFFFFFFFF</p>
<p>在计算机中,每一个数据都需要给它定义类型。给他定义宽度。在内存中的宽度。</p>
<h2 id="有符号数无符号数">有符号数无符号数</h2>
<p>数据都是有宽度的。每个数据代表什么意思呢?,二进制</p>
<pre><code class="language-shell">0 1 0 1 0 1 0 1
</code></pre>
<p><strong>规则,二进制解码增加一个规则?</strong></p>
<p><strong>无符号数规则</strong></p>
<p>你这数字是什么,那就是什么。</p>
<pre><code class="language-shell">1 0 0 11 0 1 0十六进制: 0x9A   十进制154
</code></pre>
<p>有符号数规则</p>
<p>最高位是符号位:1(负数)   0(正数)</p>
<pre><code class="language-shell">1 0 0 11 0 1 0
</code></pre>
<h2 id="原码反码补码">原码反码补码</h2>
<p>之后用它来计算</p>
<p>编码规则</p>
<p>有符号数的编码规则</p>
<p>原码:最高位符号位,对齐它的位进行本身绝对值即可。</p>
<p>反码:</p>
<ul>
<li>正数:反码和原码相同</li>
<li>负数:符号位一定是1,其余位对原码取反。</li>
</ul>
<p>补码:</p>
<ul>
<li>正数:补码和原码相同</li>
<li>负数:符号位一定是1,反码+1</li>
</ul>
<blockquote>
<p>测试</p>
</blockquote>
<pre><code class="language-shell"># 现在这些都是8位
# 如果是正数,那都是一样的。
1
# 原码0 0 0 00 0 0 1
# 反码0 0 0 00 0 0 1
# 补码0 0 0 00 0 0 1


# 现在这些都是8位
# 如果是负数
-1
# 原码1 0 0 00 0 0 1
# 反码1 1 1 11 1 1 0
# 补码1 1 1 11 1 1 1
-7
# 原码1 0 0 00 1 1 1
# 反码1 1 1 11 0 0 0
# 补码1 1 1 11 0 0 1
</code></pre>
<p><strong>如果看到一个数字,二进制,需要了解他是有符号数还是无符号数</strong></p>
<p>寄存器: mov寄存器,值</p>
<p><img alt="1679019093134" loading="lazy"></p>
<p><img alt="1679019136419" loading="lazy"></p>
<h2 id="位运算">位运算</h2>
<p>计算机现在可以存储所有的数字(整数,浮点数,字符)的,运算。</p>
<p>01</p>
<p><strong>位运算?</strong></p>
<p>2*8最高效的计算方式?</p>
<p>很多底层的调试器。需要通过位来判断CPU的状态</p>
<p><strong>与运算(and&amp;)</strong></p>
<p>计算机的本质。</p>
<p><img alt="1679019741743" loading="lazy"></p>
<pre><code class="language-shell">1011 0001
1101 1000
------------与运算
1001 0000
</code></pre>
<p><strong>或运算(or| )</strong></p>
<p><img alt="1679019977055" loading="lazy"></p>
<pre><code class="language-shell">1011 0001
1101 1000
----------   或运算
1111 1001
</code></pre>
<p><strong>异或运算(xor   ^)</strong></p>
<p>不一样就是 1</p>
<p><img alt="1679020201398" loading="lazy"></p>
<pre><code class="language-shell">1011 0001
1101 1000
----------   异或运算
0110 1001
</code></pre>
<p><strong>非运算(单目运算符 not~)</strong></p>
<p>0就是1,1就是0,取反!</p>
<pre><code class="language-shell">11011000
-------------
00100111
</code></pre>
<p>通过这些可以完成加减乘除!</p>
<p><strong>位运算(移动位)</strong></p>
<p><strong>左移:(shl &lt;&lt;)</strong></p>
<pre><code class="language-shell">0000 0001@ 所有二进制全部左移若干位,高位就丢弃了,低位补0
0000 0010
</code></pre>
<p><strong>右移:(shr &gt;&gt;)</strong></p>
<pre><code class="language-shell">0000 0001   @ 所有二进制位全部右移若干位,低位就丢弃了,高位就需要补0,1(符号位决定。)
0000 0000

int a = 10;
printf("%d\n",a&gt;&gt;2);
</code></pre>
<p>二进制、位运算=&gt; 加减乘除</p>
<h2 id="位运算的加减乘除">位运算的加减乘除</h2>
<p>计算机只认识01</p>
<p>基本数学是建立在 加减乘除。 (加法)</p>
<p><strong>4+5?</strong></p>
<pre><code class="language-shell"># 计算机是怎么操作的!
00000100
00000101
------------ (加法:计算机是不会直接加的)
00001001

# 计算机的实现原理

# 第一步:异或: 如果不考虑进位,异或就可以直接出结果。
00000100
00000101
-----------
00000001

# 第二步:与运算(判断进位,如果与运算结果为0,没有进位。)
00000100
00000101
-----------
00000100

# 第三步:将与运算的结果,左移一位。00001000# 进位的结果

# 第四步:异或!
00000001
00001000
-------------
00001001


# 第五步:与运算(判断进位,如果与运算结果为0,没有进位。)
00000001
00001000
-----------
00000000

# 所以最终的结果就是与运算为0 的结果的上一个异或运算。
4+ 5 = 9
0000 0100 + 0000 0101 = 0000 1001 = 9
</code></pre>
<p><strong>4-5?</strong></p>
<pre><code class="language-shell"># 计算机是怎么操作的!
4+(-5)

00000100
11111011
------------ (减法:计算机是不会直接减的)
11111111   

00000100
11111011
-----------异或(如果不考虑进位,异或就可以直接出结果。)
11111111


00000100
11111011
------------   与(判断进位,如果与运算结果为0,没有进位。)
00000000

最终结果1111111116 ff    10-1
</code></pre>
<p>乘: x*y ,就是y个x相加,还是加法</p>
<p>除: x/y,   本质就是减法,就是X能耐减去多少个Y。</p>
<p><strong>计算机只会做加法!</strong></p>
<p>机器语言就是位运算。都是电路来实现的。这就是计算机的最底层的本质。</p>
<p>通过机器语言来实现加法计算器。设计电路</p>
<h2 id="汇编语言环境说明">汇编语言环境说明</h2>
<p>通过指令来替代我们的二进制编码!</p>
<p><img alt="1679034185130" loading="lazy"></p>
<p>通过汇编指令可以给计算机发一些操作,然后让计算机执行。编译器的发展,底层的大佬,几乎都是最原始的IDE。</p>
<p>在学习汇编之前,大家需要先掌握环境的配置(1、Vc6 (程序到汇编的理解),2、OD!3、抓包工具 4、加密解密工具)</p>
<p><strong>学汇编不是为了写代码</strong></p>
<p>理解程序的本质。</p>
<p><img alt="1679034664443" loading="lazy"></p>
<p>《汇编语言》16位的汇编32位   64位(本质架构区别不大,寻址能力增加。)</p>
<p>建议大家可以直接学习32位汇编!</p>
<p>汇编入门:了解汇编和程序的对应关系,程序的本质即可!</p>
<p><img alt="1679034962295" loading="lazy"></p>
<h2 id="通用寄存器">通用寄存器</h2>
<p>寄存器:</p>
<p>存储数据:CPU&gt;内存&gt;硬盘</p>
<p>32位 CPU   81632</p>
<p>64位 CPU   8163264</p>
<p><strong>通用寄存器,可以存储任意的东西</strong></p>
<pre><code class="language-shell">#32位的通用寄存器只有8个
</code></pre>
<p>​        <img alt="1679036811339" loading="lazy"></p>
<p>存值的范围 0~FFFFFFFF</p>
<p>对于二进制来说,直接修改值</p>
<p><strong>计算机如果像寄存器存值</strong></p>
<p><strong>mov指令</strong></p>
<pre><code class="language-shell">mov 存的地址,存的数
mov 存的地址1,存的地址1
</code></pre>
<p><img alt="1679037043188" loading="lazy"></p>
<p>可以将数字写入到寄存器,可以将寄存器中的值写到寄存器。</p>
<p>计算机:计算力!</p>
<p><strong>不同的寄存器</strong></p>
<pre><code class="language-shell">32位      16位   8位
EAX       AX       AL
ECX       CX       CL
EDX       DX       DL
EBX       BX       BL
ESP       SP       AH
ENP       NP       CH
ESI       SI       DH
EDI       DI       BH
</code></pre>
<p>8位:L低8位,H高8位</p>
<p><img alt="1679039303691" loading="lazy"></p>
<p>除了这些通用寄存器之外,那么其他的寄存器每一位都有自己特定的功能</p>
<h2 id="内存">内存</h2>
<p>寄存器很小,不够用。所以说,数据放在内存!</p>
<p>平时买的内存条</p>
<p>每个应用程序进程都有4GB的内存空间,空头支票,</p>
<p><img alt="1679039595285" loading="lazy"></p>
<p>程序真正运行的时候,才会用到物理内存。</p>
<p>1B = 8bit</p>
<p>1KB -= 1024B</p>
<p>1MB = 1024KB</p>
<p>1GB = 1024MB</p>
<p>4G的内存,4096m =&gt; 最终计算为位,就是这个可以存储的最大容量的。</p>
<p>计算机中内存地址很多,空间很大。</p>
<p><strong>内存地址</strong></p>
<p>存一个数:占用的大小,数据宽度!存在哪里?</p>
<p>计算机中内存地址很多,空间很大,每个空间分配一个地址,名字。</p>
<p><img alt="1679040205851" loading="lazy"></p>
<p>这些给内存起的编号,就是我们的内存地址。32位   8个 16进制的值</p>
<p>32位:寻址能力!4GB</p>
<p>FFFFFFFF + 1 = 100000000,最大的值。</p>
<p>位是怎么限制内存大小的。</p>
<p>100000000 内存地址 * 8 = 位:800000000</p>
<p>转换为10进制/8;4,294,967,296字节</p>
<p>按照规则/1024,最终发现就是4GB</p>
<p>所以每个内存地址都有一个编号!可以通过这些编号向里面存值!</p>
<p>​        <img alt="1679040553368" loading="lazy"></p>
<p>内存如何存值?</p>
<p>数据宽度:byteworddword</p>
<p>地址的位置: 0xFFFFFFFF</p>
<p>不是任意的地址都可以写东西的,申请使用的。只有程序申请过的内存地址我们才可以使用。</p>
<pre><code class="language-shell">汇编如何向内存中写值
mov数据宽度内存地址 , 1

movbyteptrds:,1

传递的值的大小一定要和数据宽度相等
</code></pre>
<p><img alt="1679040862600" loading="lazy"></p>
<p><strong>内存地址有多种写法</strong></p>
<p>ds: 内存地址偏移</p>
<p>ds:寄存器</p>
<p>ds: 寄存器偏移</p>
<p>数组[ ]</p>
<p>ds:数组</p>
<p>ds:偏移</p><br><br>
来源:https://www.cnblogs.com/ztyniubi/p/17774607.html
頁: [1]
查看完整版本: 汇编语言