王爽汇编语言个人总结(一)

说明:

该书总共17章,打算分三篇写个人总结,不包含习题。
然后单独出三个部分的习题篇,如有写错的地方,欢迎大家指出,希望和大家共同进步。

第一章 <基础知识>

汇编语言的组成

三类指令:

  1. 汇编指令: 机器码的助记符,有对应的机器码。
  2. 伪指令: 没有对应的机器码,由编译器执行,计算机并不执行。
  3. 其它符号: 如+、-、*、/ 等,没有对应的机器码。
内存单元

一个内存单元为 1 字节,也就是8比特
1 Byte = 8 bit
1 KB = 1024 Byte
1 MB = 1024 KB

总线的分类
1. 地址总线

一个CPU 有 N 根地址线,则可以说这个CPU的地址总线的宽度为 N。这样的CPU最多可以寻找 2 的 N 次方个内存单元。

2. 数据总线

数据总线的宽度决定了 CPU 和外界的数据传输速度。8 根数据总线一次可传送一个 8 位二进制数据(即一个字节)

8086 有 16 根数据线,可一次传送 16 位数据。
8088 只有 8 根数据线,一次只能传 8 位数据

3. 控制总线

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

内存储器的分类
从读写属性上看分为两类:
    随机存储器(RAM):
        可读可写,必须带电存储,关机后存储内容丢失。
    只读存储器(ROM):
        只读不可写,关机后内容不丢失。

第二章 <寄存器>

通用寄存器

8086CPU 的所有寄存器都是 16 位的,可存放两个字节。

AX 可分为 AH 和 AL
BX 可分为 BH 和 BL
CX 可分为 CH 和 CL
DX 可分为 DH 和 DL

以AX为例,AX位16位通用寄存器,AH为它的高八位,AL为它的低八位,均可单独使用。

字在存储器中的存储

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

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

由此可知,8086的16位通用寄存器可拆分为两个8位通用寄存器是出于兼容性考虑。

几条汇编指令
汇编指令                高级语言语法
move ax,18             AX=18
move ah,78             AH=78
add  ax,8              AX=AX+8
mov  ax,bx             AX=BX
add  ax,bx             AX=AX+BX
物理地址

将每一个内存单元的唯一地址称为物理地址

16位结构的CPU

运算器一次最多可以处理 16 位的数据;
寄存器的最大宽度为 16 位;
寄存器和运算器之间的通路为16位。

8086CPU给出物理地址的办法

8086CPU 采用一种在内部用两个16位地址合成的办法形成一个20位的物理地址。

CPU 中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
所以20位的 物理地址 = 段地址*16 + 偏移地址
由于段地址为16进制表示,故 *16 相当于段地址左移一位,也就是后面补一个0即可
同时段地址 * 16必然是 16 的倍数,所以一个段的起始地址一定是16的倍数
而偏移地址为16位,最大寻址能力为64KB,所以一个段的长度最大为64KB。

发现

CPU可以用不同的段地址和偏移地址形成同一个物理地址。
所以给定一个物理地址,我们无法确定它位于哪一个段中。

段寄存器

8086 CPU有4个段寄存器: CS、DS、SS、ES
CS: 代码段寄存器
DS: 数据段寄存器
SS: 堆栈段寄存器
ES: 附加段寄存器

CS 和 IP

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

在8086PC机中,任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存 M * 16 + N 单元开始,读取一条指令并执行。

修改CS、IP的指令

由于mov指令(传送指令)不能直接用于设置CS、IP的值
我们介绍一个最简单的可以修改CS、IP的指令: jmp指令

同时修改CS、IP格式: “ jmp 段地址: 偏移地址 ”
例如:jmp 2AE3:3,执行后: CS=2AE3H,IP=0003H
仅修改IP的内容:“ jmp 某一合法寄存器 ”
例如:

move ax,1000H
jmp ax

实验1 查看CPU和内存,用机器指令和汇编指令编程

Debug基本知识
用Debug 的 R 命令查看、改变CPU寄存器的内容;
用Debug 的 D 命令查看内存中的内容;
用Debug 的 E 命令改写内存中的内容;
用Debug 的 U 命令将内存中的机器指令翻译成汇编指令;
用Debug 的 T 命令执行一条机器指令;
用Debug 的 A 命令以汇编指令的格式在内存中写入一条机器指令。

第三章 <寄存器(内存访问)>

内存中字的存储

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

大端存储模式:数据的低位保存在内存中的高地址中,数据的高位保存在内存中的低地址中;
小端存储模式:数据的低位保存在内存中的低地址中,数据的高位保存在内存中的高地址中;

由此,这里应该是小端存储模式

DS 和 [address]

mov 指令可完成两种传送:

1.将数据直接送入寄存器
2.将一个寄存器中的内容送入另一个寄存器
mov al,[0]
在这条指令中,[]表示将引用一个内存单元,[0]中的0表示内存单元的偏移地址。
而偏移地址不能直接定位一个内存单元,故8086CPU会直接取DS中的数据为内存单元的段地址
mov、add、sub指令

合理设想:8086CPU内部有寄存器到段寄存器的通路,那么也应该有相反的通路。

可通过debug验证得: mov 寄存器, 段寄存器 是正确的指令

add 和 sub指令同mov一样,都有两个操作对象。

数据段

如何访问数据段中的数据

mov ax,1234H
mov ds,ax
mov ax,0
add ax,[0]
add ax,[1]
add ax,[2]

