码迷,mamicode.com
首页 > 编程语言 > 详细

汇编语言第三章总结

时间:2018-11-01 22:27:34      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:指针   如何   数据线   物理地址   一个   交换   lifo   style   方法   

在csapp中的新理解:

 (1)栈向下增长,栈顶元素的地址是所有栈中元素地址中最低的

(2)因为栈和程序代码以及其他形式的程序数据都是放在同一内存中,所以程序可以用标准内存寻址方法访问栈内的任意位置

(3)加载有效地址(load effective address)指令leap实际上是movq指令的变形,它的指令形式是从内存读数据到寄存器,但实际上它根本就没有引用内存。

         例:leap (%rdx),%rax

         它的第一个操作数看上去是一个内存引用,但该指令并不是从指定位置读入数据,而是将有效地址写入到目的操作数。这条指令可以为后面的内存引用产生指针。目的操作数必须是一个寄存器。

书上内容的总结:

3.1 内存中字的存储

  • 字单元:即存放一个字型数据(16位)的内存单元,由两个地址连续的内存单元组成。
  • 小端法:高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的地位字节
  • 低地址的内存单元作为字数据地址
  • N地址字单元:起始地址为N的字单元
  • 任何两个地址连续的内存单元,N号单元和N+1号单元,可以将他看成两个内存单元,也可看成一个地址为N的字单元的高位字节单元和地位字节单元

3.2 DS和[address]

  • DS段寄存器:用来存放要访问数据的段地址
  • ds的赋值:(8086不支持将数据直接送入段寄存器的操作,只好用一个寄存器来进行中转)
mov bx,1000H
mov ds,bx
  • [...]表示一个内存单元,[...]中的数字表示内存单元的偏移地址
  • 8086CPU自动取ds中的数据为内存单元的段地址

3.3 字的传送

  • 8086是16位结构,有16根数据线,可以一次性传送16位的数据,即可以一次性传送一个字
  • 传送字型数据的实例:
mov ax,1000h
mov ds,ax        ;改变ds的值
mov ax,[0]       ;将地址为10000的字数据送入ax
mov bx,[2]       ;将地址为10002的字数据送入bx
mov cx,[4]       ;将地址为10004的字数据送入cx

3.4 mov、add、sub指令

  • mov、add、sub指令的总结:

技术分享图片  技术分享图片  技术分享图片

  • 注意事项:

1)指令中两个操作数的长度要一样(mov ax,cl  mov al,300 这都是错误的)

(2)关于立即数:不能作为第一个操作数(目的操作数);在完整的汇编程序中,作第二个操作数(源操作数)时,若最高位是十六进制的a~f,前面要加零

(3)两个内存单元之间不能直接传送数据

(4)不能使用mov指令直接改变cs和ip的值

(5)关于段寄存器:两个段寄存器之间不能直接传送;不能把常数送入段寄存器

3.5 数据段

  • 可以将一组长度为N(N<=64KB)、地址连续,起始地址为16的倍数的内存单元当作专门存储数据的内存空间——定义数据段
  • 用ds存放数据段的段地址

3.6 栈

  • 后进先出(LIFO):最后进入这个空间的数据,最先出去
  • 两个基本操作:入栈(PUSH)和出栈(POP)
push ax  ;表示将寄存器ax中的数据送入栈中
pop ax   ;表示从栈顶取出数据送ax

技术分享图片

(push 内存单元和pop 内存单元  实际上实现了从内存单元到内存单元的传送)

  • 注意事项:

(1)操作对象不能是常数

(2)pop 段寄存器 中,段寄存器不能是CS和SS

(3)出栈和入栈以字为单位

3.7 CPU提供的栈机制

  • 段寄存器SS:栈段段寄存器    寄存器SP:栈指针寄存器
  • 栈顶的段地址存放在SS中,偏移地址存放在SP中
  • 任意时刻,SS:SP指向栈顶元素
  • 栈顶的物理地址:SS*16+SP   
  • push的执行:(入栈时,栈顶从高地址向低地址方向增长

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

  • pop的执行:

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

  • 栈为空时,就相当于栈中唯一的元素出栈,此时栈顶指向的单元的偏移地址为栈最底部的字单元的偏移地址+2
  • pop操作前的栈顶元素,在pop以后,依然存在,但是它已不在栈中,当再次执行push时,它将被覆盖

3.8 栈顶超界问题

  • 当栈空时,再使用pop出栈
  • 当栈满时,再使用push入栈
  • 有可能取到栈以外未知的值,若栈段的大小为64KB,会使栈指针重新指向最后进栈的元素的地址,重新又执行指令
  • 栈空间的大小我们要自己管理

3.9 栈段

  • 一个栈段最大可以设为64KB

(push,pop等栈操作,修改的只是SP,也就是说,栈顶的变化范围最大为:0~FFFFH)

  • 初始化栈段:
;将10000h~1000fh这段空间当作栈
mov ax,1000h
mov ss,ax          ;设置栈的段地址,ss=1000h
mov sp,0010h    ;设置栈顶的偏移地址,因栈为空,所以sp=0010h

3.10 利用栈保护现场和实现数据交换

  • 保护现场:
mov ax,1000h
mov ss,ax
mov sp,0010h   ;初始化栈顶
mov ax,001Ah
mov bx,001Bh
push ax
push bx

pop bx   ;从栈中恢复ax,bx原来的值
pop ax
  • 实现数据交换:
;初始化的栈段和ax,bx的值的代码同上
push ax
push bx

pop ax   ;当前栈顶是bx中原来的数据:001Bh,此时使ax=001Bh
pop bx   ;此时栈顶使ax中原来的数据:001Ah,此时使bx=001Ah

课后思考:

思考了一下,如何使用栈操作实现字节数据的交换?

我认为首先要把字节数据扩展成字数据,再进行栈操作实现字节数据的交换。

在csapp中介绍了一系列零扩展和符号扩展的指令(AT&T汇编),其中,movzbw则是将做了零扩展的字节传送到字,也许可以如下进行交换:

movzbw %al,%eax  ;将al中的字节数据做零扩展送到ax中
movzbw %bl,%ebx
pushl %eax
pushl %ebx

popl %eax
popl %ebx

 

汇编语言第三章总结

标签:指针   如何   数据线   物理地址   一个   交换   lifo   style   方法   

原文地址:https://www.cnblogs.com/kwcymino/p/9892538.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!