《汇编语言》阅读笔记

news/2025/1/24 11:58:06/文章来源:https://www.cnblogs.com/T0fV404/p/18689346

汇编语言

首先,我必须赞扬王爽老师,这是我见过写的最好的教科书了.

然后要注意,汇编语言这本书的前提是8086PC机十六位处理器.还要学x86和x64以及其他奇奇怪怪的架构的汇编

全称

AH&AL=AX(accumulator):累加寄存器
BH&BL=BX(base):基址寄存器
CH&CL=CX(count):计数寄存器
DH&DL=DX(data):数据寄存器
SP(Stack Pointer):堆栈指针寄存器
BP(Base Pointer):基址指针寄存器
SI(Source Index):源变址寄存器
DI(Destination Index):目的变址寄存器
IP(Instruction Pointer):指令指针寄存器
CS(Code Segment)代码段寄存器
DS(Data Segment):数据段寄存器
SS(Stack Segment):堆栈段寄存器
ES(Extra Segment):附加段寄存器

FLAG 标志寄存器: FLAG 寄存器中存储的信息通常又被称作程序状态字(PSW)
OF overflow flag 溢出标志 操作数超出机器能表示的范围表示溢出,溢出时为1.
SF sign Flag 符号标志 记录运算结果的符号,结果负时为1.
ZF zero flag 零标志 运算结果等于0时为1,否则为0.
CF carry flag 进位标志 最高有效位产生进位时为1,否则为0.
AF auxiliary carry flag 辅助进位标志 运算时,第3位向第4位产生进位时为1,否则为0.
PF parity flag 奇偶标志 运算结果操作数位为1的个数为偶数个时为1,否则为0.
DF direcion flag 方向标志 用于串处理.DF=1时,每次操作后使SI和DI减小.DF=0时则增大.
IF interrupt flag 中断标志 IF=1时,允许CPU响应可屏蔽中断,否则关闭中断.
TF trap flag 陷阱标志 用于调试单步操作.

psw: program status word
tcon: timer control
ie: interrupt enable
scon: serial control
EA --Effective Address:有效地址 ,即偏移地址。

SA--segment address

基础知识

(1) 汇编指令是机器指令的助记符, 同机器指令一一对应。
(2) 每一种CPU都有自己的汇编指令集。
(3) CPU 可以直接使用的信息在存储器中存放。
(4) 在存储器中指令和数据没有任何区别,都是二进制信息。
(5) 存储单元从零开始顺序编号。
(6) 在计算机中专门有连接 CPU 和其他芯片的导线, 通常称为总线。总线从物理上来讲, 就是一根根导线的集合。根据传送信息的不同, 总线从逻辑上又分为3类,地址总线、控制总线和数据总线。每一个CPU 芯片都有许多管脚,这些管脚和总线相连。也可以说,这些管脚引出总线。一个CPU 可以引出3 种总线的宽度标志了这个CPU 的不同方面的性能:
地址总线的宽度决定了CPU 的寻址能力;
数据总线的宽度决定了CPU 与其他器件进行数据传送时的一次数据传送量;
控制总线的宽度决定了CPU 对系统中其他器件的控制能力。

出于对兼容性的考虑, 8086CPU 可以一次性处理以下两种尺寸的数据。

  • 字节: 记为byte , 一个字节由8 个加组成,可以存在8 位寄存器中。
  • 字: 记为word, 一个字由两个字节组成, 这两个字节分别称为这个字的高位字节和低位字节.

寄存器

通用寄存器

一个典型的CPU(此处讨论的不是某一具体的CPU) 由运算器、控制器、寄存器(CPU工作原理)等器件构成, 这些器件靠内部总线相连。

8086CPU 有14 个寄存器,每个寄存器有一个名称。这些寄存器是: AX 、BX 、EX 、DX 、SI 、DI 、SP 、BP 、IP 、CS 、SS 、DS 、ES 、PSW 。

