C指针原理(9)-C内嵌汇编

我们使用m标记可以直接在内存中对数进行操作,前面的例子对变量进行操作时都需要将变量值存储在要修改的寄存器中,然后将它写回内存位置中.

#include <stdio.h>
int main(void){
    int xa=2;
    int xb=6;
     asm volatile(
    "subl %1,%0\n\t"
     :"=r"(xb):"m"(xa),"0"(xb));
    printf("%d\n",xb);
    return 0;
}

我们直接从xa的内存地址中将xa取出,而不需要再将xa先存储在一个寄存器。

首先,我们看一下AT&T汇编各段的意义

?

?

节 含义
.text 已编译程序的机器代码
.rodata 只读数据,如pintf和switch语句中的字符串和常量值
.data 已初始化的全局变量
.bss 未初始化的全局变量
.symtab 符号表,存放在程序中被定义和引用的函数和全局变量的信息
.rel.text 当链接器吧这个目标文件和其他文件结合时,.text节中的信息需修改
.rel.data 被模块定义和引用的任何全局变量的信息
.debug 一个调试符号表。
.line 原始C程序的行号和.text节中机器指令之间的映射
.strtab 一个字符串表,其内容包含.systab和.debug节中的符号表
?

上面列表也许比较抽象,我们从一个C程序生成的中间汇编代码分析:

#include <stdio.h>

void main(){

   char *x="xxxx";

   char y[]="yy";//y的16进制ASCII码是97,9797的十进制为31097

   printf("%s-----%s",x,y);

   exit(0);

}

?我们使用gcc -S testcr.c,查看编译生成的汇编代码(为便于理解,将生成的汇编代码进行了注释)

.file   "testcr.c"

    .section    .rodata

.LC0:

    .string "xxxx"#使用char *分配

.LC1:

    .string "%s-----%s"

    .text

.globl main

    .type   main, @function

main:

    pushl   %ebp

    movl    %esp, %ebp

    andl    $-16, %esp

    subl    $32, %esp#分配32字节栈空间,根据变量情况分配

    movl    $.LC0, 24(%esp)#x变量使用指针(4个字节大小),放入栈中,可以看到,变量分配靠近栈空间的尾部

    movw    $31097, 29(%esp)#字符‘yy‘移到main程序的栈中,直接将y变量的值放入栈中

    movb    $0, 31(%esp)#加上NULL标志,表示字符结束 

    movl    $.LC1, %eax

    leal    29(%esp), %edx

    movl    %edx, 8(%esp)

    movl    24(%esp), %edx

    movl    %edx, 4(%esp)

    movl    %eax, (%esp)

    call    printf

    movl    $0, (%esp)

    call    exit

    .size   main, .-main

    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"

    .section    .note.GNU-stack,"",@progbits

在MAIN函数中char *分配在只读数据段中,实际使用时,只在程序栈中分配一个指针的空间。char[] 在程序栈中分配空间,然后直接使用movl、movw之类的汇编直接把值放入栈中空间。那么在其它函数中声明的呢,可以从以下程序中看出,仍然如此。

#include <stdio.h>

void myprinf(){

   char *x="xxxx";

   char y[]="yy";//y的16进制ASCII码是97,9797的十进制为31097

   printf("%s-----%s",x,y);

}

void main(){

   int num=1;

   myprint();

   exit(0);

}

生成的中间汇编代码为:

.file "testcr.c"


    .section    .rodata

.LC0:

    .string "xxxx"

.LC1:

    .string "%s-----%s"

    .text

.globl myprinf

    .type   myprinf, @function

myprinf:

    pushl   %ebp

    movl    %esp, %ebp

    subl    $40, %esp

    movl    $.LC0, -16(%ebp)

    movw    $31097, -11(%ebp)

    movb    $0, -9(%ebp)

    movl    $.LC1, %eax

    leal    -11(%ebp), %edx

    movl    %edx, 8(%esp)

    movl    -16(%ebp), %edx

    movl    %edx, 4(%esp)

    movl    %eax, (%esp)

    call    printf

    leave

    ret

    .size   myprinf, .-myprinf

.globl main

    .type   main, @function

main:

    pushl   %ebp

    movl    %esp, %ebp

    andl    $-16, %esp

    subl    $32, %esp

    movl    $1, 28(%esp)

    call    myprint

    movl    $0, (%esp)

    call    exit

    .size   main, .-main

    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"

    .section    .note.GNU-stack,"",@progbits

内存的常用分配方式有:

