汇编指令

程序的机器级表示

有些话、适合烂在心里 提交于 2019-12-01 07:28:24
机器级代码 在计算机中最终执行的都是机器代码,汇编代码、C 语言代码和高级语言的代码都需要转换成机器代码来执行。文章涉及的机器语言主要指 Intel IA32。 如下一段 C 语言代码: 1 int accum = 0; 2 3 int sum(int x, int y) 4 { 5 int t = x +y; 6 accum += t; 7 return ; 8 } 通过 gcc -m32 -O1 -o code.o -c code.c 生成二进制格式的目标代码文件 code.o,通过 hexdump 查看文件内容,在计算机中最终执行的字节指令是: 通过 objdump -d code.o 反汇编查看这段二进制对应的汇编内容: 这里的指令 55 对应了汇编代码 push %ebp,汇编代码非常接近于机器代码,它用可读性更好的文本表示处理器执行的指令。 除了像上面那样通过反汇编目标文件查看对应的汇编代码,还可以通过 gcc 查看 C 编译器产生的汇编代码,如下命令会产生一个汇编文件 code.s 。 # -m32 表示用 32 位模式编译 gcc -O1 -m32 -S code.c 数据格式 虽然 C 语言可以在存储器中声明和分配各种数据类型的对象,但是机器代码只是简单地将存储器看成是一个很大的、按字节寻址的数组。C 语言中的聚合数据类型,例如数组和结构

2019-2020-1 20175320 《信息安全系统设计基础》第五周学习总结

倾然丶 夕夏残阳落幕 提交于 2019-12-01 07:23:15
2019-2020-1 20175320 《信息安全系统设计基础》第五周学习总结 一、教材学习内容总结 本周我们了解了在计算机系统中程序的机器级表示。通过反汇编器可以将机器码转化为类似汇编代码的格式,而该章节内容的主要介绍了在x86-64中的汇编指令以及汇编指令与c代码之间的转化。虽然同样是汇编,但与我们上学期学习的8086中的汇编语句有着一定的区别,以下是本章节需要注意的内容: objdump命令:通过 objdump -d 文件名+后缀 可以将机器码转化为汇编代码,这是进行分析的重要前提条件。 寄存器的前缀不同,对应的存储长度不同。%r是64位、%e是32位、%是16位及以下的寄存器,在进行算术和逻辑操作时,必须通过前缀选择正确长度的寄存器。 操作数有多种寻址方式,我们需要熟悉各种虚拟地址的寻址方式。 x86-64中的数据传送指令以及各种算术和逻辑操作指令的两个操作数的关系相较于8086是相反的,这是与8086最大的区别。 各种操作指令可以通过后缀来指定数据的位数,或者进行数据长度之间的转换,但操作指令规定的长度一定要与寄存器长度相匹配,比如movq、movabsq、movswl等指令。 在使用mov指令时,不可以两个操作数同为存储器,且立即数不能作为目的地址。 在x86-64中,栈操作指令总是以四字作为出以及入栈的单位。 在移位操作中,左移与右移的效果有所区别

arm汇编—ldr加载指令,ldr伪指令

