挑战1周实现汇编百例
汇编基础
什么是机器指令?
是二进制语言吗?还是十六进制
机器指令由谁执行?
cpu
机器指令和汇编指令有什么关系?
通过编译器(翻译软件),汇编指令可以翻译成机器指令
什么是伪指令?
告诉翻译软件,制定翻译规则
汇编指令存放在哪?
内存中
内存编号为什么是073F:02CE
这样的形式?
内存编号为什么是从0开始的
DOSBOX -debug -u/-d
u指令是 机器指令和汇编指令
d指令是 数据
汇编资料
对于初学者来说,以下是一些推荐的汇编语言编程实验案例和资料,这些资源可以帮助初学者通过实践来理解和学习汇编语言的基本概念和技巧:
1. **汇编语言27个经典案例**:
- 这篇文章提供了适合初学者的汇编语言经典案例,包括判断闰年程序、产生随机数并运算的程序、计算平台长度程序、加减乘除四则运算等。
- [CSDN 博客链接](https://blog.csdn.net/aasd23/article/details/124782182)
2. **汇编语言基础学习以及各种指令记忆**:
- 这篇文章介绍了汇编语言的基础知识和各种指令,适合初学者学习和记忆。
- [CSDN 博客链接](https://blog.csdn.net/anuo5680/article/details/101272355)
3. **给单片机初学者的几点建议**:
- 这篇文章为想要学习单片机汇编语言的初学者提供了一些实用的建议和指导。
- [EEWORLD 论坛链接](https://bbs.eeworld.com.cn/thread-51410-1-1.html)
4. **初学者到底是应该先学C还是汇编?**:
- 这篇讨论为初学者提供了学习编程语言的顺序建议,包括汇编语言的学习。
- [电子发烧友论坛链接](https://bbs.elecfans.com/jishu_2038095_1_1.html)
5. **汇编语言 - 资料下载**:
- 这个网站提供了汇编语言的资料下载,包括书籍和源代码,适合初学者。
- [硬件研发网链接](https://www.91hardware.com/dl/644)
6. **我想单片机汇编语言入门,应该怎么做呢?**:
- 这篇文章为初学者提供了学习单片机汇编语言的步骤和建议。
- [EEWORLD 论坛链接](http://bbs.eeworld.com.cn/thread-1277217-1-1.html)
7. **底层之旅:汇编语言探秘**:
- 这篇文章为初学者和有编程经验的开发者介绍了汇编语言的基础知识。
- [腾讯云开发者社区链接](https://cloud.tencent.com/developer/article/2338800)
8. **64位汇编语言的书**:
- 这篇文章推荐了一些适合初学者入门的64位汇编语言教材。
- [掘金链接](https://juejin.cn/s/64%E4%BD%8D%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E7%9A%84%E4%B9%A6)
9. **新书推荐| 汇编语言上机指导(微课版)**:
- 这本书以上机操作为驱动,通过上机实验详细介绍程序的调试过程,适合初学者。
- [搜狐链接](https://www.sohu.com/a/675935613_453160)
10. **汇编语言程序设计(第3版)小说作品大全**:
- 这本书主要阐述了汇编语言程序设计的知识,适合作为教材或自学教材。
- [起点中文网链接](https://www.qidian.com/soushu/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%EF%BC%88%E7%AC%AC3%E7%89%88%EF%BC%89.html)
这些资源可以帮助初学者通过理论学习和实践操作来掌握汇编语言的基本技能。在学习过程中,建议结合实际的编程练习,以加深理解和记忆。
以下是一些适合初学者的汇编语言中文实验案例和中文资料,这些资源可以帮助你学习和实践汇编语言:
1. **关于汇编语言入门的几个案例**:
- 提供了适合初学者的汇编语言编程案例,包括判断闰年程序、产生随机数并运算的程序等。
- [CSDN 博客链接](https://blog.csdn.net/aasd23/article/details/124782182)
2. **汇编语言范例_汇编例程**:
- 汇编语言的27个经典案例,适合初学者练习。
- [CSDN 博客链接](https://blog.csdn.net/qq_32783703/article/details/125359330)
3. **汇编语言程序设计案例式实验指导**:
- 一本书,全书共分5章,包括基础性实验和案例式实验指导。
- [百度百科链接](https://baike.baidu.com/item/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E6%A1%88%E4%BE%8B%E5%BC%8F%E5%AE%9E%E9%AA%8C%E6%8C%87%E5%AF%BC/12060751)
4. **Aurix/Tricore实验分享之四十九: Tricore 1.6汇编语言1**:
- 分享了关于 Tricore 1.6 汇编语言的实验。
- [Infineon 社区博客链接](https://community.infineon.com/t5/%E5%8D%9A%E5%AE%A2/Aurix-Tricore%E5%AE%9E%E9%AA%8C%E5%88%86%E4%BA%AB%E4%B9%8B%E5%9B%9B%E5%8D%81%E4%B9%9D-Tricore-1-6%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%801/ba-p/578616)
5. **汇编语言课程设计案例精编**:
- 提供了一些汇编语言课程设计案例,帮助学生深入理解计算机工作原理。
- [掘金链接](https://juejin.cn/s/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1%E6%A1%88%E4%BE%8B%E7%B2%BE%E7%BC%96)
6. **汇编语言跨专业实验一**:
- 介绍了一系列汇编语言的实验项目和考核方式。
- [Scribd 链接](https://www.scribd.com/presentation/721475345/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E8%B7%A8%E4%B8%93%E4%B8%9A%E5%AE%9E%E9%AA%8C%E4%B8%80)
7. **AT89C51汇编语言例子大全**:
- 提供了多个关于 AT89C51 单片机的汇编语言实验案例。
- [电子发烧友链接](https://m.elecfans.com/article/322833.html)
8. **汇编语言程序设计实验指导及习题集**:
- 一本实验指导书,包含了汇编语言的实验指导和习题集。
- [云商汇链接](http://1646.yunshow.com/htmlys/skj/2008/0515/goods_book_22314.html)
9. **编程语言程序设计(Professional Assembly Language) PDF**:
- 一本书,向使用高级语言的程序员讲解编译器如何从 C 和 C++ 程序创建汇编语言例程。
- [脚本之家链接](https://m.jb51.net/books/163007.html)
10. **Assembly Language and Microcomputer Interfacing**:
- 课程资料,包含汇编语言与微机接口的教学内容。
- [江苏大学计算机科学与通信工程学院链接](https://cs.ujs.edu.cn/AssemblyLanguageandMicrocomputerInterfacingProjectCH.doc)
常见汇编语言指令
1. **数据传输指令**:
- `MOV`:将数据从源操作数传输到目标操作数。
- `PUSH`:将数据压入堆栈。
- `POP`:从堆栈中弹出数据。
2. **算术运算指令**:
- `ADD`:将两个操作数相加。
- `SUB`:从一个操作数中减去另一个操作数。
- `MUL`:将两个操作数相乘。
- `DIV`:将一个操作数除以另一个操作数。
3. **逻辑运算指令**:
- `AND`:对两个操作数进行逻辑与操作。
- `OR`:对两个操作数进行逻辑或操作。
- `XOR`:对两个操作数进行逻辑异或操作。
- `NOT`:对操作数进行逻辑非操作。
4. **控制流指令**:
- `JMP`:无条件跳转到指定的地址。
- `JE`(或 `JZ`):如果等于(或零)则跳转。
- `JNE`(或 `JNZ`):如果不等于(或非零)则跳转。
- `CALL`:调用子程序。保存IP,跳转
- `RET`:从子程序返回。
5. **字符串处理指令**:
- `MOVS`:移动字符串。
- `CMPS`:比较字符串。
- `SCAS`:扫描字符串。
6. **位操作指令**:
- `SHL`:逻辑左移。
- `SHR`:逻辑右移。
- `ROL`:循环左移。
- `ROR`:循环右移。
为了更全面地了解汇编语言的指令集,你可以参考以下资料:
- [汇编语言之常见的汇编指令 - CSDN博客](https://blog.csdn.net/u011068702/article/details/53011181)
- [汇编指令入门级整理 - CSDN博客](https://blog.csdn.net/albertsh/article/details/106041560)
- [ARM 中常用的汇编指令解释汇总 - 咸鱼书生](https://www.cnblogs.com/FireLife-Cheng/p/18021537)
- [汇编语言--x86汇编指令集大全 - 知乎专栏](https://zhuanlan.zhihu.com/p/53394807)
- [汇编语言之常见的汇编指令 - 阿里云开发者社区](https://developer.aliyun.com/article/834230)
这些资料将帮助你更好地理解汇编语言的指令和它们的用法。
数据寄存器
在 DOS 操作系统下的 debug
工具中,-a
, -r
, -t
是三个常用的命令,它们的含义和作用如下:
-
-a (Assemble):
-a
命令用于进入汇编模式,允许用户在内存中的指定位置输入汇编指令。- 使用
-a
后,你可以直接键入汇编语句,debug
会将其转换成机器码并存储在内存中。 - 例如,
-a 100
命令会从内存地址0100
开始,让用户输入汇编代码。
-
-r (Register):
-r
命令用于查看或修改 CPU 寄存器的内容。- 直接输入
-r
可以查看所有寄存器的当前值。 - 输入
-r
后跟寄存器名称(如-r ax
)可以查看或修改指定寄存器的值。
-
-t (Trace):
-t
命令用于单步执行程序,它会执行当前指令指针(IP)指向的一条指令,并更新所有寄存器的状态。- 使用
-t
可以帮助用户调试程序,观察每条指令执行后寄存器和内存的变化。
在你提供的示例中,首先使用 -a
命令输入了汇编指令 MOV AX,0005
和 STI
,然后使用 -r
命令查看寄存器状态,可以看到 AX
寄存器的值被设置为 0005
。最后,使用 -t
命令单步执行了 STI
指令,这条指令的作用是设置中断标志位,允许 CPU 响应外部中断。
mov ax,5
mov ax,4E20H
mov bx,ax
mov ch,bl:为什么
注意:AL低位寄存器特性
寄存器相加是不会互相影响的
案例一
mov ax,0
mov ax,93H
add al,85H
实际相加AX的值应该是118。但是因为AL是8位寄存器,所以只能存储低8位数据即18。
悬念:高位数据去哪里
案例二
寄存器类型
上述寄存器是 x86 架构中的 CPU 寄存器,每个寄存器都有其特定的用途和功能。以下是每个寄存器的类型和作用:
-
AX (Accumulator Register):
- 累加器寄存器,通常用于算术运算、数据传输和中断返回值。它经常被用作乘法和除法的默认操作数。
-
BX (Base Register):
- 基址寄存器,主要用于地址寻址。在某些寻址模式中,它可以用来存储一个内存地址的基点。
-
CX (Count Register):
- 计数寄存器,经常用于字符串操作和循环控制。例如,
LOOP
指令会使用CX
寄存器作为循环次数的计数器。
- 计数寄存器,经常用于字符串操作和循环控制。例如,
-
DX (Data Register):
- 数据寄存器,通常用于输入/输出操作和与
AX
寄存器一起用于某些乘法和除法操作。
- 数据寄存器,通常用于输入/输出操作和与
-
SP (Stack Pointer Register):
- 堆栈指针寄存器,用于指向当前的栈顶。在执行
PUSH
和POP
操作时,SP
寄存器会自动增减。
- 堆栈指针寄存器,用于指向当前的栈顶。在执行
-
DS (Data Segment Register):
- 数据段寄存器,用于存储默认的数据段的基地址,用于数据相关的内存访问。
-
ES (Extra Segment Register):
- 附加段寄存器,用于存储额外的段基地址,通常与字符串和其他数据传输指令一起使用。
-
SS (Stack Segment Register):
- 堆栈段寄存器,用于存储堆栈的段基地址。
SP
寄存器和SS
寄存器一起决定了当前的栈顶位置。
- 堆栈段寄存器,用于存储堆栈的段基地址。
-
CS (Code Segment Register):
- 代码段寄存器,用于存储当前执行代码的段基地址。
CS
寄存器和指令指针IP
寄存器一起决定了下一条要执行的指令的位置。
- 代码段寄存器,用于存储当前执行代码的段基地址。
-
IP (Instruction Pointer Register):
- 指令指针寄存器,用于存储下一条要执行的指令的偏移地址。
IP
寄存器总是与CS
寄存器一起使用,以形成完整的指令地址。
- 指令指针寄存器,用于存储下一条要执行的指令的偏移地址。
在实模式下,CS:IP
组合指向当前执行的指令,DS
通常用于数据的内存访问,SS:SP
组合指向栈顶,而 ES
可以用作附加的数据段寄存器。这些寄存器是实现程序逻辑、内存管理和处理器控制流的关键。
地址寄存器
在 DOS 操作系统中的 debug
工具里,-d
和 -e
是两个用于内存操作的命令:
-
-d (Dump):
-d
命令用于显示内存内容,即将内存中的数据“转储”到屏幕上。你可以指定一个内存地址,debug
会从那个地址开始显示一定范围内的内存数据。- 例如,
-d 1000:0000
会显示从内存地址1000:0000
开始的内容。
ascii编码
-
-e (Enter):
-e
命令用于编辑内存内容,即直接在指定的内存地址输入数据。你可以指定一个内存地址,并输入要写入的数据。- 例如,
-e 1000:0000 4E 65 77
会在内存地址1000:0000
处写入数据4E 65 77
(在 ASCII 中对应 “New”)。
这两个命令在调试程序时非常有用,允许你查看和修改程序在内存中的状态。通过使用 -d
命令,你可以查看程序变量的当前值或者指令的编码。而 -e
命令则允许你改变内存中的值,这对于测试程序在不同数据输入下的行为非常有帮助。
段地址寄存器
ds
es
ss
cs
偏移地址寄存器
sp
bp
si
di
ip
bx
基础地址:段地址 * 16(10H)
偏移地址
物理地址 = 基础地址 + 偏移地址
案例三、地址寄存器理解
修改内存地址
通过不同的段地址和偏移地址,访问的物理地址相同
寻址方式:
这种寻址方式,即实模式下的段寄存器加偏移地址的方法,允许在1MB的物理内存空间中灵活地定位数据和代码。这种方法的作用和特点包括:
-
灵活性:
- 通过改变段寄存器的值,可以访问内存中不同的16字节边界开始的区域。这种灵活性使得程序能够有效地组织和管理内存。
-
内存分段:
- 内存分段允许程序将内存分成逻辑上的段,例如代码段、数据段、堆栈段等,这有助于提高程序的结构性和可维护性。
-
内存保护:
- 在某些情况下,分段可以提供一定程度的内存保护,因为程序必须显式地通过正确的段寄存器来访问内存。
-
访问1MB内存空间:
- 在实模式下,x86架构的计算机可以访问最多1MB的物理内存空间。这是因为段寄存器是16位的,偏移地址也是16位的,所以最大可表示的物理地址是
FFFFH:FFFFH
,即FFFF0H + FFFFH = 10FFEFH
(在十进制中是1,114,095,略大于1MB)。
- 在实模式下,x86架构的计算机可以访问最多1MB的物理内存空间。这是因为段寄存器是16位的,偏移地址也是16位的,所以最大可表示的物理地址是
-
偏移地址范围:
- 1MB并不是指偏移地址的范围,而是整个可寻址的物理内存空间。偏移地址的范围实际上是0到
FFFFH
(十进制的65535),因为它是16位的。
- 1MB并不是指偏移地址的范围,而是整个可寻址的物理内存空间。偏移地址的范围实际上是0到
通过这种寻址方式,尽管每个段寄存器和偏移地址都只能表示65536个不同的值(即16位),但通过将段地址乘以16(或左移4位),实际上可以访问1MB的内存空间。这种方法在早期的计算机系统中非常常见,但在现代计算机系统中,由于现代操作系统运行在保护模式下,并使用更复杂的内存管理技术,这种寻址方式已经不再使用。
IP寄存器和指令相关。
案例四、CPU区分指令和数据
机器码 | 汇编指令 |
---|---|
b8 20 4e | |
05 16 14 | |
bb 00 20 | |
01 d8 | |
89 c3 | |
01 d8 | |
b8 1a 00 | |
bb 26 00 | |
00 d8 | |
00 dc | |
00 c7 | |
b4 00 | |
00 d8 | |
04 9c |
可以看到,指令和数据在内存中没有区别。
CPU中的段地址(CS)和偏移地址(IP)组合的时候,可以读取内容,当做指令执行。
案例五、IP寄存器和指令的关系
mov ax,1000H
mov bx,1000H
mov dl,10H
观察ip地址可以发现,IP地址加3从010D——>0110。这时候所读指令也从B8 00 10 转移到下个IP位置BB 00 10.
指令的执行过程如下:
1.CPU从CS:IP中读取指令,存储到指令缓存器中
2.IP = IP + 所读取指令的长度。指向下一个指令
3.执行指令缓存器的内容
悬念:为什么不直接执行ip读取的指令,而要存储到缓存中?
案例六、修改CS,IP寄存器指令
作用:
在 x86 架构的计算机中,修改 CS
(代码段寄存器)和 IP
(指令指针寄存器)的作用是改变 CPU 执行代码的位置。这两个寄存器共同决定了下一条要执行的机器指令的物理地址。
-
CS (Code Segment Register):
CS
寄存器存储当前执行代码段的基地址。在实模式下,这个基地址实际上是段地址乘以16(或左移4位)的结果。
-
IP (Instruction Pointer Register):
IP
寄存器存储相对于代码段基地址的偏移地址,指向当前要执行的指令。
当你修改 CS
和 IP
寄存器的值时,你实际上是在告诉 CPU 从内存的另一个位置开始执行代码。这种操作通常用于以下场景:
-
跳转执行:
- 在程序中进行远跳转(far jump)或远调用(far call)时,需要改变
CS
和IP
的值以跳转到程序的另一个部分。
- 在程序中进行远跳转(far jump)或远调用(far call)时,需要改变
-
程序流控制:
- 在操作系统或引导加载程序中,修改
CS
和IP
可以实现从一个程序段切换到另一个程序段,例如从引导扇区代码跳转到操作系统的内核代码。
- 在操作系统或引导加载程序中,修改
-
中断处理:
- 在中断处理过程中,
CS
和IP
的值会被自动保存到栈中,以便中断处理完成后能够返回到中断前的代码位置。中断向量表中存储的中断处理函数地址也是由CS
和IP
的值组成的。
- 在中断处理过程中,
-
系统初始化:
- 在系统启动时,BIOS 会设置
CS
和IP
寄存器,以指向系统的初始化代码。
- 在系统启动时,BIOS 会设置
修改 CS
和 IP
寄存器是一种底层操作,需要谨慎进行,因为错误的值可能导致程序崩溃或系统不稳定。在现代操作系统中,程序通常在保护模式下运行,这种模式下的内存管理和程序流控制更加复杂,涉及到分段和分页机制。
要求:CS = 2000H , IP = 0000写出指令的执行过程
a 2000:0
mov ax,6622H
jmp 1000:3
mov cx,ax
a 1000:0
mov ax,0123H
mov ax,0
mov bx,ax
jmp bx
mov cx,0
案例七、利用指令计算次方
计算2的8次方
mov ax,1
,将1赋值给ax
add ax,ax
,ax = ax+ax
jmp 2000:0003
mov ax,1
,将1赋值给ax
add ax,ax
,ax = ax+ax ,2,4,8,16,,,执行8次
jmp 2000:0003
转移到原始IP地址
理解错误:当跳转到2000:0003这个CS:IP时候,自动执行add指令。所以可以实现ax值的自增。
相当于 c语言中的ax = ax++
案例八、保存的地址与内存访问
call指令保存内存到哪里?
ds
是段地址寄存器,用来访问数据
mov al,ds[0]
mov al,ds[1]
mov al,ds[2]
mov al,ds[3]
解释
: mov移动指令,获取当前地址的第一个数据,因为al是8位寄存器,所以al会被依次赋值
这是啥问题?