ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

汇编语言

2022-05-26 22:00:09  阅读:291  来源: 互联网

标签:汇编语言 mov 地址 内存 寄存器 ax CPU


汇编语言

基础知识

机器语言与汇编语言

  • 机器语言:一列二进制数,计算机将其变为一列高低电平,驱动计算机的电子器件。

  • 汇编语言:机器语言难以辨别和记忆,便产生了便于记忆的机器指令的书写格式

\(e.g.:\)

操作:把寄存器BX中的内容送到AX中

机器指令:1000100111011000

汇编指令:mov ax, bx

graph LR 汇编指令--编译器-->机器码

汇编语言的组成

  • 汇编指令:机器码的助记符,有对应得到机器码

  • 伪指令:没有对应的机器码,由编译器执行,计算机不执行

  • 其它符号:没有对应的机器码,有编译器识别,\(e.g.+、-、*、/\)

计算机原理补充

  • 指令和数据:都是二进制信息,在内存或磁盘上几乎没有区别,\(e.g.\)对于1000100111011000,既可以把它看作89D8H,也可以看作mov ax, bx指令来执行

  • CPU对存储器的读写:CPU要从内存中读数据,先要指定存储单元的地址,对哪个器件操作,执行什么操作...

    • 信息交互:存储单元的地址(地址信息)、器件的选择,读或写的命令(控制信息)、读或写的数据(数据信息)

    • 总线:连接CPU和其它芯片的导线,根据传送信息的不同,分为地址总线、控制总线、数据总线

      • 地址总线:CPU与通过地址总线指定存储器单元。例如一个具有10根地址总线的CPU可以传递10位二进制数据,表示\(2^{10}\)种不同的数据。

      • 数据总线:内存与其他器件之间通过数据总线进行数据传送,数据总线的宽度决定数据传送速度。

      • 控制总线:控制总线的宽度决定CPU对外部器件的控制能力。

CPU从内存中读取数据的过程如上图

  1. CPU通过地址总线将地址信息3发出;

  2. CPU通过控制总线发出内存读命令,选中存储器芯片,通知它将要从中读取数据;

  3. 存储器将3号单元中的数据8通过数据总线送入CPU中;

写入数据过程类似。

寄存器

CPU主要由运算器、控制器、寄存器构成,在CPU中:

  • 运算器进行信息处理

  • 寄存器进行信息存储

  • 控制器控制各种期间工作

  • 内部总线连接各器件并进行数据传送

  • \(8086CPU\)中有14个寄存器,分别为:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW

几条简单的汇编指令(不区分大小写):
mov ax, 18——将18送入AX
mov ah, 78——将78送入AH
add ax, 8——将寄存器AX中的数值加8 
mov ax, bx——将寄存器BX中的数据送入AX中
add ax, bx——将AX与BX中的数据相加并将结果存储在AX中

通用寄存器

在\(8086CPU\)中寄存器为16位,存放两个字节。寄存器AX、BX、CX、DX通常用来存放一半性的数据,称为通用寄存器。而且它们都可以氛围两个独立使用的8位寄存器使用。

  • AX分为AH和AL

  • BX分为BH和BL

  • ……

    2.png

如上图,数据20000的二进制为100111000100000,存储在AX中,将16位的AX分为两个8位寄存器,即AX的低八位(07)构成AL,表示78;高八位(815)构成AH,表示32

字在寄存器中的存储:一个字有两个字节组成,它的高位字节和低位字节分别存储在寄存器的高八位和低八位寄存器中。

段寄存器

物理地址

所有的内存单元构成的存储空间是一个一维空间,每个内存单元在这个空间中有唯一的地址,这个地址称为物理地址

8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力。但是8086CPU是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。如果只是将地址从内部简单发出,那么它只能送出16位的地址,表现出的寻址能力只有64KB。

如图,8086CPU在内部用两个16位地址合成一个20位的物理地址。

