汇编学习笔记

学习汇编

这篇文章用来记录王爽版8086cpu的学习历程

两个重要的知识点

学习汇编语言,首先必须了解两个知识点:寄存器和内存模型。

先来看寄存器。CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。

但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。

寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的。有人比喻寄存器是 CPU 的零级缓存。

王爽8086CPU中的需要记住寄存器

指令

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

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

CPU要工作必须向它提供指令和数据,指令和数据在存储器中存放,也就是我们平时说的内存,CPU不能使用磁盘上的数据。

CPU要从内存中读数据,首先要指定存储单元的地址。

存储器被划分为若干个存储单元从0开始顺序编码,例如一个存储器有128个存储单元,它可以存储128个Byte,编码从0~127。

最小信息单位bit(比特),也就是一个二进制位。一个存储单元可以存储8个bit,即8位二进制数。8个bit组成一个Byte,也就是一个字节。微型机存储器的存储单元可以存储一个Byte,即8个二进制位。

1KB=1024B

1MB=1024KB

1GB=1024MB

1TB=1024GB

地址总线上能传送多少个不同的信息,CPU就可以对多少个存储单元进行寻址。一根导线可以传送的稳定状态只有1高电平和0低电平两种,10根导线可以传送10位二进制数据,而10位二进制数可以表示2的10次方个不同的数据。一个CPU有N根地址线,则可以说这个CPU的地址总线的宽度为N,这样的CPU最多可以寻找2的N次方个存储单元。

测验题

例,1个CPU的寻址能力为8KB,那么它的地址总线的宽度为13。 解析:1KB=1024B,8KB=1024B*8=2^N, N=13

例题,8080、8088、80286、80386的地址总线宽度分别位16根、20根、24根、32根,则他们的寻址能力分别为:64(KB)、1(MB)、4(MB)、4(GB)。 解析:一个内存单 元=1Byte

8根数据总线一次可以传送8位二进制数据(即一个字节)。

例,8080、8088、8086、80286、80386的数据总线宽度分别为8根、8根、16根、16根、32根,则他们一次可以传送的数据为:1B、1B、2B、2B、4B.

例,从内存中读取1024字节的数据,8086至少读512次,80386至少读256次。

解析:8086的数据总线宽度为16根(即一次传送的数据为2B) 1024B/2B=512,同理1024B/4B=256。

在存储器中指令和数据没有任何区别,都是二进制信息。

就像棋盒中的黑白棋子,只有在棋盘中展开对弈时才有意义,在棋盒中是没有实际意义的

地址总线的宽度决定了CPU的寻址能力;

数据总线的宽度决定了CPU与其他器件进行数据传送时的一次数据传送量;

控制总线的宽度决定了CPU对系统中其他器件的控制能力。

内存地址空间的大小受CPU地址总线宽度的限制,8086CPU的地址总线宽度为20,可以传送2^20个不同的地址信息,即可以定位2^20个内存单元,则8086PC的内存地址空间大小为1MB。

mov 指令

将逗号右边的给逗号左边的

要保证寄存器与寄存器之间 数据与寄存器之间 的位数一致性

寄存器是相互独立的, al就是al ah就是ah 不会相互影响

16位寄存器进行16位运算 保存16位数据 8位寄存器进行8位运算保存8位数据

指令是有长度的,一条指令可以有多个字节组成

指令的执行过程

cpu从cs:ip 所指向的内存单元中读取指令,存放到指令存储器中

ip=ip+所读指令的长度,从而指向下一条指令

执行指令缓存器中的内容,回到第一步

在进行数据传送或运算时,要注意指令的两个操作对象的为啥应当是一致的,如下面的指令都是错误的:

mov ax,bl (在8位寄存器和16位寄存器之间传送数据)

mov bh,ax (在16位寄存器和8位寄存器之间传送数据)

mov al,2000 (8位寄存器最大可存放值位255的数据)

add al,100H (将一个高于8位的数据加到一个8位寄存器中)

CPU访问内存单元时,要给出内存单元的地址,所有的内存单元构成的存储空间是一个一维的线性空间,每个内存单元在这个空间都有唯一的地址,我们将这个唯一的地址称为物理地址。CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。

8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力,而8086CPU又是16位结构,在内部一次性处理、传输、暂时存储的地址位16位。8086CPU采用一种在内部用两个16位地址(段地址+偏移地址)合成的方法来形成一个20位的物理地址。

物理地址=段地址SAx16+偏移地址EA 或 物理地址=基础地址+偏移地址

