【汇编二】

内存中字存储、字单元的概念

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

单元即存放一个字型数据的内存单元,由两个地址连续的内存单元组成;高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节

将起始地址为N的字单元称为N地址字单元,比如:2地址字单元由2、3两个内存单元组成

DS寄存器

CPU要读写一个内存单元的时候,必须先给出这个内存单元的地址,在8086PC中,内存地址由段地址和偏移地址组成。8086CPU中有一个DS寄存器,通常用来存放要访问的数据的段地址。比如我们要读取10000H单元的内容,可用以下程序段:

   move bx,1000H
   move ds,bx
   move al,[0]

上面的三条指令将10000H(1000:0)中的数据读到al中。

使用mov指令,可完成两种传送:(1)将数据直接送入寄存器;(2)将一个寄存器中的内容送入另一个寄存器。
也可以使用mov指令将一个内存单元中的内容送入一个寄存器中。mov指令格式为: mov 寄存器名, 内存单元地址。
“[]”表示一个内存单元,“[0]”中的0表示内存单元的偏移地址,段地址默认放在ds中。

不禁疑惑,上面为什么要通过三行指令去把数据送给段寄存器而不是直接传送过去?
由于8086CPU硬件设计的问题,8086CPU不支持将数据直接送入段寄存器。如mov ds,1000H是非法的。所以我们得使用一个寄存器进行中转。

解释一下三条指令的意思:
(1).先将段地址1000H放入中转寄存器bx中,然后再放入ds
mov bx,1000H
mov ds,bx
(2).完成数据从1000:0单元到al的传送
mov al,[0]:“[]”表示一个内存单元,“[0]”中的0表示内存单元的偏移地址,段地址默认放在ds中。

mov add sub 指令

mov add sub的几种操作形式:

mov 寄存器,数据
mov 寄存器,寄存器
mov 寄存器,内存单元地址
mov 内存单元,寄存器
mov 段寄存器,寄存器

数据段

写几条指令,累加数据段123B0H–123BAH中的前3个字型数据
mov ax,123BH

mov ax,123BH
mov ds,ax
mov al,0
mov ax,[0]
mov ax,[2]
mov ax,[4]

一个字型数据占两个单元,所以偏移地址是0,2,4

CPU提供的栈机制

数据和程序有区别吗? 如何确定内存中的信息哪些是数据,哪些是程序?

没有区别,都是二进制信息。cs:ip指向的内存为指令,ds段寄存器指向的为数据、

栈 :特殊的访问方式的存储结构,先进后出 LIFO(last in first out)

CPU都有栈的设计,提供相关的指令来以栈的方式读取内存空间,我们编程的时候可以将一段内存当作栈来使用 PUSH(入栈)POP(出栈)操作都是以字为单位进行。pop从栈顶取出数据

push ax
pop ax 
push [0] 
pop [0] 
push ds 
pop ds 
push cs 
pop cs

将10000H~1000FH这段内存当做栈来使用
move ax,0123H   将0123H这一段地址给ax
push ax         ax入栈
move bx,2266H   将2266H这一段地址给bx
push bx        bx入栈

push ax 的执行,由以下两步完成:

    (1) sp = sp - 2 , SS:SP 指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;

    (2) 将ax中的内容送入SS:SP执行的内存单元,SS:SP此时指向新栈顶。

    由图可以看出, 8086CPU中,入栈时,栈顶从高地址向低地址方向增长。

    接下来,我们描述POP指令功能。 例如 pop ax :

    pop ax 的执行过程和push ax 刚好相反,由以下两步完成:

    (1) 将SS:SP指向的内存单元的数据送入ax中;

    (2) SP = SP + 2, SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
//仅进行ax,bx操作时
AX = 0123H
PUSH AX
SS = 1000H
SP = 000DH

BX = 2266H
PUSH BX
SS = 1000H
SP = 000BH 
栈顶往上移SP = SP - 2

POP AX 
AX = 2266
sp = sp + 2
sp = 000DH

//push 先操作sp再放数据
//pop  先拿数据再操作sp

然后一个一个出栈,拿出来。
注意:这里有一个栈顶的概念,每次放入一个段地址,栈顶就会上升“两格”(两个字节),每次出栈栈顶就会下降“两格”。此时栈顶下降后,内存中的数据并未消失。但是倘若重新写入数据,就可以将其覆盖。

&:我猜,数据所谓的“删除后”还能被恢复大概是这个原理,你存入的数据并没有被真正的删除,除非你把你的数据覆盖掉。内存相当于一个仓库吧,你要想把它拿掉,就需要填满新的东西。(仅猜测,没仔细了解过,以后有时间去学习一下)