3
  1. CPU中的相关部件提供一个16位的地址,一个称为段地址,另一个称为偏移地址

  2. 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;

  3. 地址加法器将2个16位的地址合成为一个20位的地址;物理地址=段地址*16+偏移地址

  4. 地址加法器再通过内部总线将20位的物理地址送入输入输出控制电路

  5. 输入输出控制电路将20位的物理地址送上地址总线;

  6. 20位的物理地址被地址总线传送到存储器;

$e.g.段地址:0X1230,偏移地址:0X00C8,物理地址= 0X1230*16+0X00C8 = 123C8 $

解读物理地址的生成过程物理地址=段地址*16(基础地址)+偏移地址

  • 段的划分:段的划分来自于CPU而不是内存,假设我们认为\(10000H\)到\(100FFH\)为一个段,段的起始地址为\(10000H\),大小为\(100H\);我们也可以把\(10000H~1007FH\)、\(10080H~100FFH\)认为是两个段,起始地址分别为\(10000H\)和\(10080H\),大小都为\(80H\)。

  • 段的长度:基础地址=段地址*16,则段的起始地址为16的倍数;偏移地址为16位,则一个段的最大长度为\(64KB\)

寄存器CS、IP

CS和IP指示了CPU当前要读取指令的地址,其中CS为代码段寄存器,IP为指令指针寄存器。

在8086PC机中,CPU将从M*16+N开始读取一条指令并执行,如下动图

4

(8086CPU当前状态:CS2000H,IP0000H;内存20000H~20009H中存放可执行机器码)

  1. 初始状态:CS:2000H,IP:0000H;

  2. CS、IP中的内容送入加法器得到物理地址;

  3. 地址加法器将物理地址送入输入输出控制电路;

  4. 输入输出控制电路将20000H送上地址总线;

  5. 从内存单元20000H中得到机器指令B8 23 01,通过数据总线送入CPU;

  6. 输入输出控制电路将机器指令送入指令缓冲器;

  7. 执行指令mov ax, 0123H,IP的值增加

执行下一段重复上述过程。

修改CS、IP中的指令

程序员你呢沟通过修改寄存器中的内容实现对CPU的控制,而CPU从何处执行指令是由CS、IP中的内容决定的,因此,改变CS、IP的内容可以控制CPU执行目标指令。

;同时修改CS、IP的内容
jmp 段地址;偏移地址
;仅修改IP的内容
jmp 合法寄存器

\(e.g.\)

jmp 2AE3: 3,执行后CS=2AE3H,IP=0003H

jmp ax,执行前ax=1000H,CS=2000H,IP=0003H;执行后ax=1000H,CS=2000H,IP=1000H

注:mov IP, ax不合法

段寄存器DS和[address]

在\(8086CPU\)中,DS寄存器通常用来存放要访问的段地址

\(e.g.\)将10000H(1000:0)中的数据读取到al

mov bx, 1000H
mov ds, bx
mov al. [0]  ; […]表示一个内存单元

注:DS是段寄存器, mov ds, 1000H非法。例如,要将AL中的数据/指令送入DS中,指令为:

mov ax, 1000H
mov ds, ax
mov [0], al

mov、add、sub指令

mov 寄存器, 数据          mov ax, 8
mov 寄存器,寄存器         mov ax, bx
mov 寄存器, 内存单元      mov ax, [0]
mov 内存单元, 寄存器      mov [0], ax
mov 段寄存器, 寄存器      mov ds, ax

寄存器SS、SP

CPU的栈机制

在基于\(8086CPU\)编程时,可以将一段内存当作栈使用。最基本的两个指令PUSH实现入栈,POP实现出栈。如下图将10000H~1000FH这段内存用作栈使用

push ax / push […]  ; 将寄存器AX/[内存单元]中的数据送入栈中
pop ax / pop […]   ; 将栈顶数据去除送入AX/[内存单元]中
5

SS、SP

