《汇编语言》学习笔记(第三章、第四章)

第3章、寄存器(内存访问)

3.1 内存中字的存储

字单元:存放一个字型数据(16位)的内存单元,由两个连续的内存单元组成,高地址内存单元放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节。

将起始地址为N的字单元称为N地址字单元。

3.2 DS和[address]

DS寄存器:通常用来存放要访问数据的段地址

[address]表示一个偏移地址为address的内存单元,段地址默认放在ds中

mov指令将一个内存单元中的内容送入另一个寄存器中:

mov 寄存器名 [内存单元的偏移地址]

指令执行时,8086CPU自动取ds寄存器中的数据为内存单元的段地址。

所以我们在将一个内存单元中的内容送入一个寄存器中时,需要提前将内存单元的段地址放入ds中。

8086CPU不支持将数据直接送入段寄存器,只能通过另一个寄存器中转,先将段地址送入一个一般的寄存器,如bx,再将bx中的内容送入ds。

3.4 mov、add、sub指令

mov 寄存器,数据 比如: mov ax,8

mov 寄存器,寄存器 比如: mov ax,bx

mov 寄存器,内存单元 比如: mov ax,[0]

mov 内存单元,寄存器 比如: mov [0],ax

mov 内存单元,段寄存器 比如: mov [0],cs

mov 段寄存器,内存单元 比如: mov cs,[0]

mov 段寄存器,寄存器 比如: mov ds,ax

mov 寄存器,段寄存器 比如:mov ax,ds

mov指令几乎都可以互相传递,唯一要注意的是:不能将数据直接送入段寄存器!

可以将内存单元的内容送入段寄存器,也可以将寄存器的内容送入段寄存器,但是唯独不能将数据直接送入段寄存器!

在这里插入图片描述

3.7 CPU提供的栈机制(ss和sp)

在基于8086CPU编程的时候,可以将一段内存当作栈来使用。

8086CPU的入栈和出栈操作都是以字为单位进行的。

push和pop指令执行时,CPU从SS和SP中得到栈顶的地址

段寄存器SS,存放栈顶的段地址,SP寄存器存放栈顶的偏移地址,任意时刻,SS:SP指向栈顶元素

8086CPU中,入栈时,栈顶从高地址向低地址方向增长。

push ax表示将寄存器ax中的数据送入栈中,由两步完成。

  1. SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
  2. 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。
image

pop ax表示从栈顶取出数据送入ax,由以下两步完成。

  1. 将SS:SP指向的内存单元处的数据送入ax中;
  2. SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。

当栈为空的时候,不存在栈顶元素,此时SS:SP指向栈的最底部单元下面的单元。该单元的偏移地址为栈最底部的字单元的偏移地址+2!

一定要注意,栈最底部的字单元的地址并不是最底部的内存单元的地址!

由于栈从栈底到栈顶是从高地址到低地址的,而字单元的地址是两个字节单元地址中的较低的那一个,所以栈最底部的字单元的地址并不是最底部的内存单元的地址!

3.8 栈顶超界的问题

栈顶超界会导致其他内存空间的指令或数据被覆盖,产生无法想象的后果。

8086CPU不保证我们对栈的操作不会超界。

我们在编程时要自己操心栈顶超界的问题。

3.9 push、pop指令

push 寄存器 将一个寄存器中的数据入栈
pop 寄存器 出栈,用一个寄存器接收出栈的数据

push 段寄存器 将一个段寄存器中的数据入栈
pop 段寄存器 出栈,用一个段寄存器接收出栈的数据

image

实验

  1. 将10000H~1000FH这段空间当作栈,初始状态栈是空的;
  2. 设置AX=001AH,BX=001BH;
  3. 将AX、BX中的数据入栈;
  4. 然后将AX、BX清零;
  5. 从栈中恢复AX、BX原来的内容。
mov ax, 1000H 
mov ss, ax 
mov sp, 0010H    ;初始化栈顶
mov ax, 001AH
mov bx, 001BH 

