【软件开发底层知识修炼】十二 C/C++语言中内嵌汇编语言(asm)

上一篇文章学习了链接脚本的语法与相关概念:链接脚本的概念

在继续学习链接器的内容的同时,先学习一个新内容:内嵌汇编。

GCC编译器一般支持C/C++内嵌汇编语言,这样可以实现语言本身无法实现的内容。我们本文主要介绍C语言中的内嵌汇编,C++语言也是一样的规则。

首先要知道以下内容

x86汇编的两种语法:intel语法和AT&T语法
x86汇编一直存在两种不同的语法,在intel的官方文档中使
用intel语法,Windows也使用intel语法,而UNIX平台的汇编器一
直使用AT&T语法,所以本文是AT&T语法。 mov %edx,%eax 这条
指令如果用intel语法来写,就是 mov eax,edx ,寄存器名不加 % 号,
并且源操作数和目标操作数的位置互换。本文不详细讨论这两种
语法之间的区别,读者可以参考[AssemblyHOWTO]。
介绍x86汇编的书很多,UNIX平台的书都采用AT&T语法,例
如[GroudUp],其它书一般采用intel语法,例如[x86Assembly]。

1、C语言中的内嵌汇编

首先看一下C语言中的内嵌汇编语法格式:
在这里插入图片描述

  • 上述的volatile 关键字在以后会讲解具体作用,这里知道它是禁止编译器优化即可
  • 可选参数的意思是这些参数可以没有
  • 汇编指令是必须有的项

上述的解释还不是很好理解,我们可以看一个示例:

在这里插入图片描述
在以上的内嵌汇编中,我们可以来分析一下它的语法规则:
在这里插入图片描述

  • “movl %1, %0\n” 这句话中,%的意思是占位的意思。%1代表是一个input对应的寄存器,%0代表的是result对应的寄存器。他们所对应的寄存器是任意的,因为下面的限制符前面是 r ,代表编译器自动将通用寄存器与变量进行关联。当然这里也可以直接指定通用寄存器不用占位符。
  • 上面的图中说r这个限制符只是建议编译器用通用寄存器来与变量相关,但是编译器不一定听,比如如果在某个时候通用寄存器已经被被人占用,此时编译器就不会使用通用寄存器来关联我们的变量。
  • 带 = 号的是输出参数,即result是输出参数
  • input是输入参数
  • 上述汇编的意思是将输入参数input的值,传送给输出参数的值result。所以执行完上述汇编代码后,result与input的值都为1.

看了上面的解释,我们大概学会了内嵌汇编的组成,大致有汇编指令,这是必须存在的,可选参数,这是不必须存在的。

我们注意到上面的限制符 r 代表编译器指定一个通用寄存器关联变量,这是让编译器做主。但是我们也可以自己做主,自己指定一个寄存器来关联我们的变量。那么,都有哪些限制符以及他们对应的寄存器呢?常用的见下表:

在这里插入图片描述

上述的r代表通用寄存器,很明显与我们刚学习的一样。

1.1 代码实验

在知道了上述规则之后,我们来看看一个例子:

9-1.c

#include <stdio.h>int main()
{int result = 0;int input = 1;int a = 1;int b = 2;asm volatile ("movl %1, %0\n": "=r"(result): "r"(input));printf("result = %d\n", result);printf("input = %d\n", input);asm volatile ("movl %%eax, %%ecx\n""movl %%ebx, %%eax\n""movl %%ecx, %%ebx\n": "=a"(a), "=b"(b): "a"(a), "b"(b));printf("a = %d\n", a);printf("b = %d\n", b);return 0;
}

编译:

  • gcc 9-1.c

