汇编指令初步(AT&T格式)

目录

一、寄存器的种类

二、mov指令

三、lea指令

四、跳转指令

五、压栈/弹栈指令

六、sub/add指令


一、寄存器的种类

80386有如下通用寄存器:

  • AX,BX,CX,DX;SI,DI;SP,BP(16位)
  • AH,AL;BH,BL;CH,CL;DH,DL(8位)
  • 以E开头的寄存器为32位
    • EAX(累加器,是算术运算的主要寄存器)
    • EBX(基址寄存器,在内存中寻址时存放基址)
    • ECX(计数器)
    • EDX(数据寄存器)
    • ESI(源变址)
    • EDI(目标变址)
    • ESP(堆栈指针)
    • EBP(基址指针)
    • EIP(程序计数器,存储的是将要执行的下一条指令放在内存中的地址)
    • EFLAGS(保存的是根据运算得到的结果设置的条件码ZF,CF,SF,OF)
  • 段寄存器:
    • CS:代码段寄存器
    • SS:堆栈段寄存器
    • DS:数据段寄存器
    • ES、FS、GS:附加数据段寄存器
  •  汇编指令初步(AT&T格式)_第1张图片(该图摘自教案,侵删)
  • 内存有大小端之分,寄存器没有
  • 整型占四个字节,短整型占两个字节,字符型占一个字节
  • 指向字符/整数/字符串/数组的指针均占用四个字节(其实指针存储的就是数据在内存中的地址)

二、mov指令

mov后的字母表示操作数的长度

使用mov指令可以在寄存器与寄存器之间、内存与寄存器之间传送数据

  • movl:用于传送32位的长字值(四个字节)/  传送双字
  • movw:用于传送16位的字值(两个字节)/  传送字
  • movb:用于传送8位的字值(一个字节)/  传送字节

mov指令可以根据目的操作数的大小来决定传送的字节数

举例:movl $4, %eax           执行的是将立即数4送入到寄存器eax中;

movl %ebx, %eax      执行的是将寄存器ebx中的送入寄存器eax中;

           movl $values,%eax    表示将values的首地址送入寄存器eax中;

           movl values,%eax    表示将以values为首地址共四个字节单元表示的值送入到寄存器eax中;

  • movsbl %dh, %eax 表示将%dh进行符号扩展之后存入寄存器eax中(扩展位根据最高位来填充)
  • movzbl %dh, %eax 表示将%dh进行零扩展之后存入寄存器eax中(扩展位由零来填充)

与查看数据相关的指令

--print &value,查看value变量在内存中的地址
--x/4bt 查看内存内容(b表示单字节,h表示双字节,w表示四字 节,g表示八字节)
x 按十六进制格式显示变量,a 按十六进制格式显示变量。
u 按十六进制格式显示无符号整型;o 按八进制格式显示变量。
t 按二进制格式显示变量;d 按十进制格式显示变量
c 按字符格式显示变量;f 按浮点数格式显示变量
s 按照字符串格式显示变量

汇编代码的格式: “ 指令 源操作数 ,目的操作数 ”
示例:movl $8 , %eax
操作数:立即数(immediate)、寄存器(register)、存储器(memory)
注意:CPU计算总是仅从寄存器直接存/取数据

三、lea指令

lea 指令是mov 指令的变形
lea 指令形式是从存储器读数据到寄存器,但实际并没有引用存储器,而是将有效地址写入目的操作数(必须是寄存器)
leal S,D 表示D <---&S,将S的地址给D
 

据说,Intel对于设计出LEA指令颇为得意,LEA指令可以在一个时钟周期内完成,执行效率高;

lea不在ALU里执行,而是在AGU(address generation unit)里执行,可提高并行效率;

    如:加法需要1~3个时钟周期,乘法一般需要>10个时间周,除法需要几十甚至上百个时间周期

可以模拟一些三元运算

    例如:%ebx =% eax +% edx,不使用lea需要多条指令,而使用lea: lea (%eax,%edx,1), %ebx

lea指令和mov指令的辨析

  • leaq 8(%edi), %eax==> R[%eax] = 8 + R[%edi]
  • movq 8(%edi), %eax==> R[%eax] = M[8 + R[%edi]]

movl $立即数a,size(%register)是指将立即数a存放到在内存中最终地址为寄存器%register中的值 + size中的单元去

注:括号内的是寄存器,括号外size是偏移值,可为负数。

四、跳转指令

  • jmp L:无条件跳转指令,跳转至L
  • jge L:使用cmpl R1,R2作为判断(符号数减法,R2-R1),大于等于则跳转至L
  • jae L:使用cmpl R1,R2作为判断(符号数减法,R2-R1),大于等于则跳转至L

五、压栈/弹栈指令

  • push S:压栈指令。对于pushl S,表示R[%esp] <-- R[%esp] – 4;M[R[%esp]] <-- S,其中,4为l的字节数,且假设栈往低地址扩展。

注意:push $value表示将value的首地址压入栈中

  • pop D:出栈指令。对于popl D,表示D <-- M[R[%esp]];R[%esp] <-- R[%esp] + 4,同理

push与pop也可以自动根据操作数的长度来分配入栈/出栈时栈顶指针需要减小/增大的地址长度

六、sub/add指令

  • subl %eax,%edx   表示将%edx-%eax的结果存放进寄存器edx中
  • addl %eax,%edx   表示将%edx+%eax的结果存放进寄存器edx中

1008.s

汇编指令初步(AT&T格式)_第2张图片

 在调试过程中输入“p value1”即可查看value1的值,输入“p &value1”即可查看地址(p是print的缩写)

汇编指令初步(AT&T格式)_第3张图片

此时用p来查看value2的值默认的是打印四个字节(即会将后两个字节中的数据打印出来),所以value2会是0x??030002(根据value2的值可以算得为0x00030002)

汇编指令初步(AT&T格式)_第4张图片(上机验证正确) 

分析“movl %ecx, value2”这条指令,此时value2代表的是value2所处单元的首地址,该条指令代表的就是从寄存器ecx中取出的四个字节的数据复制到以value2所处单元的首地址为首的四个内存单元

输入“p $ eax”可以查看寄存器eax中的值


1009.s

汇编指令初步(AT&T格式)_第5张图片

  1. ".section .data"这一段表示申明变量,value1为一个值为400的整型(int占用四个字节),values为一个存储了400,15,20,25,30,35,40,45,50,55,60的整型数组(每个整型数值占四个字节)
  2. ".section .text" ".global _start" "_start:"相当于固定格式(类似于C++中的头文件,命名空间等)
  3. 10-12行格式一样,以第十行为例,该指令将立即数1送入寄存器edi中
  4. 第13行,这个时候value1可以看做它所处内存单元的首地址,将从value1首地址开始的四个字节的值送入寄存器ecx中
  5. 14-16行同上
  6. 以第18行为例,该行是将以为values+%edi+%ebx*1为首地址之后的四个字节中的数据送入寄存器eax中

先根据“p &values”得到values的首地址,再输入“x /44bx values首地址”查看以values为首地址共11*4个字节的单元的数据,

汇编指令初步(AT&T格式)_第6张图片

执行第十四行(按照十六进制显示eax中的数据)得到

执行第十五行,得到

执行第十六行,得到


 

 

你可能感兴趣的:(计算机操作系统课程笔记)