第一,静态分配,所有名字在编译时绑定某个存储位置。不能在运行时改变?
第二,栈分配,活动时压入系统栈。?
第三,堆分配,以任意次序分配

原文地址:http://blog.51cto.com/13959448/2324500

时间: 2024-11-02 08:12:56

C指针原理(9)-C内嵌汇编的相关文章

GCC在C语言中内嵌汇编 asm __volatile__ 【转】

转自:http://blog.csdn.net/pbymw8iwm/article/details/8227839 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作. 1.简单的内嵌汇编 例: __asm__ __volatile__("hlt"); "__asm__"表示后面的

内嵌汇编与C/C++实现的冒泡排序,快速排序算法排序500W个数据对比

内嵌汇编是微软为了提高程序的直接操作硬件能力,以及实现大任务程序效率的提高,而嵌入在VC中的,他不依赖于汇编器对内嵌汇编代码进行汇编,这些内嵌汇编代码由C编译器内部实现,可以使程序好像自陷到汇编状态一样.这意味着你如果在C/C++程序中使用了 inline  asm进行 汇编 那么 就注定无法跨平台的,对于没有汇编基础的同学是需要去学习下王爽的8086汇编程序设计.,因为有些时候C++程序员是不得不懂这些东西的 ,否则你永远无法知道编译器为你的函数做了什么,.你还有哪些地方需要优化, 不管处于什

VC内嵌汇编基础知识

http://www.cppblog.com/xingkongyun/archive/2008/12/21/70003.html 为了加速游戏,一提起汇编语言,大家也许会感到很神秘.其实如果你学起来就会发现,它并非想象中那样难.特别是内嵌汇编,由于它和C++紧密结合, 使你不必考虑很多烦琐的细节(例如输入输出函数的写法),学习起来比较容易.使用内嵌汇编,特别是使用MMX指令,可以大大提高各种游戏中常见特效的速 度,对于编出一个漂亮的游戏非常重要.学好汇编语言还有一个特别有趣的用处:可以观察和看懂

汇编语言9内嵌汇编

C语言 内嵌汇编 void main(){ char ps[20] = "aaaaaaaaaa\n"; char *p1 =ps; //用汇编语句改写下面2句代码 ps[3]='b'; printf(ps);} //等价的写法1:void main(){ char ps[20] = "aaaaaaaaaa\n"; char *p1 =ps; HMODULE hmod =GetModuleHandle("msvcr90.DLL"); if (hmo

GCC在C语言中内嵌汇编 asm __volatile__

转自 http://blog.csdn.net/pbymw8iwm/article/details/8227839 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作. 1.简单的内嵌汇编例: __asm__ __volatile__("hlt"); "__asm__"表示后面的代

内嵌汇编

static inline void arch_spin_lock(arch_spinlock_t *lock) {     unsigned long tmp; __asm__ __volatile__( "1: ldrex   %0, [%1]\n"           "   teq %0, #0\n"                         WFE("ne") "   strexeq %0, %2, [%1]\n&quo

arm 内嵌汇编

内嵌汇编代码,每一个input和output operand,由被方括号[]中的符号名,限制字符串,圆括号中的C表达式构成 // example static inline void __down_write(struct rw_semaphore *sem) {     long oldcount; #ifndef    CONFIG_SMP     oldcount = sem->count;     sem->count += RWSEM_ACTIVE_WRITE_BIAS; #else

内存四域,变量声明和定义,寄存器,c内嵌汇编,auto,堆栈,常量,静态变量

 1.内存四大区域 2.在程序中,变量的声明可以有多份,定义只能有一份 3.寄存器在cpu里面,没有地址 4.c语言内嵌汇编语言 5.auto变量 自动分配内存,自动释放内存. 6.栈的大小由编译器决定 修改栈的方式,右击项目à属性à配置属性à链接器à系统à堆栈保留大小 7.卡死cpu,卡死内存的程序 8.在堆上申请空间后赋值后,不可以释放内容.要通过free方法进行释放对空间. 9.常量字符串在代码区.代码区是智能读的. 10.常量本质 10.静态变量,全局变量的差别 A全局变量可以跨文件

Ok6410裸机驱动学习(三)C语言内嵌汇编

1.C语言内嵌汇编使用方法 C内嵌汇编以关键字”_asm_或asm开始,下辖4个部分,各部分之间用“:”分开,第一部分是必须写的,后面3个部分可以省略,但是分号:不能省略 优化后的代码 2.汇编程序框架 .section .data <初始化的数据> .section .bss <未初始化的数据> .section .text .global _start _start: <汇编代码>