push ax 
push bx    ;ax、bx入栈

sub ax, ax   ;将ax清零,也可以用mov ax,0,
             ;sub ax,ax的机器码为2个字节,
             ;mov ax,0的机器码为3个字节。

sub bx, bx 

pop bx  ;从栈中恢复ax、bx原来的数据
pop ax  ;

将10000H~1000FH这段空间当作栈,初始状态栈是空的;

mov ax, 1000H
mov ss, ax
mov sp, 0010H

空栈时SP指向的内存单元的偏移地址为栈最底部的字单元的偏移地址+2

空栈时SP指向的内存单元的偏移地址为栈最底部的字单元的偏移地址+2

空栈时SP指向的内存单元的偏移地址为栈最底部的字单元的偏移地址+2

问题 3.12

因为push、pop在执行时只能修改SP,所以栈顶的变化范围是0~FFFFH,一个栈最大可以被设为64KB。

小于64KB的栈,栈顶超界时会覆盖别的内存单元;

而等于64KB的栈,栈顶超界时,SP会溢出,栈顶将环绕,覆盖原来栈中的内容。

段的综述

我们可以用一个段存放数据,将它定义为“数据段”;

我们可以用一个段存放代码,将它定义为“代码段”;

我们可以用一个段当作栈,将它定义为“栈段“。

对于数据段,将它的段地址放在DS中,用mov、add、sub等访问内存单元的指令时,CPU就将我们定义的数据段中的内容当作数据来访问;

对于代码段,将它的段地址放在CS中,将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令;

对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作的时候,比如执行push、pop 指令等,就将我们定义的栈段当作栈空间来用。

CPU将内存中的某段内容当作代码,是因CS:IP指向了那里; CPU将某段内存当作栈,是因为SS:SP指向了那里。

一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以什么也不
是。关键在于CPU中寄存器的设置,即CS、IP、SS、SP、 DS的指向。

实验 2

我们可以用“d 段地址:偏移地址 ”的方式查看指定内存单元的内容,其中的段地址存储在DS段寄存器中。

我们既可以以数据的方式直接给出段地址,也可以以段寄存器的方式给出段地址。

image
image

第4章、第一个程序

4.1 一个源程序从写出到最终执行的过程

image
  1. 使用文本编辑器用汇编语言写汇编程序,产生了一个存储源程序的文本文件
  2. 使用汇编语言编译程序对文件中的源程序进行编译,产生目标文件
  3. 使用连接程序对目标文件进行连接,产生可在操作系统中直接运行的可执行文件
  4. 操作系统执行可执行文件:
    1. OS将可执行文件中的机器码和数据加载入内存
    2. 进行相关的初始化(比如设置CS:IP指向第一条要执行的指令)
    3. 由CPU执行程序。

4.2 源程序

在汇编语言源程序中有两种指令:

  • 汇编指令:有对应的机器码,可以被编译为机器指令,最终被CPU执行
  • 伪指令:没有对应的机器码,由编译器来执行
1.asm
assume cs:codesg 将用作代码段的段codesg和段寄存器cs联系起来。

codesg segment 定义一个段,段的名称为“codesg”,这个段从此开始
               codesg是一个标号,作为一个段的名称,最终被编译连接成一个段的段地址

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

    mov ax, 4c00H 
    int 21H 这两条指令实现程序的返回

codesg ends 名称为“codesg”的段到此结束

end 编译器在编译汇编程序的过程中,碰到了伪指令end,结束对源程序的编译

源程序:源程序文件中的所有内容称为源程序

程序:源程序中最终由CPU执行处理的指令或数据(即源程序中去掉伪指令的部分)

程序最先以汇编指令的形式存在源程序中,经过编译、连接后变成机器码,存在可执行文件中。

可执行文件是怎么得到运行的?

一个程序P2在可执行文件中,则必须有一个正在运行的程序P1,将P2从可执行文件中加载入内存后,将CPU的控制权交给P2,P2才能得以运行。P2开始运行后,P1暂停运行。而当P2运行完毕后,应该将CPU的控制权交还给使它得以运行的程序P1,此后P1继续运行。