“段地址x16”更有一种说法是左移4位(指二进制位)。一个数据的二进制形式左移1位,相当于该数据乘以2;左移N位,相当于该数据乘以2的N次方。

左移运算的理解:例,一个数据为2H,二进制形式为10B,对其进行左移运算有:

左移位数二进制十六进制十进制

010B2H2

1100B4H4

21000B8H8

310000B10H16

4100000B20H32

段地址x16必然是16的倍数,一个段的起始地址一定是16的倍数;偏移地址为16为,16位地址的寻址能力为64KB,所以一个段的长度最大为 64KB。CPU可以用不同的段地址和偏移地址形成同一个物理地址。偏移地址16位,变化范围为0~FFFFH,仅用偏移地址来寻址最多可寻 64KB 个内存单元。

给定段地址为0001H,仅通过变化偏移地址寻址,CPU 的寻址范围为0010H到1000FH。

解析:物理地址=SA16+EA,EA的变化范围为0H~ FFFFH ;

物理地址范围为(SA16+0H) ~ (SA16+ffffH),现在SA=0001H,那么寻址范围为 (0001H16+0H)’ ~ (0001 H*16+FFFFH)=0010H~1000FH

有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为1001H ,最大为2000H。当段地址给定为1001H 以下和2000H 以上, CPU无论怎么变化偏移地址都无法寻到20000H单元。

解析:物理地址= SA16+EA;20000H = SA16+EA;SA= (20000H- EA) /16=2000H-EA/16;EA取最大值时, SA=2000H-ffffH/16=1001H;SA为最小值,EA取最小值时,SA=2000H-0H/16=2000H,SA为最大

8086 cpu 设计者给了它20根地址线 表示范围 0~FFFFFH

地址线的数量决定了cpu的寻址能力

地址加法器决定地址的计算方式

段地址* 16(10H)+偏移地址 =物理地址 ,因为8086cpu有20根地址线,16位寄存器无法表示,所以采取这样的方式

段地址 *16 =基础地址

基础地址+偏移地址=物理地址

物理地址

段地址*10H +偏移地址(0~FFFFH)=物理地址

冒号前段地址 冒号后偏移地址

U指令 将某个内存地址 开始的字节 全部当做指令

D 指令 将某个内存开始的字节 全部当成数据

ip寄存器和指令有关

CPU是怎样区分指令和数据的?

8086cpu中 在任意时刻,cpu将cs ip所指向的内容 全部当成指令来执行

在内存中指令和数据是没有任何区别的,都是二进制信息,cpu只有在工作的时候才将有的信息当做指令 有的信息当做数据,cpu根据什么将内>存中的信息当做指令的话,cpu将cs ip 指向的内存单元中的内容当做指令

指令和数据在内存中有区别吗?是没有区别的

在cpu中的cs段地址寄存器和 ip这个偏移地址寄存器 组合的时候从中读取内容当做指令来执行

cs:ip 决定了cpu从哪里开始读取指令 指令是有长度的,一条指令可以由多个字节构成

指令的执行过程

cpu从cs:ip 所指向的内存单元读取指令,存放到指令缓存器中

ip=ip+所读指令的长度,从而指向下一条指令

执行指令缓存器中的内容,回到步骤一

明白ip寄存器和指令的关系

汇编指令 jmp jump的简写

这是一条转移指令,可以修改cs和ip这2个寄存器

两种写法

Jum 2000:0

Jum 寄存器

例题

假设cs=2000H ,ip=0000 写出下列指令的执行过程

a 2000:0 CS=2000H IP=0

mov ax,662H CS=2000H IP=0+3=3

jmp 1000:3 CS=2000H IP=3+5=8

mov cx,ax

a 1000:0 CS=1000H IP=3

mov ax,0123H

mov ax,0 CS=1000H IP=3+3=6

mov bx,ax CS=1000H IP=6+2=8

jmp bx CS=1000H IP=8+2=10(A)

mov cx,0

Debug 调试工具

r 可以查看和改变寄存器中的内容

d 可以查看内存中的内容

u 可以将内存中的机器指令翻译成汇编指令

a 可以以汇编指令的格式在内存中写入一条汇编指令

t 执行 当前 cs :ip 所指向的机器指令

e 可以改写内存中的内容

p 跳过loop

g 跳到指定位置

一个字型数据 存放在内存中 可以有2个连续的地址的内存单元组成

高地址内存单元存放 字型数据的高位字节

低地址 内存单元存放 字型数据的地位字节