8086CPU 的上一代CPU 中的寄存器都是8 位的, 为了保证兼容, 使原来基于上代
CPU 编写的程序稍加修改就可以运行在8086 之上, 8086CPU 的AX、BX、EX 、DX 这4个寄存器都可分为两个可独立使用的8 位寄存器来用:

  • AX 可分为AH 和AL ;
  • BX 可分为BH 和BL ;
  • EX 可分为CH 和CL ;
  • DX 可分为DH 和DL 。

内存地址管理

8086只有16位总线,但却可以寻址1Mb的大小.以下是它的做法:

image-20250124002355445

如图2 . 6 所示, 当8086CPU 要读写内存时:
21
内存
(1) CPU 中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
(2) 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
(3) 地址加法器将两个16位地址合成为一个20位的物理地址,地址加法器采用物理地址=段地址x16+偏移地址的方法用段地址和偏移地址合成物理地址;
(4) 地址加法器通过内部总线将20位物理地址送入输入输出控制电路;
(5) 输入输出控制电路将20位物理地址送上地址总线;
(6) 20 位物理地址被地址总线传送到存储器。

在这里就引入了段的概念.

CS和IP

CS 为代码段寄存器, IP 为指令指针寄存器.

image-20250124002849245image-20250124002856454

image-20250124002917839

image-20250124002932660

以上可以概括为:

(1) 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
(2) IP=IP+所读取指令的长度,从而指向下一条指令;
(3) 执行指令。转到步骤(1) , 重复这个过程。

可用jmp 段地址:偏移地址来修改CSIP,也可以使用jmp 合法寄存器等于mov IP,寄存器.

寄存器(内存访问)

CPU 要读写一个内存单元的时候, 必须先给出这个内存单元的地址, 在8086PC 中,内存地址由段地址和偏移地址组成。8086CPU 中有一个DS 寄存器, 通常用来存放要访问数据的段地址。

CPU 如何知道栈顶的位置?显然,也应该有相应的寄存器来存放栈顶的地址,8086CPU 中,有两个寄存器,段寄存器SS 和寄存器SP, 栈顶的段地址存放在SS中,偏移地址存放在SP 中。任意时刻,SS:SP 指向栈顶元素。push指令和pop指令执行时,CPU从SS和SP中得到栈顶的地址。

第一个程序

先对汇编代码的结构做个了解.

以下是一段汇编代码:

assume cs:codesg
codesg segmentmov ax, 0123Hmov bx, 0456Hadd ax, bxadd ax, axmov ax, 4c00Hint 21H
codesg ends
end

伪代码

xxx segmentxxx ends是一对,也是必须用到的,功能是定义一个代码段

end是汇编程序结束的标志

assume是关联相关的段寄存器

程序返回代码

mov ax,4c00H
int 21H ;程序返回代码

编译与链接

编译与链接不做了解.

[BX]和loop指令

一些定义

[BX]表示的是内存单元的偏移地址

(BX)则表示里面的内容

idata表达常量

loop

这是一段含loop的指令:

assume cs:code
code segmentmov ax, 2mov cx, 11
s: add ax, axloop s ;cx为0则执行下一条,否则令cx减1mov ax,4c00hint 21h
code ends
end

段前缀

这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的"ds:" "cs:" "ss:" " es:",在汇编语言中称为段前缀。默认则在ds中

包含多个段的程序

代码段使用数据

以下是一段asm代码:

assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hmov bx, Omov ax, Omov cx, 8
s: add ax, cs:[bx]add bx, 2loop smov ax, 4c00hint 21h
code ends
end

程序第一行中的“dw" 的含义是定义字型数据。dw 即“ define word "。
在这里,使用dw定义了8个字型数据(数据之间以逗号分隔),它们所占的内存空间的大小为16个字节。

入口

assume cs:code
code segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
start: mov bx, 0mov ax, 0mov cx , 8
s: add ax, cs:[bx]add bx, 2
code ends
end start

在程序的第一条指令的前面加上了一个标号start,而这个标号在伪指令end的后面出现。这里,我们要再次探讨end的作用。end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方。在程序6.2中我们用end指令指明了程序的入口在标号start处,也就是说,“ mov bx,0"是程序的第一条指令。

不同的段