程序返回:一个程序结束后,将CPU的控制权交还给使它得以运行的程序

所以需要在程序的末尾添加返回的程序段。

    mov ax, 4c00H 
    int 21H 这两条指令实现程序的返回

image

4.5 编译连接

首先在DOSBox Options.bat中对DOSBox中的虚拟目录和本地电脑中的真实目录挂载(mount)

image

如图,将DOSBox中的d:目录与本地路径的D:\DOSBox\masm挂载,即访问DOSBox中的d:目录相当于访问D:\DOSBox\masm

image

连接的作用:

  1. 当源程序很大时,可以将它分为多个源程序文件来编译,每个源程序编译成目标文件后,再用连接程序将它们连接在一起,生成一个可执行文件
  2. 程序中调用了某个库文件中的程序,需要将这个库文件和该程序生成的目标文件连接在一起,生成一个可执行文件
  3. 一个源程序编译后,得到了存有机器码的目标文件,目标文件中的有些内容还不能直接用来生成可执行文件,连接程序将这些内容处理为最终的可执行信息。所以,在只有一个源程序文件,也不需要调用某个库中的子程序的情况下,也必须用连接程序对目标文件进行处理,生成可执行文件。

4.6 以简化的方式进行编译和连接

在masm(link)后面加上被编译(连接)的源程序文件(目标文件)的路径、文件名,在结尾再加上分号,编译器就会在编译(连接)过程中自动忽略中间文件的生成。

image
image

4.7 exe的执行

image

在可执行文件的目录下输入可执行文件的名字即可执行(由于我将DOSBox中的d:目录与本地路径的D:\DOSBox\masm挂载,而可执行文件又在D:\DOSBox\masm下,所以此时就相当于在可执行文件所在的目录下)

4.8 谁将可执行文件中的程序装载入内存并使它运行?

程序P1要想运行,必须要有一个正在运行的程序P2,将P1从可执行文件中加载入内存,将CPU的控制权交给它,P1才能运行;P1运行完毕后,要将CPU的控制权还给使它得以运行的程序P2。

操作系统是由多个功能模块组成的庞大、复杂的软件系统,操作人员通过一个称为shell(外壳)的程序来操作计算机系统进行工作。

在DOS中有一个程序command.com,在DOS中被称为命令解释器,也就是DOS系统的shell

DOS启动时,先完成其他重要的初始化任务,然后运行command,由command执行用户输入的命令,比如:cd、dir、type。

在DOS中,command处理各种输入,命令或要执行的程序的文件名,我们就是通过command来进行工作的。

用户想要执行一个程序:

  1. 在command中输入该程序的可执行文件的名称
  2. command根据文件名找到可执行文件
  3. 将可执行文件中的程序加载入内存
  4. 设置CS:IP指向程序的入口
  5. command暂时停止运行,将CPU的控制权交给另一个程序
  6. 另一个程序运行完后,CPU控制权返回到command中,等待用户的输入。

4.9 程序执行过程的跟踪

command将程序加载入内存,CS:IP一指向程序的入口,command就放弃了CPU的控制权,直到程序结束,所以我们无法逐条指令看到程序的执行过程。

而Debug将程序加载入内存后并不放弃CPU的控制,单步执行程序。所以我们使用Debug来逐条执行指令,查看每一条指令的执行结果,跟踪执行过程。

debug a.exe,debug将程序从a.exe中加载入内存

image

程序被装入内存的位置:


image

(1) 程序加载后,ds中存放着程序所在内存区的段地址(SA),这个内存区的偏移地址为0,则程序所在的内存区的地址为ds:0;

(2) 这个内存区的前256个字节中存放的是PSP, DOS用来和程序进行通信。从256字节处向后的空间存放的是程序。

(3) 程序的物理地址是SAx16+0+256=(SA+16)x16+0,用段地址和偏移地址表示为:SA+10H:0。

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

推荐阅读更多精彩内容