【汇编语言学习笔记·一】汇编语言基础知识

汇编语言的由来

向CPU输入一系列高低电平(1和0),就可以控制CPU完成一系列操作,这些1和0就是机器语言

然而机器语言对人类而言十分难以理解,因此就诞生了汇编语言。机器语言尽管看上去只是一堆1和0,但它们内部仍有结构——存在机器指令,用来控制CPU完成对应指令所约定好的功能。汇编语言为每一条机器指令都规定了一条汇编指令,而汇编指令就是人类较能容易理解的了。

此外,为了进一步方便汇编语言的编写,又提供了一些由编译器来识别和处理的伪指令和符号,它们没有直接对应的机器指令。

这就是汇编语言的由来。

由于汇编语言的底层性,在编写汇编语言时无法像C语言那样即使避开了CPU的部分工作原理也能够进行编程,因此需要对CPU的部分工作原理进行了解

寄存器

寄存器是CPU本身的一部分,它们可以存储数据,而它们存储的数据就是指导CPU运行的依据,所谓“向CPU输入一系列1和0”,大抵就是逐个向对应的寄存器输入这些东西。

不同型号的CPU,其寄存器的个数和结构不同,8086有14个寄存器:AX, BX, CX, DX, SI, DI, SP, BP, IP, CS, SS, DS, ES, PSW

这些寄存器都是16位的,现代CPU基本上都是64位的,2010年左右一般个人电脑上装载的CPU还有很多是32位的,这些CPU上的寄存器就都是64位和32位的,事实上,在8086之前,还有一些8位的CPU。

为了保证新的CPU能够向下兼容,寄存器能够分解:

RAX是64位的,它的一半是EAX,32位;然后就到了之前提到的AX,16位;AX又可以分为两个8位的寄存器:AH和AL
BX, CX, DX同理。(带H的是高八位,带L的是低八位)

8086 中的数据段寄存器: DS

8086CPU会自动把 ds 寄存器中的数据当作是段地址,并与偏移地址address计算得到物理地址,以此来对内存中的指定位置进行寻址。

段寄存器并不支持直接使用mov ds, 数据来直接修改
只能通过mov ds, ax或者其他合法寄存器来修改。
这是8086CPU本身的设计所导致的,其他CPU有可能可以使用 mov ds, 数据 的形式来修改段寄存器的内容

汇编语言的“数据类型”

C语言中有诸如 intdoubleunsigned long long 等数据类型,划分这些数据类型的依据有占的字节数和它们的意义(或者说,程序对其预设的处理方式)

而在汇编语言中基本上只有四种数据类型,划分它们的依据仅有其占的字节数:

  • qword:8个字节,64个二进制位
  • dword:4个字节,32个二进制位
  • word:2个字节,16个二进制位
  • byte:1个字节,8个二进制位

word 仅在16位以上的CPU才有,dwordqword 同理,8086CPU就只有 wordbyte 两种基本数据类型

字单元

16位寄存器用于存储一个字,高8位存放高位字节,低8位存放低位字节。

在内存中,使用两个内存单元存储一个字。

mem

如图:可用内存单元0和1来存储一个字:4E20H。

0单元存放低位字节,1单元存放高位字节

定义:字单元。由两个连续的内存单元组成,以“N地址字单元”称呼起始地址为N的字单元。

0地址字单元由0和1组成,1地址字单元由1和2组成
1地址字节单元由1组成。

8086 特有的地址表示方式

8086的架构较为特殊,它是16位的但是地址总线却是20位
这就为8086提供了1MB的寻址能力。8086中的相关部件会提供两个16位的地址值,一个称作段地址,另一个称作偏移地址,两个地址通过地址加法器能够算出一个20位的地址值,然后通过地址总线即可获取到对应数据。算法为:**物理地址=段地址 * 0x16 + 偏移地址 **

一般而言,使用8086时会使用 CS, DS, SS, ES 作为段寄存器。

高位CPU,一根32位的地址总线的寻址能力就有4GB,一根64位的地址总线的寻址能力就有16EB(一百多万GB),就不需要段地址和偏移地址来定址了,一个地址即可完成定址的需求,也就没有了短地址和偏移地址的概念。

指令地址寄存器

IP寄存器就是指令地址寄存器,在高位 CPU 里,使用 EIP 和 RIP。当然,由于8086在寻址上的特性,又有一个 CS 寄存器,称作代码段寄存器。

指令地址寄存器的作用是保存正在执行的指令的地址,当执行完这条指令后,寄存器存储的地址值会自动变为下一条指令的地址。

对于64位的CPU而言,它正在执行的指令的地址就是 RIP,但是对8086而言则是 CS:IP(CS * 0x10 + IP)

mov 指令无法修改 CS 和 IP 寄存器,要修改它们需要使用 jmp 指令:

同时修改CS和IP中的内容的指令:
jmp 段地址: 偏移地址
只修改IP中内容的指令:
jmp 某一合法寄存器

mov

  • mov 寄存器名, 数据:把数据存放到寄存器中

  • mov 寄存器名, 寄存器名:把一个寄存器中的数据复制到另一个寄存器中

  • mov 寄存器名, [address]address是偏移地址,把它与ds中的段地址合成的物理地址指向的内存中的数据读入寄存器。

  • mov [address], 寄存器名:将寄存器中的数据存放到ds:address指向的内存中。