先进后出
后进先出

8086CPU的入、出栈(均以字为单位)

mov     ax,1234H
push    ax
-----------------
pop     ax

8086CPU如何知道栈顶和偏移地址 ???

8086寄存器中有两个寄存器,段寄存器 SS 和 寄存器SP,栈顶的段地址存放在 SS 中,偏移地址存放在SP中。任意时刻,SS:SP 指向栈顶元素。

push ax 的执行过程 ???

SP = SP - 2
将 ax 中的内容送入 SS:SP 指向的内存单元处

pop ax 的执行过程 ???

将 SS:SP 指向的内存单元处的数据送入 ax 中
SP = SP + 2

注意:

8086CPU 不保证我们对栈的操作不会超界。我们编程的时候要自己注意栈顶超界的问题。

push/pop 指令

使用格式:

push    寄存器      //将一个寄存器中的数据入栈
pop     寄存器      //用一个寄存器接收出栈的数据
---------------------------------------------
push    段寄存器    //将一个段寄存器中的数据入栈
pop     段寄存器    //用一个段寄存器接收出栈数据
---------------------------------------------
push    内存单元    //将一个内存字单元的字入栈
pop     内存单元    //用一个内存字单元接收出栈数据

注意:

一直压栈,直到栈满时SP = 0;如果再次压栈,栈顶将环绕,覆盖原来栈中的内容。所以一个栈的最大容量为64KB

第四章 <第一个程序>

一个源程序的执行过程

第一步: 编写汇编源程序
第二步: 对源程序进行编译连接
第三步: 执行可执行文件中的程序

源程序
assume cs:codesg        //申明一个代码段codesg
codesg segment          //定义代码段codesg起始
    mov ax,0123H
    mov bx,0456H
    add ax,bx
    add ax,ax
    mov ax,4c00H
    int 21H
codesg ends             //codesg定义结束
end                     //汇编程序结束标志

与结束相关的概念

在这里插入图片描述在这里插入图片描述

第五章 <[BX]和 loop 指令>

如何完整描述一个内存单元

  1. 内存单元的地址
  2. 内存单元的长度(类型)
[BX]

[BX]表示以BX的内容作为偏移地址
mov ax,[bx] 即: (ax) = ((ds)*16 + (bx))
mov [bx],ax 即: ((ds)*16 + (bx)) = (ax)

inc

inc bx 即:(bx) = (bx) + 1

Loop

格式

loop 标号

执行步骤

(cx) = (cx) - 1
判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行

案例:编程计算2的n次方

assume cs:codesg
codesg segment          //codesg代码段定义(开始)
    mov ax,2            //赋值
    mov cx,n-1          //设置循环次数
s:  add ax,ax           //标号
    loop s              //循环

    mov ax,4c00h        //程序返回
    int 21h
codesg ends             //codesg代码段定义(结束)
end                     //汇编程序结束

编程计算 123*236

assume cs:code
code segment
    mov     ax,123
    mov     cx,235
s:  add     ax,123
    loop    s

    mov     ax,4c00h
    int     21h
code ends
end

注意:在汇编源程序中,据不能以字母开头,字母开头需在前面加0
例如:

assume cs:code 
code segment
    mov     ax,0ffffh
    mov     ds,ax
    mov     bx,6

    mov     al,[bx]
    mov     ah,0

    mov     ax,0

    mov     cx,3
s:  add     dx,ax
    loop    s

    mov     ax,4c00h
    int     21h
code ends
end
MASM与DEBUG中编写汇编源程序区别

MASM

mov     al,[0]      //将常数0送入al中(与mov al,0 含义相同)
mov     al,ds:[0]   //(al) = ((ds)*16 + (bx))
mov     al,[bx]     //(al) = ((ds)*16 + (bx))
mov     al,ds:[bx]  //含义同 mov    al,[bx]

DEBUG

mov     al,[0]      //(al) = ((ds)*16 + bx)
实验:

编程,向内存0:2000:23F依次传送数据063(3FH)

assume      cs:code
code segment
    mov     ax,20h
    mov     ds,ax
    mov     bx,0
    mov     cx,40h
s:  mov     [bx],bl
    inc     bx
    loop    s
    
    mov     ax,4c00h
    int     21h
code ends
end

第六章 <包含多个段的程序>

如何循环操作多个数据

assume  cs:code
code    segment
    dw  0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

    mov     bx,0
    mov     ax,0
    mov     cx,8
s:  add     ax,cs:[bx]
    add     bx,2
    loop    s

    mov     ax,4c00h
    int     21h
code    ends
end

注:
dw 表示定义字型数据。
dw 定义的数据放在代码段的最开始,所以偏移地址为 0

思考 ???
dw 定义的数据既然放在代码段最开始,而程序执行是根据CS:IP来的,这样会不会产生问题?
这可能会将数据当成指令来执行,出现未知的错误。

assume  cs:code
code    segment
            :
            :
            数据
            :
            :
start:              //程序开始的位置
            :
            :
            代码
            :
            :
code ends
end start
w 定义的数据放在代码段的最开始,所以偏移地址为 0

<font color="green">思考 ???</font>
dw 定义的数据既然放在代码段最开始,而程序执行是根据CS:IP来的,这样会不会产生问题?
这可能会将数据当成指令来执行,出现未知的错误。

assume cs:code
code segment
:
:
数据
:
:
start: //程序开始的位置
:
:
代码
:
:
code ends
end start

  • 53
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linux-hzh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值