汇编基本概念
汇编入门概念
目录
入门知识
课程内容
- 课程指南
- 访问寄存器和内存
- 汇编语言程序
- 内存寻址方式
- 流程转移与子程序
- 中断及其应用
- 高级汇编语言技术
课程指南
定位
- 理解硬件结构
- 掌握指令集
- 理解程序的运行过程
内容:入门级指令集、作为80x86,linux,arm等的前置知识体系
- 8088
- 8086
学习方法:
- 贯穿实践
- 观察机器内部的状态
- 学习进程
编程语言与指令
机器语言与机器指令
- 机器语言:机器指令的集合
- 机器指令:机器可以正确执行的命令
- 由一串二进制数表示
- 电平脉冲(用高低电位表示0、1)
汇编语言与汇编指令
- 汇编语言:汇编指令的集合
- 汇编指令:机器指令的助记符
- 便于记忆的书写格式
汇编语言编写过程:
flowchart LR
pro[程序员]-->ins[汇编指令]-->complier[编译器]-->machine[机器码]-->cp[计算机]
汇编语言结构:
- 伪指令 — 由编译器执行
- 其它符号 — 由编译器识别
- 汇编指令 — 机器码的助记符
寄存器与内存
CPU中的寄存器
8086CPU有14个寄存器:
- 通用寄存器:AX、BX、CX、DX ;
- 变址寄存器:SI、DI ;
- 指针寄存器:SP、BP ;
- 指令指针寄存器: IP ;
- 段寄存器:CS、SS、DS、ES ;
- 标志寄存器:PSW : 共性:
- 8086CPU所有的寄存器都是16位的, 可以存放两个字节。
在 x86 架构的汇编语言中,常用的寄存器有:
- AX
- 全写:Accumulator Register
- 作用:用于算术运算、I/O 操作。
- BX
- 全写:Base Register
- 作用:用于基址的存储,通常用于指向数据段中对象的起始位置。
- CX
- 全写:Counter Register
- 作用:用于循环操作的计数器。
- DX
- 全写:Data Register
- 作用:用于存放 I/O 操作的地址或数据。
- SI
- 全写:Source Index
- 作用:作为源地址的指针,用于字符串操作。
- DI
- 全写:Destination Index
- 作用:作为目的地址的指针,用于字符串操作。
- BP
- 全写:Base Pointer
- 作用:用于指向栈中的数据,常用于高阶语言的局部变量访问。
- SP
- 全写:Stack Pointer
- 作用:指向栈顶,用于栈操作。
- IP
- 全写:Instruction Pointer
- 作用:指向下一条执行的指令。
- CS
- 全写:Code Segment
- 作用:指向代码段的起始地址。
- DS
- 全写:Data Segment
- 作用:指向数据段的起始地址。
- SS
- 全写:Stack Segment
- 作用:指向栈段的起始地址。
- ES
- 全写:Extra Segment
- 作用:额外的数据段,用于字符串操作。
- FS
- GS
- 全写:General Purpose Segment
- 作用:额外的段寄存器,提供更多段地址。
兼容性问题
问题:8086上一代CPU中的寄存器均是8位,如何确保程序的兼容性?
方案:通用寄存器分为两个独立的8位寄存器使用
细化:
- AX可以分为 AH 和 AL
- BX可分为 BH BL
- CX可分为 CH CL
- DX可分为 DH DL
字长和字
通常说的多少位CPU,指的是CPU有多少位的字长
8086是16位CPU,它的字长(word size)是16bit
一个n位的cpu中,一个字可以存在n位的寄存器里
物理地址 和 寻址能力的矛盾
矛盾:
- 寻址能力由字长决定 – 即16位字长的地址也是16位,寻址能力只有64K
- 而物理地址有 20位 ,1 M的地址
解决方法:
- 用两个16位地址(段地址、偏移地址)合成一个20位的物理地址
- 地址加法器合成地址的方法:物理地址=段地址左移4位 + 偏移地址
段地址$\times16+$偏移地址=物理地址 的本质含义
- 用一个基础地址(16位的段地址),加上相对于基础地址的偏移地址,给出内存单元的物理地址
内存的分段表示法
内存本身是一体的,分段来自于CPU
基本事实
- 段地址x16 必然是16的倍数,意味着一个段的起始地址也是16的倍数
- 偏移地址是16位,16位地址的寻址能力是64k,因此一个段的最大长度为64k
存储单元地址的表示方法、例子:
数据存在 21F60H 中,段地址是 2000H
- 数据存在内存 2000H:1F60H 单元中
- 数据存在内存的 2000H段中的 1F60H 单元中
段地址的重要性
由于段地址的重要性,有专门用来存放 段地址的寄存器。
- CS - 代码段寄存器
- DS - 数据段寄存器
- SS - 栈段寄存器
- ES - 附加段寄存器
偏移地址可以用多种方法提供 — 形成8086丰富的取址方式
掌握汇编语言是 学会活用 丰富的取址方式 的过程
Debug的使用
在DOSBOX中 挂载指定目录到 C盘, 并转到C盘
1
2
mount c e:\dailyfile\codefile\masm
C:
相关命令
- r - 寄存器相关操作
- r 寄存器名 - 修改指定寄存器内容
- d - 查看内存
- d 列出预设地址内存 8行 x 16列个 字节, 即128个字节
- d 段地址:偏移地址 [数量]- 列出指定地址的内容,[可指定列出范围]
- e - 修改内存内容
- e 段地址:偏移地址 数据1 数据2 …
- e 段地址:偏移地址 - 询问式修改
- 空格 - 接受并继续
- 回车 - 结束
- u - 将机器指令翻译成 汇编指令 查看
- a - 用汇编指令的形式写入内存
- t - 逐条执行 CS:IP 处的指令
- 可通过r 修改 CS:IP 的位置
- q - 退出 debug
g命令
在 DOSBox 中使用 debug
工具时,g
命令是一个非常重要的指令,用于控制程序的执行。下面是详细的解释和用法:
g
命令概述
g
命令用于启动被调试程序的执行,或继续执行之前被暂停的程序。可以按指定的地址或断点进行跳转。
语法
g[=address] [address [address [...]]]
参数说明
address
: 可选的参数,指定程序继续执行的起始地址。如果省略,则从当前地址开始执行。address [address [...]]
: 可选的,指定一个或多个断点地址。如果执行达到这些地址中的任一个,程序将暂停,并返回到调试器。
使用示例
从当前地址开始执行:
g
它将从当前的指令开始继续执行程序。
从指定地址开始执行:
g=CS:100
将从代码段寄存器 (CS) 和 100 偏移(如
CS:100
)处开始执行。设置断点:
g 200 250 300
将从当前地址开始执行,并在地址
200
,250
,300
处设置断点,如果执行到这些地址之一,程序将暂停。
示例解释
假设你正在调试一个简单的程序,并希望代之从地址 0x100
处继续执行,且在地址 0x150
和 0x1A0
处设置断点:
启动
debug
并加载程序:debug myprog.exe
显示当前寄存器和状态,并查看当前地址:
-r
使用
g
命令执行程序,并在特定的断点处暂停:-g=100 150 1A0
这样,debug
将从 0x100
处开始执行,当指令指针达到 0x150
或 0x1A0
时,程序将暂停并返回到调试器界面,你可以继续调试程序。
注意事项
- 如果没有指定断点,程序将在运行到底后停止调试。
- 设置的断点无论是否真正命中,如果程序遇到非法操作或其他错误,同样会终止并返回调试器。
CS
代表当前段寄存器,通常在 16 位段的程序中会使用。
通过正确利用 g
命令,你可以高效地控制程序的执行流,设置断点并进行详细的调试分析。
修改CS:IP
- Debug中,通过 rcs/rip 进行修改
- 汇编代码中,通过 jmp 指令修改
- jmp cs:ip 指定跳转cs、ip
- jmp ax 仅更改 ip 为对应的寄存的值
字在内存中的存储
对8086CPU, 16位作为一个字
- 16位的字 在寄存器中的存储
- 例如:3E20
- 高位放高字节、低位放低字节
- AH存高位(3E), AL存低位(20)
- 连续内存,在内存中的存储
- 低位在低地址、高位在高地址
- $4E20 \underset{存放地址}{\longrightarrow} 204E$
注意区分:
字节型数据 & 字型数据
字型 — 16位CPU,即是4位16进制数 字节型 — 即,1字节 - 8位 - 2位16进制数
DS
DS
是数据段寄存器(Data Segment Register)的缩写。它用来指向内存中的数据段,帮助程序访问特定的数据区域。比如,当你需要读取或存储数据时,DS
会提供基础地址。
1
2
3
mov ax, 1000H
mov ds, ax
mov ax, [0] -- 将1000:0 的数据赋给ax
mov ax, [0]
栈及栈操作
SS、SP —- 栈段、栈顶指针
SS 指向栈的顶部(最低地址)
SP 指向栈底(最高地址) — SP初始指向的地址不存放数据、表示空栈 栈的大小 — 初始状态下的 SP - SS 即是栈的大小
关于栈的超界问题
- CPU不会检测栈的是否超界
- 需要程序员自己把握栈的大小
栈的操作
栈的每一操作,都是对一字长的数据进行操作
- push ax
- 将 ax 的数据 压入栈中
- 每压入一个,SP往前移动一个字长
- pop ax
- 将 栈顶数据弹出, 存入 ax
- 每弹出一个,SP往后移动一个字长
段的总结
- DS — 数据段
- 通过访问内存单元 []
- CS — 代码段
- CS/IP(指令指针寄存器) , 设置IP偏移量访问
- SS — 栈段
- SP 栈顶指针
- push 、 pop 操作