运行结果如下:
在这里插入图片描述

  • 分析上述代码
  1. 第一个汇编代码上述已经分析过,是将input值赋给result
  2. 第二个汇编代码块是交换a与b的值。
  • 分析第二个代码块

    • "=a"(a), "=b"(b) 代表输出参数,且将EAX寄存器与变量a关联,将EBX寄存器与b相连
    • "a"(a), "b"(b) 代表输入参数,且将EAX寄存器与变量a关联,将EBX寄存器与b相连
    • movl %%eax, %%ecx\n" 将EAX寄存器的值(也就是a的值)传送给ECX寄存器
    • movl %%ebx, %%eax\n" 将EBX寄存器的值(也就是b的值)传送给EAX,相当于将b赋给a
    • movl %%ecx, %%ebx\n" 将ECX寄存器的值(也就是a的值)传送给EBX,相当于将a赋给b

经过了上面的操作,就交换了a与b的值。

2、使用内嵌汇编进行系统调用

在程序中我们经常使用printf打印东西。中所周知,printf是一个系统函数,我们如何在不使用printf的前提下打印字符串?

使用内嵌汇编可以进行系统调用。

可以通过INT 0X80H 指令进行系统调用:

  • INT指令用于使用Linux内核服务(这是一个中断指令,众所周知中断会使执行流切换到内核)
  • 80H是一个中断向量号,用于执行系统调用

在这里插入图片描述

我们还是具体来看一个例子吧:
在这里插入图片描述

上面的解释是非常清楚的。注意区分传递的是立即数还是占位符即可。

同时,上面的例子 加了保留列表。它的意思是保留寄存器,不用于关联变量,因为这些寄存器已经被我们用于做系统调用以及传参数了。

那么上述汇编代码执行后参数s与参数l会被传给系统调用函数sys_write 。

下面再给出一个示例来看看与上面的示例有什么区别:

在这里插入图片描述

上面这个示例没有可选参数与保留列表。也就是没有输入输出参数,没有保留列表。

除了上述的区别,还有什么区别???

很明显,这个寄存器的前面是一个%,而刚刚那个是%%两个百分号。这是什么原因?

那么在内嵌汇编中就有如下注意事项:

  • 嵌入汇编时,除了汇编语言的指令不能省略,可选参数与保留列表都可以省略

  • 当省略的参数在中间时, 对应分隔符 “ : ”不可省略.如下图中的输出参数的分隔符:
    在这里插入图片描述

  • 当省略保留列表时,对应的“ : ”可忽略

  • 当省略可选参数时,寄存器前使用 % 作为前缀

  • 当有可选参数时,寄存器前使用 %% 作为前缀

2.1 代码实验

在学习了上述的一系列原理后,我们写出如下代码:

9-2.c

#include <stdio.h>int main()
{char* s = "D.T.Software\n";int l = 13;printf("main begin\n");asm volatile("movl $4, %%eax\n""movl $1, %%ebx\n""movl %0, %%ecx\n""movl %1, %%edx\n""int $0x80     \n":: "r"(s), "r"(l): "eax", "ebx", "ecx", "edx");asm volatile("movl $1,  %eax\n""movl $42, %ebx\n""int $0x80     \n");printf("main end\n");return 0;
}

运行结果:
在这里插入图片描述

可以看出,我们使用内嵌汇编打印出了"D.T.Software\n"; 并且,在第二个汇编代码块中,进行系统调用调用了sys_exit 函数,直接退出进程运行了,所以第二个printf("main end\n"); 并没有执行。

当然我们也可以使用以下命令查看最近一次的一个进程退出时的退出状态码:

  • echo $?

得出:
在这里插入图片描述

很明显,退出状态码是42,正好与我们程序中写的一样。

3、 总结

  • C程序中支持内嵌汇编
  • 通过寄存器到汇编的关联,可以实现汇编到C程序的交互
  • 内嵌汇编代码时,可以使用占位符指定交互的变量
  • 限制符建议编译器将合适的寄存器关联到变量
  • 通过内嵌汇编可以直接进行系统调用

本文参考狄泰软件学院相关课程
想学习的可以加狄泰软件学院群,
群聊号码:199546072

学习探讨加个人(可以免费帮忙下载CSDN资源):
qq:1126137994
微信:liu1126137994

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

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

相关文章

数据思维整理

数据思维整理分享

