汽车美容大概要学多久:x86汇编与C的关系

来源:百度文库 编辑:偶看新闻 时间:2024/05/01 02:12:03
一、汇编基础

1 .section .data

2 .section .text

3 .globl _start

4 _start:

5   mov1 $1, %eax

  mov $4, %ebx

  int $0x80  

汇编中,以点(.)开头的名称不会被翻译成机器指令,而是给汇编器的一些特殊指令,称为汇编指示(assembler directive)或伪操作(pseudo-operation).

1. .section .data

.section指示把代码划分为若干段(section),程序被操作系统加载执行时,每个段被加载到不同的地址,具有不同的读、写、执行权限.

.data段保存程序的数据,是可读可写的。C程序的全局变量也属于.data段。如果没有定义数据,.data段可为空。

2. .section .text

.text段保存代码,是只读和可执行的,后面那些指令都属于这个.text段。

3 .globl _start

.globl告诉汇编器,_start这个符号要被链接器用到,所以在目标文件的符号表中要特殊标记。_start就像C程序的main一样特殊,是程序的入口地址。每个汇编程序都要提供一个_start符号并用.globl声明。

_start是个符号(symbol).符号在汇编中代表一个地址,在指令中,所有的符号都被替换成它所代表的地址值。

4 _start: 

 _start标号代表程序的入口,所以,下条指令mov1 $1, %eax称为程序中第一条被执行的指令

在汇编中,立即数前面加$,寄存器名前加%,以便跟符号区别开。

 

int指令为软中断指令,可以用这条指令故意产生一个异常。异常处理和中断类似,CPU从用户模式切换到特权模式,然后跳转到内核代码中执行异常处理程序。内核提供了很多系统服务供用户程序使用,这些系统服务不能像库函数那样调用,因为执行用户程序时CPU处于用户模式,不能调用内核函数,所以要通过系统调用切换CPU模式,通过异常处理程序进入内核,而不能由用户程序随心所欲,想调哪个内核函数就调哪个内核函数,这样保证系统服务被安全调用。在调用结束后,CPU再切换到用户模式,继续执行int指令后面的指令,在用户程序看来就跟函数调用和返回一样。eax和ebx寄存器的值是传递给系统调用的两个参数,eax的值是系统调用号,1表示_exit系统调用。ebx值则是个_exit系统调用的参数,即退出状态。

 

Little Endian

   低地址保存整数的低位,这种字节序称为小端(Little Endian)

Big Endian

   低地址保存整数的高位,称为大端(Big Endian)

二、C内联汇编

   C代码中内联汇编需要和C的变量建立关联,需要用到完整的内联汇编格式.

  __asm__(assembler template                       ---汇编指令部分

          : output operands            ---约束条件,指示汇编指令的运算结果输出到

                                                      那些C操作数中,C操作数应该是左值表达式

          : input operands             ---约束条件,指示汇编指令需要从哪些

                                                      C操作数获得输入  

          : list of clobbered register --此部分是在汇编指令中被修改过的寄存器

                                                     列表,指示编译器哪些寄存器的值在执行

                                                     这条__asm__语句时会改变。

         );

 e.g

   #include

   int main()

   {

     int a = 10, b;

     __asm__("movl %1, %%eax\n\t"

             "movl %%eax, %0\n\t"

              :"=r"(b)  

              :"r"(a)   

              :"%eax"   

            );

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

     return 0;

  }

"r"(a)指示编译器分配一个寄存器保存变量a的值,作为汇编指令的输入,也就是指令中的%1(按照约束条件的顺序,b对应%0,a对应1%),至于%1究竟代表哪个寄存器则由编译器自己决定。汇编指令首先把%1所代表的寄存器的值传给eax(为了和%1这种占位符区分,eax前面要求加两个%号),然后把eax的值再传给%0所代表的寄存器。"=r"(b)就表示把%0所代表的寄存器的值输出给变量b。在执行这两条指令的过程中,寄存器eax的值被改变了,所以把"%eax"写在第四部分,告诉编译器在执行这条__asm__语句时eax要被改写,所以在此期间不要用eax保存其它值。