assume cs:code, ds:data, ss:stack
data segment
dw 0123h , 0456h, 0789h, 0abch, 0defh , 0fedh , 0cbah, 0987h
data ends
stack segmentdw 0 , 0 , 0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
stack ends
code segment
start: mov ax, stackmov ss, axmov sp, 20h ;设置栈顶ss:sp 指向s tack : 20mov ax, datamov ds, axmov bx, 0mov cx, 8
s : push [bx]add bx, 2loop smov bx, Omov cx, 8
s0 : pop [bx]add bx, 2loop s0mov ax, 4c00hint 21h
code ends
end start

这里是定义多个段,由于有符号,所以符号可以对应段地址,比如mov ax, stack就是把stack的段地址放入ax中.

更灵活的定位内存地址的方法

字符形式的数据

" db'unIX' ” 相当于“db 75H 6EH 49H 58H”.

si和di

si和di在8086机里与bx功能接近,但不能分成两个8位寄存器

不同的寻址方式的灵活应用

(1) [idata]用一个常量来表示地址, 可用于直接定位一个内存单元;
(2) [bx]用一个变量来表示内存地址, 可用于间接定位一个内存单元;
(3) [bx+data]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接
定位一个内存单元;
(4) [bx+si]用两个变量表示地址;
(5) [bx+si+idata]用两个变最和一个常量表示地址。

数据处理的两个基本问题

Warnings

mov ax, [bx]
mov ax, [si]
mov ax, [di]
mov ax, [bp]
mov ax, [bx+si]
mov ax, [bx+di]
mov ax, [b p+si]
mov ax, [b p+di]
mov ax, [bx+si+idata]
mov ax, [bx+di+idata]
mov ax, [bp+si+idata]
mov ax, [bp+di+idata]
下面的指令是错误的:
mov ax, [bx+bp]
mov ax, [si+di]

只要在[ ]中使用寄存器bp ,而指令中没有显性地给出段地址,段地址就默认在ss 中。比如下面的指令。
mov ax, [bp]
mov ax, [bp+i data]
mov ax, [bp+si]
含义: (ax) = ((ss) *16+ (bp) )
含义: (ax) = ((ss) *16+ (bp) +idata)
含义: (ax) = ((ss) *16+ (bp) + (si))
mov ax, [bp+si+idata] 含义: (ax) = ((ss) *16+ (bp) + (si) +idata)

寻址方式小结

image-20250124105340921

指令转移的原理

可以修改IP, 或同时修改CS和IP的指令统称为转移指令。

依据位移进行转移的jmp指令

jmp short 标号(转到标号处执行指令)

这种格式的jmp指令实现的是段内短转移,它对IP 的修改范围为-128~ 127, 也就是说,它向前转移时可以最多越过128 个字节,向后转移可以最多越过127个字节。jmp指令中的“short"符号,说明指令进行的是短转移。jmp 指令中的“标号”是代码段中的标号,指明了指令要转移的目的地,转移指令结束后,CS:IP应该指向标号处的指令。

在"jmp short 标号"指令所对应的机器码中, 并不包含转移的目的地址,而包含的是转移的位移。这个位移,是编译器根据汇编指令中的“ 标号”计算出来的.

实际上, jmp short 标号”的功能为:(IP)=(IP)+8 位位移。
(1) 8 位位移=标号处的地址-jmp指令后的第一个字节的地址;
(2) short 指明此处的位移为8位位移;
(3) 8 位位移的范围为- 128~ 127, 用补码表示(如果你对补码还不了解, 请阅读附
注2);
(4) 8 位位移由编译程序在编译时算出。
还有一种和“jmp short 标号”功能相近的指令格式,jmp near ptr 标号,它实现的是
段内近转移。
jmp near ptr 标号”的功能为: (IP)=(IP)+ 16 位位移。
(1) 16 位位移=标号处的地址-jmp 指令后的第一个字节的地址;
(2) near ptr 指明此处的位移为16 位位移,进行的是段内近转移;
(3) 16 位位移的范围为—32768~32767, 用补码表示;
(4) 16 位位移由编译程序在编译时算出。

转移的目的地址在指令中的jmp指令