CPU如何知道10000H~1000FH这段空间被当作栈来使用?当我们push ax 时,要将寄存器中的内容放在当前栈顶单元的上方,成为新的栈顶元素;pop ax等指令执行时, 要从栈顶单元中取出数据,送入寄存器中。那么CPU是怎么知道栈顶元素的呢?

如同CPU知道当前执行的指令所在位置,用CS、IP 来存放当前指令的段地址和偏移地址。在8086CPU中,有两个寄存器,段寄存器SS和寄存器SP, SS用来存放栈顶的段地址SP存放偏移地址。任意时刻,SS:SP指向栈顶元素。当执行push和pop指令时,CPU从SS何SP中得到栈顶的地址。

栈顶超界的问题

8086CPU不保证我们对栈的操作不会超界。这就是说,8086CPU只知道栈顶在何处(由SS:SP指示),而不知道读者安排的栈空间有多大。这点就好像,CPU只知道当前要执行的指令在何处(由CS:IP指示),而不知道读者要执行的指令由多少。从这两点上我们可以看出8086CPU的工作原理,它只考虑当前的情况;当前的栈顶在何处、当前要执行的指令是哪一条。

我们在编程时要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致超界;执行出栈操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。

有兴趣可以了解一下,现在对越界问题的防范,如windows的金丝雀机制

栈段

我们可以将一段内存定义为一个段。用一个段地址指示段,用偏移地址访问段内的单元。这完全是我们自己的安排。

对于数据段,将它的段地址放到DS中,CPU就将我们定义的数据段中的内容当作数据访问

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

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

将10000H-1000FH当作栈,初始状态栈为空,将AX,BX,DS的数据入栈
mov ax,1000H
mov ss,ax
mov sp,0010H

push ax
push bx 
push ds
//若要原封不动拿出来,栈先进后出的特性
pop ds
pop bx
pop ax

&:感觉栈的特性有点像压手枪子弹的感觉,hhhh

第一个程序:源程序从写出来到执行过程

1文本编辑汇编代码

2使用汇编语言编译程序对源程序进行编译生成目标文件

3再用连接程序对目标文件进行连接,生成可在操作系统中直接运行的可执行文件

可执行文件包含2部分内容:

​ 1.程序(从源程序中的汇编指令翻译过来的机器码和数据(源程序中定义的数据))

​ 2相关的描述信息(比如这个程序有多大,要占用多少内存空间等)

assume cs:aicat 
aicat segment
	mov ax,0123H
	mov bx,0456H
	
	mov ax,4c00H
	int 21H
aicat ends

sutong segment

sutong ends
end	

参考博客:https://blog.csdn.net/wen623/article/details/5689613?spm=1001.2014.3001.5502

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ELF (Executable and Linkable Format) 文件是可执行文件或共享库的格式。它包含了可执行代码和元数据(如符号表,程序头部等),但不包含汇编代码。要查看汇编代码,可以使用反汇编工具,如objdump来反编译ELF文件进制代码。 ### 回答2: 是的,elf文件可以看到汇编进制。ELF(可执行与可链接格式,Executable and Linkable Format)是一种常见的进制文件格式,用于存储可执行文件、目标文件、共享库和核心转储文件等。 通过使用相关工具,如反汇编工具,我们可以将ELF文件的机器指令转换为汇编指令。反汇编是一种将进制代码转换为可读性更高的汇编代码的过程。它允许我们分析和理解程序的逻辑和执行流程。 在反汇编过程,我们可以看到程序使用的各种指令、寄存器的操作、内存地址的引用等。这有助于我们理解程序的实际执行过程,并可以用于调试、性能分析、逆向工程等目的。 需要注意的是,ELF文件可能包含很多节(sections),而不仅仅是代码节。除了代码节(.text节)之外,还有数据节、符号表节、重定位节等。这些节包含了程序的各个部分和相关信息。因此,在查看ELF文件的汇编进制时,我们需要关注并选择适当的节来分析。 ### 回答3: elf文件是一种可执行文件格式,它包含了程序的进制机器代码、数据和其他用于执行程序的信息。所以通过查看elf文件的进制内容,我们可以间接地看到一部分汇编代码。 具体地说,elf文件是由不同的节(section)组成的,每个节都有不同的作用和内容。其包含了.text节,它存储了程序的进制机器代码,也就是汇编指令进制表示。通过查看.text节的内容,我们可以间接地了解到程序的汇编指令。 然而,直接从elf文件提取汇编代码是非常困难和复杂的,因为elf文件进制机器代码是经过编译和链接处理的,其还包含了许多与具体平台相关的信息和修饰。如果想要完整地查看汇编代码,最好的方法是使用专门的反汇编工具,将elf文件转换为可读的汇编代码。 总而言之,从elf文件的进制内容可以间接看到一部分汇编代码,但如果需要获取完整的汇编代码,最好使用反汇编工具进行处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值