C/C++知识点之C指针原理(9)-C内嵌汇编
小标 2019-02-19 来源 : 阅读 1003 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之C指针原理(9)-C内嵌汇编,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之C指针原理(9)-C内嵌汇编,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之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


内存的常用分配方式有:


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

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程