1.如何由机器代码生成汇编代码?

objdump -d再加上文件名即可直接在终端看到由反汇编器恢复的汇编代码。注意,文件名并不一定得是.o文件,任何可执行文件都可以。

结果如下:

仅列举了反汇编test.o的结果,其它的也测试过,不放图了。

2. 32位和64位的基本数据类型大小对比:

32位:

char:1字节,char*:4字节,short int:2字节,int:4字节,unsigned int:4字节,float:4字节,double:8字节,long:4字节,long long:8字节,unsigned long:4字节

64位:

char:1字节,char*:8字节,short int:2字节,int:4字节,unsigned int:4字节,float:4字节,double:8字节,long:8字节,long long:8字节,unsigned long:8字节

红字标识的是有变化的数据类型。

3.几个术语:

字节:8位,后缀:b

字:16位,后缀:w

双字:32位,后缀:l

四字:64位,后缀:q

MOV类指令也有movb,movw,movl,movq,分别对应这几种大小的操作数。

4.x86-64的寄存器:

看下面这张图:

x86-64有16个64位通用寄存器,如最左侧所示,可以对每个寄存器的低字节操作,比如要访问%rax的低8位,则可以访问%al。

同理,也有%ax对应16位,%eax对应32位,%rax对应64位。

有一条特殊规则:当对某个寄存器的低4字节操作时,如%eax,会自动把高4个字节全置为0。

5.寻址方式:

  1: $+立即数,则取得的操作数就是立即数

  2:立即数,则取得的操作数就是以立即数为地址,对应取出的操作数

  3:寄存器,则取得的操作数就是以寄存器的值

  4:(寄存器),则取得的操作数就是以寄存器的值为地址,对应取出的操作数

  5:立即数1(寄存器1,寄存器2,立即数2),则取得的操作数就是以立即数1的值+寄存器1的值+寄存器2的值*立即数2为地址,对应取出的操作数

  6.有了最通用的第5条,其他变种都能写出,比如(,寄存器2,立即数2),则取得的操作数就是以寄存器2的值*立即数2为地址,对应取出的操作数

习题练一下:

  

答案:

%rax对应0x100,  0x104对应0xAB,  $0x108对应0x108,  (%rax)对应0xFF,  4(%rax)对应0xAB,  9(%rax,%rdx)对应0x11

260(%rcx,%rdx)对应0x13,  0xFC(,%rcx,4)对应0xFF,  (%rax,%rdx,4)对应0x11

讲解一下260(%rcx,%rdx),因为260=0x104,所以操作数是0x104+0x1+0x3=0x108地址对应的值,是0x13

6.mov指令

  1.mov指令的顺序是从左到右,如mov a,b,则把a的值复制给b

  2.除了之前提到的movb,movw,movl,movq,还有movabsq,代表传送绝对的四字,movq虽可传四字,但一旦要传立即数,则只能传32位补码表示的立即数,随后把它符号拓展到64位。而movabsq可以直接传64位的立即数,但是它只能以寄存器作为目的地。

  3.所有mov指令都不支持从一个内存地址直接传到另一个内存地址,如movw (%rax),4(%rsp)是不行的。

  4.决定mov使用哪个后缀的是寄存器的大小,当两边操作的都是寄存器时,若大小不同,必须用第5条中的小数据复制到大目的地的类型的mov指令,当两边操作的是立即数和内存时,可以以立即数大小为准,

  例子:movl $0x4050,%eax  0x4050虽然是2字节,但%eax是4字节,所以movl

     movw %bp,%sp

     movb (%rdi,%rcx),%al

     movb $17,(%rsp)  立即数->内存

     movq %rax,-12(%rbp)

  5.当想将小的数据复制到大的目的地时,可以用movz或movs,前者代表用0填充高字节,后者代表用符号填充高字节,后面还要加上两种转换数据的大小,

  比如movzbw(字节->字,0填充),movswq(字->四字,符号填充),还有一种cltq指令,特指%eax->%rax的符号拓展转换,等价于movslq %eax,%rax

  注意movs和movz都是以寄存器为目的地的。

  根据以上信息,可以知道,之前的第4点中的特殊规则其实相当于是说movl可以实现movzlq的功能

  

  6.当作强制类型转换时,若既涉及大小的变化又涉及符号变化,则操作时应先改变大小。

  例子:有两个指针,sp和dp,分别保存在%rdi和%rsi中,指向的数据类型分别是src_t和dest_t,中间寄存器为%rax,可用其任意子部分

  当src_t为long,dest_t为long时,写出转换的指令:

    movq (%rdi),%rax

    movq %rax,(%rsi)

  当src_t为char,dest_t为int时,写出转换的指令:

    movsbl (%rdi),%eax           //因为char是有符号的,先用movsbl转成4字节

    movl %eax,(%rsi)     //以寄存器大小决定后缀用l

  当src_t为char,dest_t为unsigned时,写出转换的指令:

    movsbl (%rdi),%eax

    movl %eax,(%rsi)     //转换后两者大小相等,无需作零拓展

  当src_t为unsigned char,dest_t为long时,写出转换的指令:

    movzbq (%rdi),%rax          //答案是movzbl (%rdi),%eax,答案疑似错了

    movq %rax,(%rsi)    

  当src_t为int,dest_t为char时,写出转换的指令:

    movl (%rdi),%eax           //先改变大小指的是源比目的小时先改变大小

    movb %al,(%rsi)

  当src_t为unsigned,dest_t为unsigned char时,写出转换的指令:

    movl (%rdi),%ax

    movb %al,(%rsi) 

  当src_t为char,dest_t为short时,写出转换的指令:

    movsbw (%rdi),%ax

    movw %ax,(%rsi) 