"jmp far ptr 标号"实现的是段间转移,又称为远转移。

转移地址在寄存器中的jmp指令

指令格式:jmp 16位reg
功能:(IP)=(l6位reg)

转移地址在内存中的jmp指令

(1) jmp word ptr 内存单元地址(段内转移)

(2) jmp dword ptr 内存单元地址(段间转移)

有条件转移

jcxz 当cx为zero时,短转移

loop其实是类似的,而且也是短转移.

CALL 和RET 指令

跳过,已经品味得够多了.

标识寄存器

FLAG 标志寄存器: FLAG 寄存器中存储的信息通常又被称作程序状态字(PSW)
OF overflow flag 溢出标志 操作数超出机器能表示的范围表示溢出,溢出时为1.
SF sign Flag 符号标志 记录运算结果的符号,结果负时为1.
ZF zero flag 零标志 运算结果等于0时为1,否则为0.
CF carry flag 进位标志 最高有效位产生进位时为1,否则为0.
AF auxiliary carry flag 辅助进位标志 运算时,第3位向第4位产生进位时为1,否则为0.
PF parity flag 奇偶标志 运算结果操作数位为1的个数为偶数个时为1,否则为0.
DF direcion flag 方向标志 用于串处理.DF=1时,每次操作后使SI和DI减小.DF=0时则增大.
IF interrupt flag 中断标志 IF=1时,允许CPU响应可屏蔽中断,否则关闭中断.
TF trap flag 陷阱标志 用于调试单步操作.

adc sbb

adc 是带进位加法指令, 它利用了CF 位上记录的进位值。
指令格式: adc 操作对象1, 操作对象2
功能: 操作对象1 = 操作对象1+ 操作对象2+CF
比如指令adc ax,bx 实现的功能是: (ax)=(ax)+(bx)+ CF

sbb 是带借位减法指令,它利用了CF位上记录的借位值。
指令格式: sbb 操作对象1, 操作对象2
功能: 操作对象l =操作对象1-操作对象2-CF
比如指令sbb ax,bx 实现的功能是: (ax)=(ax)—(bx)—CF

用于更大数据的高位运算

cmp

cmp 是比较指令, cmp 的功能相当于减法指令,只是不保存结果。cmp 指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
cmp 指令格式:cmp 操作对象1, 操作对象2
功能:计算操作对象l —操作对象2 但并不保存结果,仅仅根据计算结果对标志寄存
器进行设置。
比如,指令cmp ax,ax,做(ax)-(ax)的运算,结果为0, 但并不在ax中保存,仅影响
flag的相关各位。指令执行后:zf=1, pf=1, sf=0, cf=0 of=0。

相关跳转

下面是常用的根据无符号数的比较结果进行转移的条件转移指令。

image-20250124114137692

这些指令比较常用,它们都很好记忆,它们的第一个字母都是j ,表示jump; 后面的
字母表示意义如下。
e : 表示equal
ne: 表示not equal
b: 表示below
nb : 表示not below
a : 表示above
na: 表示not above

popf pushf

压入和弹出 相关寄存器为标识寄存器

内中断和外中断

没啥好了解的,跳过

指令

mov add sub div mul abc sbb

push pop

int

inc:令寄存器加1

loop

and:逻辑与指令,按位进行与运算。 or:逻辑或指令, 按位进行或运算。

db dw dd(dword) dup(db 重复的次数 dup(重复的数据)) offset(获取偏移值)

jmp

shl shr 位移,移出的最后以为放到CF中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/874684.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【unity】学习制作2D横板冒险游戏-3-

添加野猪添加刚体2D组件,碰撞组件,该碰撞组件是确保野猪能跟地面碰撞添加玩家图层和敌人图层,并应用,使野猪和玩家不会彼此被推着走碰撞剔除中选择Player和Enemy再增加一个碰撞组件当作触发器,设置如下,该碰撞组件是确保人物和怪物的互动基本属性及其计算 再如图路径下创建…

远控流畅游戏,我用过最棒工具ToDesk

