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的十進制為31097printf("%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, @functionmain:pushl %ebpmovl %esp, %ebpandl $-16, %espsubl $32, %esp#分配32字節棧空間,根據變量情況分配movl $.LC0, 24(%esp)#x變量使用指針(4個字節大小),放入棧中,可以看到,變量分配靠近棧空間的尾部movw $31097, 29(%esp)#字符'yy'移到main程序的棧中,直接將y變量的值放入棧中movb $0, 31(%esp)#加上NULL標志,表示字符結束 movl $.LC1, %eaxleal 29(%esp), %edxmovl %edx, 8(%esp)movl 24(%esp), %edxmovl %edx, 4(%esp)movl %eax, (%esp)call printfmovl $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的十進制為31097printf("%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, @functionmyprinf:pushl %ebpmovl %esp, %ebpsubl $40, %espmovl $.LC0, -16(%ebp)movw $31097, -11(%ebp)movb $0, -9(%ebp)movl $.LC1, %eaxleal -11(%ebp), %edxmovl %edx, 8(%esp)movl -16(%ebp), %edxmovl %edx, 4(%esp)movl %eax, (%esp)call printfleaveret.size myprinf, .-myprinf.globl main.type main, @functionmain:pushl %ebpmovl %esp, %ebpandl $-16, %espsubl $32, %espmovl $1, 28(%esp)call myprintmovl $0, (%esp)call exit.size main, .-main.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3".section .note.GNU-stack,"",@progbits內存的常用分配方式有:
第一,靜態分配,所有名字在編譯時綁定某個存儲位置。不能在運行時改變
第二,棧分配,活動時壓入系統棧。
第三,堆分配,以任意次序分配
總結
以上是生活随笔為你收集整理的C指针原理(9)-C内嵌汇编的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Showdoc使用——接口文档
- 下一篇: 固定布局(fixed layout)、流