汇编先导课笔记
一、概述
- 语言
- 进制
- 进制如何运算
- 二进制
- 数据宽度
- 有符号数和无符号数
- 原码反码补码
- 位运算
- 位运算计算
- 汇编
- 寄存器
- 内存
- 汇编指令
- 内存复制
- 堆栈的指令
- 汇编如何写函数
- 堆栈传参
- 堆栈平衡
- 外挂
二、为什么要学汇编语言
-
语言
- 人和人沟通就是通过语言,人和计算机交流就需要计算机的语言。
-
机器语言:
# 我们目前主流的电子计算机 0和1 电路有通断,代表两种状态 # 最早的程序员:穿孔卡带!都是通过0101来个状态来进行编程 要解决的基本问题:加减乘除,本质上都是加的问题,加减乘除就是一堆01组成的命令 加:假设为0100 0000 减:假设为0100 1000 乘:假设为0100 1000 0100 1000 除:假设为0100 1000 1100 1000
- 这些复杂的机器语言,不方便记忆,因此助词符出现了,如加用INC,减用DEC,乘用MUL,除用DIV,这些助记符就是汇编语言,汇编语言可以直接操作计算机的底层,甚至是操作底层数据的位。
- 通过编译器,将人能理解的语言转化成计算机能理解的二进制语言。
加 INC -编译器-> 0100 0000 减 DEC 0100 1000 乘 MUL 0100 1000 0100 1000 除 DIV 0100 1000 1100 1000
- 因为有上面这层关系,所以离java等编写的程序的本质会有一个隔阂,也就是不知道程序的本质是怎么运行实现的。
- 汇编语言一般用于底层或单片机等的编写
-
C语言:汇编语言的进一步简化
加 A+B -编译器-> 0100 0000 减 A-B 0100 1000 乘 A*B 0100 1000 0100 1000 除 A/B 0100 1000 1100 1000
- 暴破(暴力破解 ):必须要弄懂底层的东西
三、进制的思想本质
- 二进制的本质是 0 1
- 学习进制的障碍:受10进制的传统思想禁锢,人类天然的选择就是10进制(10个手指,“屈指可数”),要跳出固有的思维方法。
- 进制
- 思想:每一种进制都是完美的,都有自己的计算方式
- 多种进制
- 1进制:一进一,结绳记事。1 1
- 2进制:二进一,计算机。0 1 10 11
- 8进制:八进一,8个符号组成 ,0 1 2 3 4 5 6 7
- 10进制:十进一,10个符号组成,0 1 2 3 4 5 6 7 8 9
- 16进制:十六进一,16个符号组成,0 1 2 3 4 5 6 7 8 9 a b c d e f
- 进制远远没有那么复杂,只要会查数就可以
测试
#一进制 1-20
1 11 111 1111...
#三进制 1-20
0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121
#七进制 1-20
0 1 2 3 4 5 6 10 11 12 13 14 15 16 20 21 22
#十进制 1-20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#二进制 1-20
0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111
#进制的本质就是一组符合,逢几进几
- 问题:1+1=3?
- 大众化的十进制: 0 1 2 3 4 5 6 7 8 9 10
- 十进制所用的符号可随便定义: 0 2 5 a t a s d 8 6 20,可以自己随便定义,要从学习转变成创作者
- 加密解密:程序员可以使用进制加密,破解程序会很麻烦,是一种高级加密,这种加密方式,数字量一大,总是有规律的。
四、进制的运算
#使用八进制计算下面的结果
2+3=5(2后移动3位)
2*3=6(=3+3)
4+5=11(4后移5位)
4*5=24(4后移动4个5,相当于5+5+5+5)
#运算的本质就是查数
0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26
#使用八进制计算下面的结果 九九乘法表=加法表 进位
277+333=632
276*54=20250
237-54=163
234/4=47
- 八进制乘法表
- 八进制加法表
#运算的本质就是查数
277
333 +
------
632
276
54 *
------
1370
1666 +
------
20250
#减法的本质就是加法
237
54 -
------
163
#除法的本质,除数乘以哪个数最接近结果即可
234 #2和4除不够除,先找谁*4最接近23,不能超过23
4 /
------
47
- 结论:无论是什么进制,本身都是有一套完美的运算体系,我们都可以通过列表的方式将它计算出来。
五、二进制
- 计算机使用二进制0 1,用不同的状态来表示,因为现在使用的电子计算机,用高低电平来表示0和1。
- 电子计算机有物理极限:摩尔定律(集成电路上可以容纳的晶体管数目在大约每经过18个月便会增加一倍),这种极限到头后,追求语言的极限,如并发语言(软操作)。
- 量子计算机:
- 可以实现量子计算的计算机。传统的计算机:通过集成电路来实现电路的通断,通过高低电平来表现出两个值0和1
- 量子计算机的单位:昆比特(量子比特)。量子的两态,还有一个叠加态。
- 量子计算机的核心要素是提高计算机的计算力
- 传统计算机中的二进制
#二进制 0-1111
0 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111
二进制这么去写很麻烦,二进制能否简写?
0 1 2 3 4 5 6 7 8 9 a b c d e f
这就是16进制出来了。
- 为什么要学二进制:
- 寄存器、内存、位,底层的每一个位都是有含义的。
- 汇编高级:了解程序的深层,操作系统的内核。
六、数据宽度
- 计算机内存中,任何的数据类型都是有宽度的,宽度就是表示这种数据类型的数据占多大的空间。
- c和c++ java都需要定义数据的类型,计算机底层需要我们给这些数据定义宽度。
位 0 1
字节 0-0xFF
字 0-0xFFFF
双字 0-0xFFFFFFFF
- 在计算机中,每个数据都需要给它定义类型。目的就是给它定义宽度,在内存中的宽度。
七、有符号数和无符号数
-
数据都是有宽度的,每个数据代表什么意思,需要设定规则,如mp3播放需要mp3的解码规则等
-
二进制数也需要解码,也需要规则。
-
无符号数规则
- 数字是什么,那就是什么
1 0 0 1 1 0 1 0 十六进制:0x9A 十进制:154
-
有符号数规则
- 最高位是符号位:1(负数) 0(正数)
- 那数据是多少是如何转换的,就需要用到原码反码和补码。
八、原码反码补码
-
有符号数的编码规则
-
原码:最高位是符号位,对其他位进行本身绝对值即可。
-
反码:
- 正数:反码和原码相同
- 负数:符号位一定是1,其他位对原码取反
-
补码:
- 正数:补码和原码相同
- 负数:符号位一定是1,其他位+1
测试
#针对的是8位数
#如果是正数,都是一样的
1
#原码:0000 0001
#反码:0000 0001
#补码:0000 0001
-1
#原码:1000 0001
#反码:1111 1110
#补码:1111 1111
-7
#原码:1000 0111
#反码:1111 1000
#补码:1111 1001
#如果看到一个数字,二进制的,需要了解它是胡符号数还是无符号数
九、位运算的理解
-
寄存器:存值的,比内存的速度要快,mov指令可以往寄存器中存值
-
计算机中的负数是用补码的方式存储的
-
位运算:
-
2*8的最高效的运算方式 :
- 2 << 3 或者 8 << 1
2 << 3 即 2 左移 3 位
系统中运算是二进制,左移一位即乘2
- 2 << 3 或者 8 << 1
-
很多底层的调度器。需要通过位来判断CPU的状态。
-
与运算(and &):
- 计算机的本质
-
1011 0001 1101 1000 --------------与运算 1001 0000
-
或运算(or |)
-
1011 0001 1101 1000 --------------或运算 1111 1001
-
-
异或运算(xor ^)
-
不一样就是1,如01=1,11=0
-
1011 0001 1101 1000 --------------异或运算 0110 1001
-
-
非运算(单目运算符 not ~)
-
0就是1,1就是0,取反
-
1101 1000 ------------取反 0010 0111
-
-
位运算(移动位):
二进制 十进制->左移*2,右移/2 0000 0001 1 0000 0010 2 0000 0100 4 0000 1000 8
- 左移:(shl <<)
0000 0001 #所有二进制位全部左移若干位,高位就丢弃,低位补零 0000 0010
- 右移:(shr >>)
0000 0001 #所有二进制位全部右移若干位,低位就丢弃,高位补0或1(符号位决定) 0000 0000
-
通过上面的位运算来实现加减乘除
-
十、位运算的加减乘除
-
计算机只认识0 1
-
基本数学是建立在 加减乘除上的,主要是加法。
# 4+5
0000 0100
0000 0101
--------------加(计算机不会直接加,只懂得与或非和异或运算)
0000 1001
#计算机的实现原理
#第一步:异或,不考虑进位,异或就可以直接出结果
0000 0100
0000 0101
--------------异或
0000 0001
#第二步:与运算(判断进位,如果与运算的结果都为0,则没有进位;如果不为0.则代表当前位需要进位)
0000 0100
0000 0101
--------------与
0000 0100 #1处需要进位
#第三步:将与运算的结果左移一位,就是进位的结果。
0000 0100
--------------<
0000 1000
#第四步:将第一的结果和第三步的结果异或
0000 0001
0000 1000
--------------异或
0000 1001
#第五步:与运算,将第一的结果和第三步的结果在进行与运算 (判断是否有进位,为0,则最终结果就是上面的结果)
0000 0001
0000 1000
--------------与
0000 0000
#所以最终结果就是0000 1001
# 4-5=4+(-5) -5用补码来表示=1111 1011(取反加一)
0000 0100
1111 1011
--------------加(计算机不会直接加,只懂得与或非和异或运算)
1111 1111
#计算机的实现原理
#第一步:异或,不考虑进位,异或就可以直接出结果
0000 0100
1111 1011
--------------异或
1111 1111
#第二步:与运算(判断进位,如果与运算的结果都为0,则没有进位;如果不为0.则代表当前位需要进位)
0000 0100
1111 1011
--------------与
0000 0000 #无进位
#所以最终结果就是1111 1111
- 乘:x*y,就是y个x相加
- 除:x/y,就是x能减去多少个y
- 计算机只会做加法
十一、汇编学习环境
-
从零开始设计一套进制规则,自己设计电路,来实现加减乘除,10进制和2进制的转换。
-
机器语言就是位运算。都是电路来实现的,这就是计算机最底层的本质。
-
通过机器语言来实现加法计算器。设计电路
-
汇编语言
- 就是通过指令来代替我们的二进制编码,如可以通过add指令来表示一堆的二进制操作
-
通过汇编指令可以给计算机发一些操作,然后让计算机执行(通过编译器)。
-
编译器的发展,学习底层,用越原始的ide越好
- VC6.0(c语言,程序到汇编的过程)
- OD(反汇编工具)
- 抓包工具
- 加密解密工具
-
学汇编不是为了写代码,而是为了理解程序的本质
- 16位的汇编、32位和64位的汇编
- 32和64位本质架构区别不大,寻址能力增加
- 汇编入门:要了解汇编和程序的对应关系
十二、通用寄存器
-
寄存器:cpu中有寄存器
-
存储数据:CPU>内存>硬盘
-
32位 CPU ,支持8位 、16位、 32位的寄存器
-
64位 CPU,支持8位 、16位、 32位、64位的寄存器
-
位代表的是寻址能力
-
-
通用寄存器,可以存储任何的值
# 32位cpu中的通用寄存器只有8个
# 存值范围都是从0~FFFF FFFF,FF=1111 1111,8个F就是4个8位,就是32位
-
对于二进制来说,直接修改值
-
对于汇编,计算机如何往寄存器存值
- 使用mov指令
- 可以将数字写入到寄存器,也可以将寄存器的值写入到寄存器。
mov 存的地址,存的数 mov 存的地址1,存的地址2
- 使用mov指令
-
计算机的本质就是计算力
-
不同的寄存器
FFFF FFFF FFFF FF
32位 16位 8位
EAX AX AL
ECX CX CL
EDX DX DL
EBX BX BL
ESP SP AH
EBP BP CH
ESI SI DH
EDI DI BH
#8位:L代表低8位,H代表高8位,两个8位合成一个16位
- 除了这些通用寄存器之外,那么其他的寄存器每一位都有自己特定的功能,如开机关机
十三、内存
- 寄存器很小,不够用。所以说,数据放到内存(就是平时所说的内存条)中。
- 每个应用程序进程都有4GB的内存空间。2G的内存可以跑4G的程序,这里就要用到虚拟内存。
- 程序真正运行的时候,才会用到物理内存
- 换算
- 1B=8bit
- 1KB=1024B
- 1MB=1024KB
- 1GB=1024MB
- 4G的内存,4096M=>最终计算为位,就是这个内存可以存储的最大容量,目前的内存条一般是按10进制来换算的,也就是4G达不到4096M
- 计算机中内存地址很多,空间很大。
- 存一个数:先考虑占用的大小 (数据宽度),一个byte是1个字节(8b),一个WORD是一个字(16位),一个DWORD是一个双字(32位);
- 内存地址是解决数据要存到哪里的。我们为每个空间分配一个地址,也就是取一个名字,8位代表一个字节,取一个内存地址名称,从0x0000 0000-0xFFFF FFFF,这些给内存起的名字,就是我们的内存地址。
- 32位,cpu与主内存32条线路连接,每条线路有0和1两种信号 ,总共可以形成2的32次方个寄存器地址,每个 寄存器单元8bit,就是8个16进制的值,一个F对应一个1111,所以32位的cpu最大的寻址能力就是FFFF FFFF+1=10000 0000(0000 0000也是一个数),换成10进制就是42 9496 7296*8字节/8=419 4304千字节/1024=4,096兆字节/1024=4G字节,因此32位CPU最大的内存也就用到4G,在多了就过剩。
- 如果是64位,就是0000 0000 0000 0000-FFFF FFFF FFFF FFFF,理论上支持很大的内存寻址,无上限
-
汇编如何向内存中写值
-
数据宽度 byte word(2个字节) dword(4个字节) qword(8个字节64位)
-
地址的位置:0x0000 0111等
-
mov 数据宽度 ptr ds:[内存地址],写入的值# ptr:Pointer Record 内存地址有多种写法 [0x11110f70]:经典写法 [0x11110f70+4]:偏移量写法 [eax]:寄存器写法,指的是eax寄存器中的值所对应的内存地址 [eax+4]:寄存器偏移量写法 数组[]如何开辟空间 [reg+reg*{1,2,3,4}]#reg代表寄存器 [reg+reg*{1,2,3,4}+4]#reg代表寄存器,数组的偏移量
-
不是任意的地址都可以写东西的,只有程序申请使用的内存地址才能写。
-
本文来自博客园,作者:一只快乐的小67,转载请注明原文链接:https://www.cnblogs.com/sp520/p/16387980.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!