7.push与pop指令

  1.栈是向下增长的,因此栈顶元素的地址是所有栈中元素地址中最低的。

  2.%rsp保存着栈顶元素的地址。

  3.push和pop同样有pushq,pushl,pushw,pushb等操作,以下都以pushq为例来讨论。

  4.pushq时,先将栈顶指针减8,再将值写到新栈顶地址,如:

   pushq %rbp

   等价于:

   subq $8,%rsp (下一章讲述这个指令)

   movq %rbp,(%rsp)

   这两种操作的区别是机器代码中pushq指令编码占1字节,而上面两条指令加起来需要8字节。

   验证:随便找个.c文件,先生成.s汇编代码,然后在.s里面改成需要的汇编指令,生成.o文件,再用objdump -d反汇编查看,结果如下:

   

   

   

   

    

    

    

    

    此时可以看到pushq占1个字节,再改成等价的指令来看下:

       

     

    可以看到,变成了8个字节,验证完毕。

    对了,有个小知识点,如果汇编语言中想注释怎么办?

    答案是和c,c++等一样,//和#都可以实现,可以加上注释再反汇编一下看有没有反汇编到注释的句子来验证,具体就不演示了。

   5.类似地,popq会把栈顶的值读出数据,然后再将栈指针+8,注意此时原先栈顶的内容是不变的(虽然栈顶指针已经不指向它了)。

  结束!

(有疑惑的,请看博客的“写在前面”一章) 