时光总嘲笑我的痴心妄想 提交于 2019-12-01 05:06:41
分类: 嵌入式 2014-01-17 17:15:20 操作系统:ubuntu10.04 汇编语言:arm 1, ldr加载指令 LDR指令的格式为: LDR{条件} 目的寄存器,<存储器地址> LDR指令用亍从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用亍从存储器 中读取32位的字数据到通用寄存器,然后对数据迕行处理。当程序计数器PC作为目的寄存器时, 指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设 计中比较常用,丏寻址方式灵活多样,请读者认真掌握。 指令示例: LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。 LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。 LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。 LDR R0,[R1,R2]!;将存储器地址为R1+R2的字数据读入寄存器R0,幵将新地址R1+R2写入R1。 LDR R0,[R1,#8]! ;将存储器地址为R1+8的字数据读入寄存器R0,幵将新地址R1+8写入R1。 LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,幵将新地址R1+R2写入R1。 LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1

x64指令格式

人走茶凉 提交于 2019-12-01 00:28:09
引言 看了两天的x86指令集,终于基本搞懂了x64的指令格式(只是x64哦,没有特别关注16位和32位时的格式),和RISC相比实在是太复杂了,难怪x86的功耗将不下来,光是译码器就不知道得做的多么复杂。 x64指令格式 x64指令共包括七个部分,即: legacy prefix(一个字节) REX prefix(一个字节) opcode(一到三个字节) ModRM(一个字节) SIB(一个字节) disp(最多可以8个字节) imm(最多可以8个字节) legacy prefix legacy prefix在x64下应该不常用。一种情况是需要使用16位的operand时(例如 mov ax 0x1234 ),需加前缀0x66以改变 default operand size (x64下该值是32)。还有就是需要lock的情况。还有其他情况就没有细看了。 REX REX前缀非常重要,正是这个前缀将x86带入了64位模式。它的高四位一定是0x4,低四位分别代表W、R、X、B。 W:x64模式下大部分指令的 default operand size 是32位的,对这类指令,如果需要64位的操作数,将需要将W置位,例如 mov rax rbx 。 R:将 ModRM.reg 从8个扩展到16个。 X:将 SIB.index 寄存器从8个扩展到16个 B:将 SIB.base 或者

C语言编译全过程

為{幸葍}努か 提交于 2019-11-30 19:33:32
C语言编译全过程 编译的概念:编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。 编译的完整过程:C源程序-- > 预编译处理 ( . c ) -- > 编译、优化程序( . s、 . asm)-- > 汇编程序 ( . obj、 . o、 . a、 . ko ) -- > 链接程序( . exe、 . elf、 . axf等) 1 . 编译预处理 读取c源程序,对其中的伪指令(以 # 开头的指令)和特殊符号进行处理 伪指令主要包括以下四个方面: (1)宏定义指令,如 # define Name TokenString, # undef等。 对于前一个伪指令,预编译所要做的是将程序中的所有Name用TokenString替换,但作为字符串常量的 Name则不被替换。对于后者,则将取消对某个宏的定义,使以后该串的出现不再被替换。 (2)条件编译指令,如 # ifdef, # ifndef, # else, # elif, # endif等。 这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉 (3) 头文件包含指令,如 # include "FileName" 或者 #

编程语言分类

╄→гoц情女王★ 提交于 2019-11-30 19:16:45
编程语言分类 一、机器语言 只要是谈到计算机基础,有一个东西是我们无法避免的,那就是编程到底是什么?我只放图,其他的你们自己YY。 [ 现在来想象这样一个场景,如果奴隶来自不同的国家,作为尊贵而又穷逼买不起管家的奴隶主的我们,如果需要控制奴隶,则需要和奴隶有一定的沟通才能控制努力。 如果把奴隶换成计算机,由于计算机以二进制的形式存储数据,如果我们要奴役计算机,则需要使用二进制编写程序。也就是说,如果我们需要和计算机沟通,那我们必须得会二进制代码编程。而这个二进制代码编程则是使用机器语言编程,直接操作硬件。它的优缺点如下: 优点:执行效率高(还能在快吗?有的话,马都累死了…) 缺点:开发的效率低(有本事你把下图的代码翻译翻译) [ 1.1机器语言编程 由于计算机内部只能接受二进制代码,因此,用二进制代码0和1描述的指令称为机器指令,全部机器指令的集合构成计算机的机器语言,用机器语言编程的程序称为目标程序。只有目标程序才能被计算机直接识别和执行。但是机器语言编写的程序无明显特征,难以记忆,不便阅读和书写,且依赖于具体机种,局限性很大,机器语言属于低级语言。 用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。手编程序时,程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。这是一件十分繁琐的工作

使用gdb调试c++程序

守給你的承諾、 提交于 2019-11-30 12:48:02
上篇( 使用c++开发跨平台程序 )说到 , 我不怕造东西 , 我怕的是造出来的东西 , 如果出了问题 , 我却不知道原因 . 所以调试分析是一个重要的手段 . C++ 调试是一个复杂的活 . 虽然大部分调试可以通过 IDE 在开发期间就解决了 . 但是必然的 , 还有很多东西需要在生产环境中还原它 . 分析它 , 然后解决它 .gdb 是一个成熟的工具 . 围绕着它有很多的工具可以选择 . 不过这么多工具的根本还是命令行模式下的 gdb. 废话不多说 , 现在我就用 gdb 来分析调试一下吧 . 生成 dump 文件 : 在 shell 中输入命令 : ulimit -c unlimited; 然后运行自己的程序 , 如果程序此时崩溃 , 就会在目录生成一个名为 core 的文件 .( 这个也看系统配置 .) 使用命令 gdb Test1 core 加载文件 . 或者它的详细命令 gdb -c core -e Test1 --symbols Test1 --readnow 下面是一个命令行输出的截图 : 上图中可以解释的不多 . 因为我们现在刚要入门 . 所以只能注意上图中的三个红框 . 红框 1: 命令行其中 app7 是可执行文件 , 而 core 是 dump 文件 . 红框 2: 标明 gdb 在 app7 中找到了它对应的 symbol. 红框 3: 标明 core

2019-05-16-日常零碎知识点

喜夏-厌秋 提交于 2019-11-30 12:19:57
版权声明:本文为 Jiawei Xu 于2019年5月16日所写,未经允许不得转载。 Linux网络编程 socketaddr socktaddr_in socketaddr_un UNIX Domain Socket,虽然网络socket也可以用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。Unix Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。 使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。 UNIX Domain

JVM性能优化, Part 2 ―― 编译器

巧了我就是萌 提交于 2019-11-30 07:05:15
ImportNew注:本文是JVM性能优化 – 第2篇 《JVM性能优化, Part 2 ―― 编译器》第一篇 《JVM性能优化, Part 1 ―― JVM简介 》 作为JVM性能优化系列文章的第2篇,本文将着重介绍Java编译器,此外还将对JIT编译器常用的一些优化措施进行讨论(参见“JVM性能优化,Part 1″中对JVM的介绍)。Eva Andreasson将对不同种类的编译器做介绍,并比较客户端、服务器端和层次编译产生的编译结果在性能上的区别,此外将对通用的JVM优化做介绍,包括死代码剔除、内联以及循环优化。 Java编译器存在是Java编程语言能独立于平台的根本原因。软件开发者可以尽全力编写程序,然后由Java编译器将源代码编译为针对于特定平台的高效、可运行的代码。不同类型的编译器适合于不同应用程序的需求,使编译结果可以满足期望的性能要求。对编译器基本原理了解得越多,在优化Java应用程序性能时就越能得心应手。 什么是编译器 简单来说,编译器就是将一种编程语言作为输入,输出另一种可执行语言的工具。大家都熟悉的javac就是一个编译器,所有标准版的JDK中都带有这个工具。javac以Java源代码作为输入,将其翻译为可由JVM执行的字节码。翻译后的字节码存储在.class文件中,在启动Java进程的时候,被载入到Java运行时中。 标准CPU并不能识别字节码

编程语言分类

a 夏天 提交于 2019-11-30 06:26:08
编程语言分类 一、机器语言 只要是谈到计算机基础,有一个东西是我们无法避免的,那就是编程到底是什么?我只放图,其他的你们自己YY。 现在来想象这样一个场景,如果奴隶来自不同的国家,作为尊贵而又穷逼买不起管家的奴隶主的我们,如果需要控制奴隶,则需要和奴隶有一定的沟通才能控制努力。 如果把奴隶换成计算机,由于计算机以二进制的形式存储数据,如果我们要奴役计算机,则需要使用二进制编写程序。也就是说,如果我们需要和计算机沟通,那我们必须得会二进制代码编程。而这个二进制代码编程则是使用机器语言编程,直接操作硬件。它的优缺点如下: 优点:执行效率高(还能在快吗?有的话,马都累死了…) 缺点:开发的效率低(有本事你把下图的代码翻译翻译) 1.1 机器语言编程 由于计算机内部只能接受二进制代码,因此,用二进制代码0和1描述的指令称为机器指令,全部机器指令的集合构成计算机的机器语言,用机器语言编程的程序称为目标程序。只有目标程序才能被计算机直接识别和执行。但是机器语言编写的程序无明显特征,难以记忆,不便阅读和书写,且依赖于具体机种,局限性很大,机器语言属于低级语言。 用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。手编程序时,程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。这是一件十分繁琐的工作