在\(8086CPU\)中,段寄存器SS存放栈顶地址,SP存放偏移地址。任意时刻,SS:SP指向栈顶元素

下图描述了\(8086CPU\)对push指令的执行过程,pop过程相反

6

注:入栈时,栈顶从高地址向低地址方向增长

当栈为空时,按照SS:SP指向栈顶的原则,SS:SP指向栈最底部单元下面的单元

若栈顶超界,可能会覆盖原本存放的数据,会引发一系列的错误

第一个程序

程序从写出到执行

graph LR test.asm--编译masm-->test.obj--连接link-->test.exe--加载command-->内存中的程序
  1. 编写汇编源程序;

  2. 对源程序编译连接;

    1. 使用编译程序对源程序进行编译,生成目标文件;

    2. 用连接程序对目标文件进行连接,生成可执行文件;

可执行程序

  • 程序(机器码)和数据(源程序定义的数据)

  • 相关的描述信息(大小。占的内存空间)

  1. 执行可执行文件中的程序;

操作系统按照可执行文件的描述信息,将可执行文件的机器码和数据载入内存,进行相关的初始化(设置CS:IP指向),然后由CPU执行程序。

源程序

assume cs:codesg

codesg segment  ; 定义一个段,段的名称为"codesg",段从此开始
                ; 标号:codesg指代一个地址,最终被编译、连接程序处理为一个段的段地址

    mov ax, 0123H
    mov bx, 0456H
    add ax, bx
    add ax, ax

    mov ax, 4c00H
    int 21H
codesg ends  ; 名称为"condesg"的段结束

end

下面对程序进行说明

伪指令:

没有对应的机器指令,不被CPU执行,由编译器执行

  • segmentend是一对伪指令,用来定义一个段,XXX是段的名称;每个程序至少有一个段;
  • end是汇编语言的结束标记,编译器在编译汇编程序过程中,遇到end则结束对源程序的编译;
  • assume将具有特殊用途的段与相关的段寄存器相关联汇编指令程序;

汇编指令

源程序中的汇编指令组成了最终由计算机执行的程序,这里的程序是源程序中最终由计算机执行、处理的指令或数据,程序最先以汇编指令的形式存在源程序中,经编译、连接后转为机器码,存储在可执行文件中。

[BX]和loop指令

[bx]和内存单元

要完整地描述一个内存单元,需要内存单元的地址内存单元的长度

  • 用[0]表示内存单元,0表示单元的偏移地址

  • 用[bx]表示内存单元,偏移地址在bx

段前缀

在指令mov ax, [bx]中,偏移地址又bx给出,段地址在ds中;我们也可以显式地给出段地址所在的寄存器,例如mov ax, es:[bx]

"ds:"、"cs:"、"ss:"、"es:"被称为段前缀

loop

定义“( )”表示寄存器段寄存器内存单元中的内容,(al)、(bl)等为字节型,(ds)、(ax)为字型例如

  • (ax)=0010H表示ax中的内容为0010H

  • (21000H) = 0010H表示2000:1000处的内容为0010H

  • (ax) = ((ds)*16+2)表示mov ax, [2]

  • (ax) = (ax)+2 表示add ax, 2

  • (sp) = (sp)-2表示push ax

  • (ax) = ((ss)*16+(sp)) \\ (sp) = (sp)+2表示pop ax

loop指令:用于实现循环功能,cx中存放循环次数

loop 标号

CPU执行loop指令时,进行两步操作

  1. (cx) = (cx)-1

  2. 判断(cx)是否为0

    • \((cx) = 0\)向下执行程序

    • \((cx) \not= 0\)转至标号处执行程序

《汇编语言》(第三版)王爽 著

链接:https://pan.baidu.com/s/1adqH6znzDA1pAqkK7xDt3w?pwd=1226
提取码:1226

标签:汇编语言,mov,地址,内存,寄存器,ax,CPU
来源: https://www.cnblogs.com/Euler-0525/p/16313494.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有