linux c语言编程内嵌汇编,gcc编译c语言中内嵌汇编

gcc编译c语言中内嵌汇编

--AT&T and Intel 汇编语法对照

寄存器命名:

AT&T:  %eax

Intel: eax

AT&T 语法源地址在左侧,目的地址在右侧与Intel 方式语法相反

将eax值传入ebx

AT&T:  movl %eax, %ebx

Intel: mov ebx, eax

AT&T 语法在立即数前有前缀$.

AT&T:  movl $0x0h, %eax

Intel: mov eax,0x0h

AT&T 语法在操作符后跟表示操作数类型的后缀b,w,l分别表示字节,字,双字,相当于伪操作符ptr,如果不加的话GAS会guess

AT&T:  movw %ax, %bx

Intel: mov bx, ax

内存寻址方式

AT&T:  immed32(basepointer,indexpointer,indexscale)

Intel: [basepointer + indexpointer*indexscale + immed32]

地址计算公式为:

immed32 + basepointer + indexpointer * indexscale

直接寻址

AT&T:  _a

Intel: [_a]

间接寻址

AT&T:  (%eax)

Intel: [eax]

相对寻址

AT&T: _variable(%eax)

Intel: [eax + _variable]

AT&T:  _array(,%eax,4)

Intel: [eax*4 + array]

C 代码: *(p+1) p定义为char *

AT&T:  1(%eax) where eax has the value of p

Intel: [eax + 1]

结构体数组寻址,结构体长度为8,下标存于eax,结构体内偏移地址存于ebx,_array为结构体数组首地址

AT&T:  _array(%ebx,%eax,8)

Intel: [ebx + eax*8 + _array]

函数内部实现交换

1、输入与输出变量相同

汇编代码部分标准的交换实现,输入部分用0寄存器表示"=r"(a)中所指定的寄存器即输入与输出变量相同

int main()

{                                                                              804842c:      mov    0xfffffff4(%ebp),%ecx

int a = 10, b = 0;                                                    804842f:      mov    0xfffffff0(%ebp),%edx

printf("before swap: a = %2d, b = %2d\n", a , b);   8048432:      mov    %ecx,%ebx

__asm__("nop;                                                      8048434:      mov    %edx,%esi

movl %0, %%eax;                                        8048436:      nop

movl %1, %0;                                              8048437:      mov    %ebx,%eax

movl %%eax, %1;                                        8048439:      mov    %esi,%ebx

nop;"                                                            804843b:      mov    %eax,%esi

:                                                                    804843d:      nop

"=r"(a), "=r"(b)                                             804843e:      mov    %ebx,%edx

:                                                                    8048440:      mov    %esi,%ecx

"0"(a), "1"(b)                                                8048442:      mov    %edx,%eax

:                                                                    8048444:      mov    %eax,0xfffffff4(%ebp)

"%eax"                                                         8048447:      mov    %ecx,%eax

);                                                                   8048449:      mov    %eax,0xfffffff0(%ebp)

printf("after  swap: a = %2d, b = %2d\n", a, b);

return 0;

}

2、输入与输出用不同的寄存器,&表示输入输出需要分配不同的寄存器

int main()

{

int a = 10, b = 0;

printf("before swap: a = %2d, b = %2d\n", a, b);          804842b:      mov    0xfffffff8(%ebp),%edx

__asm__("nop;                                                            804842e:      mov    0xfffffff4(%ebp),%eax

movl %2, %1;                                                     8048431:      nop

movl %3, %0;                                                     8048432:      mov    %edx,%ebx

nop;"                                                                   8048434:      mov    %eax,%ecx

:                                                                           8048436:      nop

"=&r"(a), "=&r"(b)                                              8048437:      mov    %ecx,%eax

:                                                                           8048439:      mov    %ebx,%edx

"r"(a), "r"(b)                                                        804843b:      mov    %eax,%eax

);                                                                         804843d:      mov    %eax,0xfffffff8(%ebp)

printf("after  swap: a = %2d, b = %2d\n", a , b);           8048440:      mov    %edx,%eax

return 0;                                                                       8048442:      mov    %eax,0xfffffff4(%ebp)

}

3、交换函数,需要间接寻址

#include

void swap(int* x, int* y)     08048400 :

{                                                                                          8048400:      push   %ebp

__asm__("nop;                                                             8048401:      mov    %esp,%ebp

movl (%0), %%eax;                                            8048403:      push   %ebx

movl (%1), %%ebx;                                            8048404:      mov    0x8(%ebp),%ecx

movl %%ebx, (%0);                                            8048407:      mov    0xc(%ebp),%edx

movl %%eax, (%1);                                            804840a:      nop

nop;"                                                                   804840b:      mov    (%ecx),%eax

:                                                                           804840d:      mov    (%edx),%ebx

:                                                                           804840f:      mov    %ebx,(%ecx)

"r"(x),"r"(y)                                                          8048411:      mov    %eax,(%edx)

:                                                                           8048413:      nop

"eax", "ebx", "memory"                                        8048414:      mov    (%esp,1),%ebx ;ebx还原

);                                                                         8048417:      leave   ;movl %ebp, %esp; pop ebp

}                                                                                         8048418:      ret