windows7下iis网站的.net框架版本设置

昨天下载了 VS2010 创建了一个默认的WebApplication&#xff0c;想看看在iis中运行的情况&#xff0c;虽说用了几个月的 win7 &#xff0c;但还从没有用过IIS。首先给人的感觉是IIS变化很大&#xff0c;多出了很多东西&#xff0c;让人感到很茫然。 先建个网站试试&#xff0c;…

【OS学习笔记】二十三 保护模式七:保护模式下任务的隔离与任务的特权级概念

上一篇文章学习了保护模式下操作系统内核如何加载程序并运行&#xff1a;点击链接查看上一篇文章 本篇文章接着上一篇文章学习保护模式下任务的隔离。 包括以下学习内容&#xff1a; 任务的全局空间和局部空间任务的TSS任务的LDT任务的特权级概念等 1、回顾 在保护模式下&…

[Drupal] How to add the js file and js code block in Drupal

Drupal 6:代码//This will add a JS file to your head (specifically the $scripts variable in page.tpl.php)drupal_add_js(drupal_get_path(module,my_module) ./my_module.js); //This add inline JS to the head of the documentdrupal_add_js(alert("Hello!"…

【OS学习笔记】二十四 保护模式七:调用门与依从的代码段----特权级保护

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 上一篇文章学习了保护模式下的任务与任务隔离&#xff0c;以及简单介绍了保护模式下的特权级的概念。点击链接查看上一篇文章&#xff1a;任务与任务隔…

【OS学习笔记】二十六 保护模式八:任务门---任务切换

上一篇文章学习了&#xff1a;保护模式七&#xff1a;调用门与依从的代码段----特权级保护 主要学习了以下内容&#xff1a; 描述符特权级&#xff08;目标对象的特权级&#xff09;DPL 描述符特权级&#xff08;目标对象的特权级&#xff09;DPL 当前特权级CPL 低特权级的应…

腾讯微博应用

腾讯微博开放平台提供了一些官方微博应用&#xff0c;供开发者借鉴和利用&#xff0c;其中包括&#xff1a; 一键转播——嵌入一键转播到你的网站里&#xff0c;访客便能将网页信息直接传播至腾讯微博。分享资讯的同时&#xff0c;用户通过来源链接可进入你的网站&#xff0c;从…

【OS学习笔记】二十七 保护模式八:任务切换的方法之----jmp与call的区别以及任务的中断嵌套

上一篇文章学习了任务门的概念&#xff1a;任务门—任务切换。主要学习了以下内容&#xff1a; 使用任务门进行任务切换的一般工作原理&#xff08;和中断有关的任务切换&#xff09; 本篇文章接着上一篇文章学习以下内容&#xff1a; 利用jmp进行任务切换利用call进行任务切…

Windows Phone 7 开发 31 日谈——第22日:应用?还是 游戏?

本文是“Windows Phone 7 开发 31 日谈”系列的第22日。 昨天&#xff0c;我发了一篇极长的关于Silverlight Toolkit for Windows Phone的文章。今天的会短一些&#xff0c;但却非常珍贵。我会讨论你的应用程序设置中非常细微但很重要的设置&#xff1a;类别&#xff08;Genre&…

《Advanced .NET Debugging》 读书笔记 Listing 3-6: 使用sxe在程序载入mscorwks之后停下来载入sos...

1. 在WinDbg下载入01MDASample.exe 2. 执行 sxe ld mscorwks.dll 该命令的作用是在进程载入mscorwks之后停下来 3. 执行 g 可见程序在载入mscorwks.dll 之后停下来了 4. 执行 .loadby sos.dll mscorwks 转载于:https://www.cnblogs.com/charrli/archive/2010/12/25/1916964.h…

转载并学习实现三重DES加密解密代码(一)

作者:finallyliuyu 出处&#xff1a;博客园 声明&#xff1a;此篇博文代码来自于邹德强先生。由于目前找到的版本是残缺版&#xff0c;所以我又进行了补全。读一份好代码&#xff0c;可以领略到作者的编程风格和语言驾驭能力&#xff0c;同时又能从其中汲取养分。现将我所修改后…

