C与汇编语言

目录一、汇编指令二、汇编器和链接器三、 汇编语法四、C中嵌入汇编代码五、GDB反汇编1、x86_64通用寄存器2、 调用栈3、导出汇编代码4、反汇编调试详解5、结构体反汇编一、汇编指令 汇编指令是指特定CPU架构的指令码的助记符,比如Intel x86 32位下ADD指令对应的16进制机器码有04/05/80/81等,被操作对象不同同一个...
摘要由CSDN通过智能技术生成

目录

一、汇编指令

二、汇编器和链接器

三、 汇编语法

四、C中嵌入汇编代码

五、GDB反汇编

1、x86_64通用寄存器

2、 调用栈

3、导出汇编代码

4、反汇编调试详解

5、结构体反汇编


一、汇编指令

       汇编指令是指特定CPU架构的指令码的助记符,比如Intel x86 32位下ADD指令对应的16进制机器码有04/05/80/81等,被操作对象不同同一个指令对应的指令码不同,操作对象通常是寄存器,内存地址,I/O端口等,具体操作对象通过指令码后面的一个或者多个的1字节辅助操作码指定,通过objdump命令将生成的可执行程序进行了反汇编可查看汇编指令对应的指令码。

       参考:简单学习看机器码的方法

                 Intel汇编指令格式解析

                 x86指令格式

二、汇编器和链接器

       汇编器(assembler)的作用是将用汇编语言编写的源程序转换成二进制形式的目标代码。Linux 平台的标准汇编器是 GAS, 使用标准的 AT&T 汇编语法它是 GCC 所依赖的后台汇编工具,通常包含在 binutils 软件包中,对应的命令是as。Linux 平台上另一个经常用到的汇编器是 NASM,与GAS最大的不同是,NASM使用Intel 汇编语法,除此之外NASM和GAS都有自己特定的汇编器指令和宏结构。MSAM是Intel平台上所有汇编器的鼻祖,微软的VS中自带该汇编器,同样使用Intel汇编语法。

      汇编器生成的目标代码只局限于单个源代码文件,对源代码中依赖的来自其他源代码文件中的全局变量或者函数未做解析,这时需要链接器,将这些未解析的符号翻译成实际的内存地址,最终将存在依赖关系的多个目标代码文件合并成一个可执行文件,GCC使用的链接器是ld。

       参考:Java程序员自我修养——编译过程和ELF文件

                 Linux 汇编器:对比 GAS 和 NASM

三、 汇编语法

      汇编语法与汇编器的关系,类似于C/C++标准与C/C++编译器的关系,主要有两种语法,Intel 和AT&T 汇编语法,最大的区别是后者是与平台无关的,前者只局限于Inter平台。特定CPU架构下汇编指令集和寄存器名称相当于汇编语法中的关键字,支持多平台的GAS汇编器会根据当前系统的CPU架构自动识别并转换成对应平台下的机器码。

     参考:Linux 汇编语言开发指南

四、C中嵌入汇编代码

     C标准中并未规定如何嵌入汇编代码,所以嵌入汇编代码的语法只适用于特定的编译器,下面主要介绍GCC中的内联汇编,其格式为:__asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modify)。

1、__asm__和__volatile__宏

    __asm__可简写为asm,用于标识一段汇编指令,__volatile__可简写为volatile,用于告诉编译器不需要对asm中的汇编指令做优化,原封不动的保留即可。

2、Instruction List

   Instruction List是指汇编指令列表,可以为空,多条指令时,通常一条指令一行,以分号";"或者换行符"\n"表示结束,并用双引号包住,注意指令中使用寄存器时前面必须加两个%。

3、Output

  Output指定汇编语句的输出,即将寄存器中的值存入到哪个变量中,如"=a"(a),表示将a对应寄存器的值赋值给变量a,a是寄存器eax/ax /al的简写,编译器根据汇编指令自动推测是eax还是ax。

4、Input

  Input指定汇编语句的执行参数,可以是一个常量,也可以是一个复杂的表达式,执行参数可以通过占位符或者寄存器的方式传入,占位符按照Input/Output表达式出现的顺序从0开始编号,最多十个表达式,编号最大9。

5、操作数约束

  Output表达式"=a"(a) 中a就是操作数约束中的寄存器约束,其他约束如下,其中I O表示Input和Output适用:

  • r I,O 表示使用一个通用寄存器,由GCC在%eax/%ax/%al, %ebx/%bx/%bl, %ecx/%cx/%cl, %edx/%dx/%dl中选取一个GCC认为合适的。 
  • q I,O 表示使用一个通用寄存器,和r的意义相同。 
  • a I,O 表示使用%eax / %ax / %al 
  • b I,O 表示使用%ebx / %bx / %bl 
  • c I,O 表示使用%ecx / %cx / %cl 
  • d I,O 表示使用%edx / %dx / %dl 
  • D I,O 表示使用%edi / %di 
  • S I,O 表示使用%esi / %si 
  • f I,O 表示使用浮点寄存器 
  • t I,O 表示使用第一个浮点寄存器 
  • u I,O 表示使用第二个浮点寄存器
  • m I,O 表示使用系统所支持的任何一种内存方式,不需要借助寄存器
  • i I 表示输入表达式是一个立即数(整数),不需要借助任何寄存器 
  • F I 表示输入表达式是一个立即数(浮点数),不需要借助任何寄存器
  • g I,O 表示可以使用通用寄存器,内存,立即数等任何一种处理方式。

 测试用例:

#include <stdio.h>

int main()
{
    int result = 0;
    int input = 1;

    int a = 1;
    int b = 2;

    asm volatile (
        "movl %1, %0\n"
        : "=r"(result)
        : "r"(input)
        );

    printf("result = %d\n", result);
    printf("input = %d\n", input);

    asm volatile (
        "movl %%eax, %%ecx;"
        "movl %%ebx, %%eax\n"
        "movl %%ecx, %%ebx;"
        : "=a"(a), "=b"(b)
        : "a"(4), "b"(5)
        );

    printf("a = %d\n", a);
    printf("b = %d\n", b);

    return 0;
}

   参考:__asm__ volatile 之 C语言嵌入式汇编

             《汇编语言程序设计》

五、GDB反汇编

    可通过 gcc -S test.c -o test.s 或者objdump -S test.o > test.s查看生成的汇编代码,但是同源代码

  • 10
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值