0 20H

1 4EH

2 12H

3 00H

问题

地址0存放的 字节型数据是多少? 20H

地址0存放的 字型数据是多少? 4E20H 4EH是高位字节 20H是低位字节

地址2 中存放的字节型数据是多少? 12H

地址2中存放的字型数据是多少? 0012H

地址1中存放的 字型数据是多少? 124EH 12H是高位字节 4EH是低位字节

CPU 通过内存地址去访问内存

DS 段地址寄存器 访问数据用的

mov al,ds:[0]

mov移动指令 逗号左边是CPU中的al寄存器,逗号右边是内存地址,0是偏移地址,[]表示得到里面的内容.

小结:

字型数据和字节型数据 在内存中的存放

字型数据在内存中存储时,需要2个地址连续的内存单元存放,高位字节存放在高地址中,低位字节存放在低地址中

CS 和指令有关

DS 段地址寄存器 数据段地址寄存器 和数据有关

CS:IP 指令从哪里来

DS 数据从哪里来

修改寄存器中的内容 去控制cpu 进而控制计算机

在8086cpu中,在任意时刻将段地址寄存器ss和偏移地址寄存器sp所组合出来的内存地址当做栈顶标记

push ax 修改sp寄存器中的数值 sp=sp-2 将ax中字型数据 ->ss:ip所组合内存地址中

pop ss:ip 所组合出来的内存地址中的字型数据 ->bx

修改栈顶标记 sp=sp+2 成为新的栈顶标记 出栈

我们可以 决定栈顶标记在哪里

栈在哪里 (箱子在哪里) 栈的大小(箱子的大小)

栈的设置

起始地址 + 你所设定的栈的大小的字节数

一个栈 最大的空间能设置为多少?

SP寄存器的变化范围是多少?

0~FFFFH 65536/2=32768 字型数据

SS=2000 sp=0 设置一个存放32768个字型数据的箱子

栈的作用

临时性保存数据

用栈进行数据交换

保存在栈中 每执行一条t指令 就会将寄存器保存到栈中

Call ip 保存到栈中 为了让ret指令可以从栈中拿回来

我们如何让cpu按照我们的安排去访问这些内存段呢?

对于数据段来说,段地址 -> ds段寄存器 [0] [1] …… mov add sub 指令去访问这些内存单元

那么CPU就会将我们定义的数据段中的内容 当做数据来访问

对于代码段来说,我们可以通过修改 cs,ip 这2个寄存器,去指向我们定义的代码段

这样cpu就执行我们定义的代码段中的指令

对于栈段来说,我们可以通过修改,ss,sp这2个寄存器去决定栈顶标记在哪里

这样CPU在执行栈的操作时,比如pop,push就会将我们定义的栈段当做栈空间使用

不管我们如何安排,cpu将内存中某段内容当做指令 是因为cs:ip 指向那里

cpu将某段内存当做栈空间是因为 ss:sp 指向那里

数据从哪里来,临时性的数据存放到哪里去,取决于我们cpu中的地址寄存器的设置 cs ip ss sp ds 寄存器

寻址方式的思维导图

子程序

汇编中的子程序调用(对应的高级语言的部分-函数吊用) call 子程序的名字:执行到这里,cpu 会做两件事。一是保存,二是跳转

保存:ip 指令指针。如果是段内跳转。会将当前的ip 偏移值压入栈。如果是段间跳转,会将cs 段寄存器的段地址,和ip 指令指针(偏移值) 压入栈中

跳转:根据子程序的名字跳转到指定的位置

子程序的格式

名字 pro 程序入口

内容 将在这个子程序中会使用到的寄存器压入栈中(在程序结束时要将寄存器弹出栈)

在程序执行结束,子程序末尾:ret 表达式  (段内是ret 段间是retf) 子程序名字 endp 程序执行结束后,堆栈会将要入栈的cs 和ip 弹出栈。让程序返回调用处继续向下执行。 关于ret 后面的表达式 :会改变栈的指针,也就是在CS 和IP 都被弹出栈后,表达式的值就是栈的指针SP 还要移动的字节数

关于参数:

使用寄存器来传递

在调用子程序之前先将参数压入栈中

理解了汇编中子程序的调用,再返回来看高级语言中函数的调用就不难了。在高级语言中定义了函数名是函数的起始地址。所以在调用函数时,都会使用函数名,其实就是相当于跳转目的地址,在堆栈中存放的是在函数调用中的临时变量,存放的函数执行完之后继续执行的地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349