编程语言
首页 > 编程语言> > 汇编语言

汇编语言

作者:互联网

汇编语言

基础知识

机器语言与汇编语言

\(e.g.:\)

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

机器指令:1000100111011000

汇编指令:mov ax, bx

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

汇编语言的组成

计算机原理补充

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

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

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

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

写入数据过程类似。

寄存器

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

几条简单的汇编指令(不区分大小写):
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位寄存器使用。

如上图,数据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执行,由编译器执行

汇编指令

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

[BX]和loop指令

[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