8048419:      lea    0x0(%esi),%esi

int main()

{

int a = 10, b = 0;

printf("before swap: a = %2d, b = %2d\n", a, b);

swap(&a, &b);

printf("after  swap: a = %2d, b = %2d\n", a, b);

return 0;

}

4、从汇编代码中分离函数

1> 获得汇编代码

这里用加法函数,源代码为:

int sum(int a, int b)

{

int c = a + b;

return c;

}

对应的汇编代码为

Disassembly of           section .text:

00000000 :

0:   55                        push   %ebp

1:   89 e5                   mov    %esp,%ebp

3:   83 ec 04              sub    $0x4,%esp

6:   8b 45 0c              mov    0xc(%ebp),%eax

9:   03 45 08              add    0x8(%ebp),%eax

c:   89 45 fc               mov    %eax,0xfffffffc(%ebp)

f:   8b 45 fc                mov    0xfffffffc(%ebp),%eax

12:   89 c0                  mov    %eax,%eax

14:   c9                       leave

15:   c3                       ret

16:   89 f6                   mov    %esi,%esi

2> 编写内嵌汇编语言函数

分析:为函数构建运行时堆栈情况即可使其顺利运行,由于编译器在函数执行开始和结束时会增加

routine begin:

push %ebp; mov %esp, %ebp

routine end:

leave; ret

将上面的0, 1, 14, 15去掉,返回参数放在eax中将输出部分设置为"=a"(r) 用eax寄存器 r 为需要的return type

步骤:

i   定义return_type r 变量

ii  去掉push %ebp; mov %esp, %ebp;   leave; ret

iii 输出部分为:"=a"(r):

$ vi sumassemble.c

int sum(int a, int b)

{

int r;

__asm__("sub $0x4, %%esp;

movl 0xc(%%ebp), %%eax;

addl 0x8(%%ebp), %%eax;

movl %%eax, 0xfffffffc(%%ebp);

movl 0xfffffffc(%%ebp), %%eax;

movl %%eax, %%eax;"

:

"=a"(r)

);

return r;

}

Disassembly of           section .text:

00000000 :

0:   55                        push   %ebp

1:   89 e5                   mov    %esp,%ebp

3:   83 ec 04              sub    $0x4,%esp

6:   83 ec 04              sub    $0x4,%esp

9:   8b 45 0c              mov    0xc(%ebp),%eax

c:   03 45 08              add    0x8(%ebp),%eax

f:   89 45 fc                mov    %eax,0xfffffffc(%ebp)

12:   8b 45 fc              mov    0xfffffffc(%ebp),%eax

15:   89 c0                  mov    %eax,%eax

17:   89 c0                  mov    %eax,%eax

19:   89 45 fc              mov    %eax,0xfffffffc(%ebp)

1c:   8b 45 fc              mov    0xfffffffc(%ebp),%eax

1f:   89 c0                   mov    %eax,%eax

21:   c9                       leave

22:   c3                       ret

23:   90                       nop

3> 编译可执行程序

$ vi summain.c

extern int sum(int ,int);

int main()

{

int x = sum(1,2);

printf("x = %d\n", x);

return 0;

}

$ cc -o sum_main sum_main.c sum_assemble.c

$ ./sum_main

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/295024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fstab各项参数及ls-l 长格式各项信息

/etc/fstab 下各个参数的解释 #############################################################################[rootlinux-svn ~]# cat /etc/fstab LABEL/ / ext3 defaults 1 1LABEL/boot /boot …

ajax跨域请求的问题