CSAPP阅读笔记-汇编语言初探(数据传送类指令)-来自第三章3.2-3.3的笔记-P115-P128的更多相关文章

  1. CSAPP阅读笔记-汇编语言初探(算术和逻辑操作类指令)-来自第三章3.5的笔记-P128-P135

    1.算术和逻辑操作类指令分四类:加载有效地址,一元操作,二元操作和移位,如下: 2. leaq指令,类似mov指令,它左侧的数看似是给出一个地址,在内存中从给定的地址取操作数,传给右边的目的地.但其实 ...

  2. CSAPP阅读笔记-汇编语言初探(控制类指令)-来自第三章3.6的笔记-P135-P163

    1.正溢出与负溢出: 首先,一个正数与一个负数相加,不可能溢出,因为结果的绝对值一定小于两个加数的绝对值,既然两个加数能合理表示出来,结果一定也能合理表示出来. 其次,正溢出是由于两个很大的正数相加, ...

  3. CSAPP阅读笔记-32位64位的区别--来自第三章引言的笔记--P110

    仅从寻址上看,32位和64位机器能寻址的内存空间大小不同. 需要知道的是,计算机系统对存储器作了抽象,程序“认为”内存是一个很大的字节数组,然而实际上它是由多个硬件存储器和操作系统组合起来实现的. 程 ...

  4. CSAPP阅读笔记-struct, union, 数据对齐-来自第三章3.9的笔记-P183-P191

    1.数据对齐 为什么要对齐:通俗点解释就是CPU对数据访问时,每次都是取固定数量的字节数,假如一次取4个字节,若有个int存在0x01-0x04,则一次就能取出,若存在0x03-0x06,则需要分两次 ...

  5. CSAPP阅读笔记-gcc常用参数初探-来自第三章3.2的笔记-P113

    gcc是一种C编译器,这次我们根据书上的代码尝试着使用它. 使用之前,先补充前置知识.编译器将源代码转换为可执行代码的流程:首先,预处理器对源代码进行处理,将#define指定的宏进行替换,将#inc ...

  6. CSAPP阅读笔记-栈帧-来自第三章3.7的笔记-P164-P176

    1.基本结构: 如上图所示,是通用的栈帧结构.大致分两块,调用者函数P和被调用者函数Q. 对P来说,要做的工作是把传递参数中多于6个的部分压栈,随后把Q返回时要执行的下一条指令的地址压栈. 对Q来说, ...

  7. CSAPP阅读笔记-变长栈帧,缓冲区溢出攻击-来自第三章3.10的笔记-P192-P204

    一.几个关于指针的小知识点: 1.  malloc是在堆上动态分配内存,返回的是void *,使用时会配合显式/隐式类型转换,用完后需要用free手动释放. alloca是标准库函数,可以在栈上分配任 ...

  8. CSAPP阅读笔记-数组分配与访问-来自第三章3.8的笔记-P176-P183

    这一节比较简单,仅记录几个比较重要的点: 1.C语言允许对指针进行运算,计算出的值会根据该指针引用的数据类型大小进行伸缩. 例子: 其中,xE是数组的起始地址.注意,指针运算时,若最终结果为指针,则指 ...

  9. 读书笔记,《Java 8实战》,第三章,Lambda表达式

    第一节,Lambda管中窥豹    可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式,它没有名称,但它有参数列表.函数主题和返回值.    本节介绍了Lambda表达式的语法,它包括 ...

随机推荐

  1. java Long、Integer 、Double、Boolean类型 不能直接比较

    测试: System.out.println(new Long(1000)==new Long(1000)); System.out.println(new Integer(1000)==new In ...

  2. freePCRF免费版体验

    [摘要]遍寻网络数昼夜,未得开源PCRF,亦未得有参考价值的PCRF相关文档.所幸觅得免费体验版freePCRF软件.可窥见PCRF设计思路.方法:PCC规则定义.管理策略:遂记录安装.体验心得. f ...

  3. HDU2553 N皇后问题——DFS

    N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  4. sersync服务搭建

    前言: 一.为什么要用Rsync+sersync架构? 1.sersync是基于Inotify开发的,类似于Inotify-tools的工具 2.sersync可以记录下被监听目录中发生变化的(包括增 ...

  5. sql查询语句的拼接小技巧(高手勿喷)

    1. 基本的查询语句后面加上 WHERE 1=1,便于增加查询条件. ASkStr := 'select * from Twork where 1=1 '; if length(cxTEworkid. ...

  6. 小程序:如何在wxml页面中调用JavaScript函数

    早上过来遇到一个这样的bug: 在计算百分比的时候没有保留小数点后2位,从而导致一些无法整除的结果显示太长 一开始,我以为这是一个很普通的bug,既然wxml在页面{{}}内支持简单的运算,我想也应该 ...

  7. boost::string 例题1

    如果有一个语法正确的shader源文件,其包括若干关于uniform变量的定义.请写一个程序从某个shader源文件里提取其全部定义的uniform变量.要求记录其名称.数据类型和初始值(如果有定义) ...

  8. 5.iptables--NAT

    开启Linux主机的核心转发功能 echo 1 > /proc/sys/net/ipv4/ip_forward SNAT相关操作 隐藏网内主机的IP地址,也可以共享互联网.如果只是共享IP的话, ...

  9. oracle无监听程序的解决方法(PLSQL)Oracle ORA12514 监听程序当前无法识别连接描述符中请求的服务

    \PLSQL\instantclient_11_2 listener.ora # listener.ora Network Configuration File: E:\software\PLSQL\ ...

  10. Squid代理服务器(二)——配置Squid服务器

    一.传统代理 (一)需求分析 局域网内,客户机访问自家的Web服务器,通过Squid代理服务器访问Web服务器,再由Squid反馈给客户机;在Squid主机上,构建Squid为客户机访问网站提供代理服 ...