孤独乏味人又懒,能够干嘛来消遣?手游、端游都好玩,没有高端设备在身边,也是能够轻松玩!究竟怎么实现的?其实就是通过ToDesk这种专业的远程控制软件来随时随地操作异地的目标设备从而帮助实现更丝滑给力的远程游戏畅玩体验!当然,用户能够借助完成这需求的辅助工具并不止…

C# Odbc Informix读取中文方法

一。 部署好informix服务器后 二。 在windows主机安装好Informix Client-SDK, 这个软件客户端时免费的,可以在官网下载 三。配置好ODBC连接 1.用户名密码服务端口自行填写 2.关于客户语言的配置要使用以下参数: Client Locale -> en_US.CP1252 Database Locale -> en_…

ToDesk远程连接几项模式区别何在?

对于很多用过ToDesk远程控制软件进行随时随地跨系统、跨设备操作的小伙伴们来说,它无疑能解决做种场景下问题,无论是在职场工作中,还是日常生活中,均能带来很多便捷!虽然轻松使用很简单,但很多所不知道的是其实应对不同的情况,选择不同的连接模式更有益!以下木木小编就…

如何在网站后台修改首页?

修改网站后台首页通常涉及对后台管理界面的调整。以下是详细步骤:登录后台:使用管理员账号登录网站后台管理系统。 进入模板管理:在后台管理系统中找到“模板管理”或“模板文件管理”选项。 编辑模板文件:找到后台首页的模板文件(如index.htm或index.php),使用代码编辑…

一些关于软件测试中登录模块的测试用例

以下是一份针对软件测试中登录模块较为完整的测试用例,涵盖了各种常见情况,尽量保证较高的覆盖率:一、功能测试1. 正常登录 2. 用户名错误 3. 密码错误 4. 用户名和密码都错误 5. 用户名和密码为空 6. 仅用户名为空 7. 仅密码为空 8. 用户名和密码长度极限值 9. 记住用户名…

如何修改网站管理员admin的信息?

登录网站后台:使用管理员账号(通常是admin)登录到网站的后台管理界面。进入用户管理页面:在后台管理界面中,找到“用户”、“用户管理”或类似的菜单选项,点击进入用户管理页面。找到管理员账号:在用户管理页面中,找到管理员账号(通常是admin),点击账号名称或编辑按…

如何在网站上修改源代码?

要在网站上修改源代码,您可以按照以下步骤进行操作:确定要修改的代码:确定您想要修改的网站源代码文件。 找到代码文件:根据您的网站结构,找到包含要修改代码的文件。 编辑代码文件:使用文本编辑器或专业的网页设计工具,编辑代码文件中的代码。 保存修改:修改完成后,保…

如何在CMS系统中动态修改网站栏目?

在CMS系统中动态修改网站栏目通常涉及后台管理界面的操作。以下是详细步骤:登录后台:使用管理员账号登录CMS后台管理系统。 进入栏目管理:在后台管理系统中找到“栏目管理”或“频道管理”选项。 编辑栏目:选择需要修改的栏目,进行编辑。可以更新栏目名称、描述、排序等信…

补充篇:Unity中Compute Shader的基本使用

补充篇:Unity中Compute Shader的基本使用 Compute Shader 可以充分利用GPU来帮助我们处理大规模的并行任务。虽然名字带Shader,但它可不光用于图形学,所以即便对渲染相关的知识不甚了解,也不妨碍学习它的用法。 基本流程 对任意 Project的文件夹右键Create/Shader/Compute …

修改网站首页大图通常涉及到更新网站首页的图片文件

找到图片文件:首先需要找到网站首页大图的图片文件所在的位置。通常,网站的图片文件会存储在服务器的特定目录中,例如 images 目录。 备份原图片:在修改之前,建议先备份原图片,以防修改过程中出现问题需要恢复。 准备新图片:准备好要替换的新图片,确保新图片的尺寸和格…

怎样修改网站公司名称

修改网站公司名称通常涉及到更新网站的标题、版权信息、联系方式等相关内容。以下是一些常见的方法:网站标题修改:在网站的HTML代码中,找到 <title> 标签,并将其中的公司名称修改为新的名称。例如: <title>新公司名称 - 网站首页</title>版权信息修改:…