在8086CPU中,mov 寄存器名, 数据段寄存器无法使用

汇编代码中数据的明文表示

mov ax, 1FFFH,表示把十六进制数 0x1FFF 存入寄存器 ax

mov ax, 01100110B,表示把二进制数 01100110 存入 ax

mov ax 'aa',表示把 0x6161 存入 ax(ASCII 码)

add 和 sub

mov指令一样有四种形式,不再赘述。

add是后面的数据与前面的数据相加,结果存放到前面指向的位置。

sub则是相减。

and 和 or

and指令:按位与

例如:

mov al, 01100011B
and al, 00111011B

执行后al中的数据就是00100011B

作用:可以将操作对象的某一位变成0而其他位不变

例如只希望al的第6位(从后往前数,最后一位标号为0,下同)变成0,就可以执行:

and al, 10111111B

or指令:按位或

例如:

mov al, 01100011B
or al,  00111011B

执行后al中的数据就是01111011B

作用:可以将操作对象的某一位变成1而其他位不变

例如只希望al的第6位变成1,可以执行:

and al, 01000000B

如何进行汇编语言实验

windows10 无法使用dos中的debug,masm 等工具,所以实验均通过 dosbox 来完成。相关教程:https://zhuanlan.zhihu.com/p/370786100

dos中debug工具的基本用法

  • q:退出debug

  • r:查看各个寄存器的内容

    • r 寄存器名:修改某一寄存器的内容
  • d 段地址:偏移地址:查看内存中的内容

    • d 段地址:偏移地址1 偏移地址2:查看内存中某个范围内的内容
  • e : 修改内存中的内容

  • u:查看内存中机器码的含义

  • t:执行内存中的机器码

  • a:用汇编指令的形式向内存中写入机器码

第一个汇编程序

一个源程序,从编写到执行需要三步:

  • 在文本编辑器中编辑源程序
  • 对源程序进行编译连接,生成可直接运行的可执行文件。可执行文件包含两部分:
    • 程序和数据
    • 相关描述信息(程序的大小、所占内存空间等)
  • 执行
assume cs:codesg
codesg segment
start: mov ax, 0123H
       mov bx, 0456H
       add ax, bx
       add ax, ax
       
       mov ax, 4c00H
       int 21H
codesg ends
end
伪指令 segment, ends

汇编语言的源程序中包含两种指令:汇编指令和伪指令
汇编指令是有对应机器码的指令,最终被CPU所执行
伪指令没有对应的机器指令,由编译器来执行

XXX segment:


XXX ends

这个segmentends就是一个成对使用的伪指令,其作用是定义一个段,而XXX就是这个段的名字。

一个汇编程序可以有多个段组成,这里就照应到了前面所讲的指令段、数据段、栈段等段,它们在伪指令中得到了体现。

一个有意义的汇编程序中至少要有一个代码段

伪指令 end

这是一个汇编程序结束的标记,编译器在编译汇编程序的时候,如果读取到了end,就立即停止了对源程序的编译。必须在程序末尾添加end,否则编译器无法知道何时停止编译。

伪指令 assume

将代码段codesg与段寄存器cs联系起来

汇编语言中的标号

在汇编程序中,除了汇编指令和伪指令,还有一些标号,例如codesg,这里的标号就指代了一个地址。

程序返回

一个程序 P 2 P_2 P2 存储在可执行文件中,那么就必须有一个正在运行的程序 P 1 P_1 P1,将 P 2 P_2 P2 载入内存并把CPU的控制权交给 P 2 P_2 P2,并暂停 P 1 P_1 P1 的运行。 P 2 P_2 P2 运行完毕后,就应该把CPU的控制权交回使它得以运行的程序 P 1 P_1 P1,令 P 1 P_1 P1 继续运行。这个过程就是程序返回

以下两条指令可以实现这样的程序返回,其具体原理以后再讨论:

mov ax, 4c00H
int 21H
源程序的编译和链接

使用 masm 指令进行编译,使用 link 指令进行链接

程序运行原理

操作系统的 shell

  • 操作系统是一个多功能模块组成的、复杂的软件系统。任何通用的操作系统,都要有一个被称为 shell 的程序来供操作人员来操作计算机的操作。
  • dos 系统中的 shell 是一个叫做 command.com 的程序,也叫命令解释器。
  • dos 启动并完成其他初始化操作后,运行 command.com,就会在屏幕上显示路径,然后等待用户输入。
  • dos执行一次指令后,就会再次显示当前盘符与路径组成的提示符,等待用户输入。
  • 用户执行程序时,command 会把对应程序载入内存,将 CS:IP 指向该程序的入口,然后command 暂停运行,CPU运行程序,程序结束后返回到 command,然后就会再次显示提示符。
使用debug追踪程序的运行过程

在提示符后输入

debug t1.exe

即可进入针对程序t1.exe的调试模式

即:将程序从t1.exe载入内存,进行相关初始化设定并令CS:IP指向程序的入口。

使用T命令可以单步执行程序

执行到 int 21时,用P命令执行。

程序的加载过程

  • 找到一个起始地址为SA:0000的内存区
  • 在这段内存的前256个字节中创建一个称为程序段的前段(PSP)的数据区,DOS使用PSP与被加载程序进行通信。
  • 在PSP的后面将程序装入,程序的地址设置为(SA + 10H) : 0
  • SA存入DS,并令CS : IP指向程序的入口
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值