使用getJson跨域请求,需要向服务器发送一个参数callback? $.getJSON("http://appcenter.mobitide.com/admin/appSearch.php?callback?",{keyboard: keyboardval,searchget:1,page:1}.... $(function(){$(#search_btn).click(function (){var keyboardva…

栈和队列之设计一个有getMin(得到最小值)功能的栈

有2中方案,分别用类和内部类实现了 import java.util.Stack;/*** @author chenyu 第一种设计:* 题目:设计一个有getMin功能的栈,设计一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作* 要求:1 pop push getMin操作的时间复杂度都是O(1)* …

MongoDB基本操作(增删改查)

2019独角兽企业重金招聘Python工程师标准>>> 基本操作 基本的“增删查改“,在DOS环境下输入mongo命令打开shell,其实这个shell就是mongodb的客户端,同时也是一个js的编译器,默认连接的是“test”数据库。 【出错】 首先…

Kubernetes + .NET Core 的落地实践

1容器化背景本来生活网(benlai.com)是一家生鲜电商平台,公司很早就停止了烧钱模式,开始追求盈利。既然要把利润最大化,那就要开源节流,作为技术可以在省钱的方面想想办法。我们的生产环境是由 IDC 机房的 1…

传说中的宇宙最水诺奖得主:本科历史学,却凭借“一纸”博士论文摘取诺贝尔物理学奖,出道即巅峰!...

全世界只有3.14 % 的人关注了爆炸吧知识他,到底是不是最水的诺奖得主?超模君曾经介绍了学历史,最终成为数学、物理大牛的威滕(传送门),然而竟出现了德布罗意姥爷的高分点赞!那今天,超…

linux 连接两个异构网,如何在Linux(或异构)网络上共享计算机?

在有关共享计算机的这两篇文章中的第 1 部分中,我描述了我的异构本地网络以及如何使用它来比较和测试不同操作系统和体系结构上的应用程序。有几种技术使一台工作站上的用户可以运行位于另一台工作站上的应用程序。SSH 提供到远程计算机的文本终端;可以使…

图片处理--熔铸特效

1、算法 r r*128/(gb 1);g g*128/(rb 1);b b*128/(gr 1);2、代码实现 public Bitmap render(Bitmap bitmap){if(bitmap null)return null;int width bitmap.getWidth();int height bitmap.getHeight();int[] pixels new int[width * height];bitmap.getPixels(pixels ,0…

栈和队列之用2个栈实现一个队列

import java.util.Stack;/*** @author chenyu* 题目:编写一个类,用2个栈实现一个队列,支持队列的基本操作(add poll peek)* 思路:栈的特点是先进后出,而队列是先进先出,我们用两个栈真好把顺序反过来实现类似队列的操作,如下,将1-5依次压入stackPush,* 再讲5-1倒入st…

Windows按名称排序问题

偶然发现一个按名称排序的文件夹内,文件顺序是混乱的,例如: 在一个文件夹内建立如下三个文件: 0F.txt 1A.txt 02.txt 按名称/升序排列, 将得到上述结果,0F在最前,02在最后。 百思不得其解&#…

作业四:产品同质化问题

产品同质化问题 首先,产品同质化的定义:产品在消费者选择购买的过程中由于其功能性利益与竞争产品相同可以被竞争对手所替代,竞争对手就成为我们的替代性产品。我们的产品和竞争对手的产品形成了产品的同质化(引用自百度百科 如今…

基于事件驱动架构构建微服务第13部分:使用来自Apache KAFKA的事件并将投影流传输到ElasticSearch...

原文链接:https://logcorner.com/building-microservices-through-event-driven-architecture-part13-read-model-projection-project-streams-into-elasticsearch/在本教程中,我将展示如何从KAFKA读取流并将流投影到ElasticSearch中。我必须使用来自KAF…

惊呆了!这篇论文全文都是脏话,可编辑部居然对它评价极佳并发表了!

全世界只有3.14 % 的人关注了爆炸吧知识本文转自:募格学术你见过最奇奇怪怪的论文是什么?一教授为了抗议三流科学杂志发送垃圾邮件,回复了一篇全文只重复七个脏话字眼的论文,可没想到的是,它竟然还被 出!版…

linux daemon守护线程,线程8--守护线程Daemon

packagebook.thread;/*** Daemon(守护)线程* Daemon线程区别一般线程之处是:* 只有虚拟机中的用户线程(非Daimon线程)全部结束,Daemon线程就会立即结束,并且也不会调用finally里的语句。* daemon线程所产生的所有线程都是daemon的*/publicclassDaemon {s…

单IP无TMG拓扑Lync Server 2013:前端服务器

在前面的基础架构和活动目录两篇文章中,我们已经准备好了Lync Server的所有环境。其实今天虽然部署的是Lync Server 2013的Preview版,但实际上与我们部署Lync的步骤以及规范是完全一样的,所以大家完全可以抛开Lync Server 2013 Preview版本本…

栈和队列之仅用递归函数和栈操作逆序一个栈

import java.util.Stack;/*** recursion 递归的意思* @author chenyu* 题目:仅用递归函数和栈操作逆序一个栈,列如一次压入1、2、3、4、5 栈顶到栈底是5、4、3、2、1* 将这个栈转置后栈顶到栈底依次为1、2、3、4、5* * 思路:需要两递归函数 * 第一个递归函数是去除栈…

MySQL学习笔记之五:存储引擎和查询缓存

一、存储引擎1、InnoDB⑴InnoDB是基于聚簇索引建立的,基于主键索引查询时,性能较好;它的辅助索引中必须包含主键列;因此,若表上的索引较多,为节约空间,主键应尽可能小⑵InnoDB支持自适应hash索引…

利用SOS扩展库进入高阶.NET6程序的调试

有时候我们可能想深入到程序的运行核心,去观察下内存分配情况以及堆栈内保存的东东,那么作为编程新贵的底层框架.NET6,又为我们提供了什么可用的观测工具呢?1.SOS 扩展是什么?SOS扩展库是Windows 附带的调试扩展库&…

java--用 * 打印出各种图形(新手请进)

------------------------------------ 代码: public class PrintTriangle { public static void main(String[] args) { System.out.println("左边正三角形"); printTopLeft(5); System.out.println("左边倒三角形&quo…

这种动作片还需要汽车特效?

1 奇奇怪怪的扣分点又增加了▼2 就是活好!(素材来源网络,侵删)▼3 不愧是律师!(素材来源网络,侵删)▼4 成都马拉松惊现美食街!(素材来源网络,侵…