【OS学习笔记】三十 保护模式九:段页式内存管理机制概述

上几篇文章学习了任务切换相关知识&#xff0c;如下&#xff1a; 【OS学习笔记】二十六 保护模式八&#xff1a;任务门—任务切换【OS学习笔记】二十七 保护模式八&#xff1a;任务切换的方法之----jmp与call的区别以及任务的中断嵌套 今天继续学习保护模式下的分页机制。本篇…

真人拳皇项目第六次Scrum总结——史经浩

今天&#xff0c;我们组开始了正式的编码阶段&#xff0c;前期plan的时候天马行空&#xff0c;现在是脚踏实地的coding了。在Scrum上&#xff0c;大家sync了一下各自的进展&#xff0c;如下&#xff1a; 今天 进度 问题及解决 明天 田飞 work item 37528:DirectX动画的de…

【OS学习笔记】三十一 保护模式九:页目录、页表和页三者的关系详解

上一篇文章学习了&#xff1a;保护模式九&#xff1a;段页式内存管理机制概述 本篇文章接着学习以下内容&#xff1a; 页目录概念页表概念页目录、页表与页之间的关系虚拟地址&#xff08;线性地址&#xff09;到物理地址的具体变换过程。 1、页目录、页表和页的对应关系 第…

使用某个文件夹下的所有文件去替换另一个文件夹下及其子文件夹下存在的同名文件(Python实现)...

值此新年即将到来之际,在这献上今年最后一篇文章. 产生这个需求是在项目的一次图标替换上,当时给了我一堆新图标要替换原来的老图标,可是原来的老图标分布在某个文件夹下的各个子文件夹下面,而新图标全是在同一个目录下的. 手动替换的话,只能是搜索文件名后替换,但是文件很多太…

一款研发管理软件的对象标签介绍

如果你了解WIKI&#xff0c;WIKI中的所有信息链接以标签的方式网状关联。TOPO系统中实现了完整的TAG功能&#xff0c;区别于目前市面上的其他类似管理系统&#xff0c;TOPO系统中实现的标签功能更加彻底和全面&#xff0c;例如完全用户自定义TAG&#xff0c;系统中所有管理对象…

【OS学习笔记】三十四 保护模式十:中断和异常区别

上几篇文章学习了分页机制的一些原理&#xff1a; 【OS学习笔记】三十 保护模式九&#xff1a;段页式内存管理机制概述【OS学习笔记】三十一 保护模式九&#xff1a;页目录、页表和页三者的关系详解 今天继续学习保护模式下的关于中断与异常的概念。本文主要学习中断与异常的…

记录一次文件迁移

事情的经过是这样子的&#xff01;数据库A表添加一条记录&#xff0c;**系统中B目录下就会多出5n个文件。随着系统运行3年多&#xff0c;B目录中的文件数已高达2M多&#xff0c;而这些文件恰恰又是用户高度频繁访问的。于是问题就来了&#xff0c;一方面是用户访问文件速度变慢…

【OS学习笔记】三十五 保护模式十:中断描述符表、中断门和陷阱门

上一篇文章学习了中断与异常的概念&#xff1a;【OS学习笔记】三十四 保护模式十&#xff1a;中断和异常区别 本片文章接着学习以下内容&#xff1a; 中断描述符表中断门陷阱门 1 中断描述符表 我们前面讲了无数次&#xff0c;在实模式下&#xff0c;是由位于低地址的1M内存…

【OS学习笔记】三十六 保护模式十:通过中断发起任务切换----中断任务

上一篇文章学习了&#xff1a;OS学习笔记】三十五 保护模式十&#xff1a;中断描述符表、中断门和陷阱门 本篇文章接着上一篇文章学习中断任务。 我们在前面文章中一直在说通过中断发起任务切换&#xff0c;本文就是将之前没有说明白的内容&#xff1a;通过中断发起任务切换讲…