热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入了解嵌入式汇编:探索嵌入式系统中的汇编语言

具有输入和输出参数的嵌入式汇编语句的基本格式为:asm(汇编语句:输出寄存器:输入寄存器:会被修改的寄存器);除第一行以外,后面带冒号的行若不使用就

      具有输入和输出参数的嵌入式汇编语句的基本格式为:

             asm("汇编语句"

                      :输出寄存器

                      :输入寄存器

                      :会被修改的寄存器);

       除第一行以外,后面带冒号的行若不使用就都可一省略。其中 “asm” 是内联汇编语句关键词。"汇编语句"是你写汇编指令的地方。“输出寄存器”表示当这段嵌入汇编执行完之后,那些寄存器用于存放输出数据。这些寄存器会分别对应一C语言表达式值或一个内存地址。“输入寄存器”表示在开始执行汇编代码时,这里指定的一些寄存器中应存放的输入值,它们也分别对应着一C变量或常数值。“会被修改的寄存器”表示你已对其中列出的寄存器中的值进行了改动,gcc编译器不能再依赖于它原来对这些寄存器加载的值。如果必要的话,gcc需要重新加载这些寄存器。因此我们需要把那些没有在输出/输入寄存器中的部分列出,但是在汇编语句中明确使用到或隐含使用到的寄存器名列在这个部分。

1       #define   get_seg_byte(seg,addr)  \

2       ( {   \

3        register  char  _res ;   \                                                   //定义了一个寄存器变量——res

4        _asm_("push     %%fs ;  \                                              //保存fs寄存器原值

5                    mov       %%ax,%%fs ;    \                                   //用seg设置fs

6                    movb     %%fs:%2,%%al ;     \                             //取seg:addr处1字节内容到al寄存器

7                    pop        %%fs "           \                                    //恢复fs寄存器原内容

8                    : "=a"  (_res)          \

9                    : "0"   (seg),   "m"  ( * (addr) ) ) ; \

10      _res ;  } )

     这段代码定义了一个嵌入式汇编语言函数。通常使用汇编语言最方便的方法是把他们放在一个宏内。用圆括号括住的组合语句(花括号中的语句)“({})”可以作为表达式使用,其中最后一行的变量_res是该表达式的输出值。

     因为宏语句需要定义在一行上,因此这里使用反斜杠“\”将这些语句连成一行。这条红第一将被替换到程序中引用改宏名称的地方。第一行定义了宏的名称,即宏函数名称get_seg_byte(seg,addr)。第三行定义了一个寄存器变量_res。该变量将被保存在一个寄存器中,以便快速访问和操作。如果想指定寄存器(如eax),那么我们可以把改句写成"register char _res asm("ax");",其中asm也可以写成_asm_。第四行上的_asm_表示嵌入式汇编语句的开始。第4-7行的4条语句是AT&T格式的汇编语句。另外,为了让gcc编译产生的汇编语言程序中寄存器名称前有一个百分号“%”,在嵌入汇编语句寄存器名称前就必须写上两个百分号“%%”。

     第8行即输出寄存器,该语句的含义是在这段代码运行结束后将eax所代表的的寄存器的值放入_res变量中,作为本函数的输出值,“=a”中的“a”称为加载代码,“=”表示这是输出寄存器,并且其中的值将被输出值替代。加载代码是CPU寄存器,内存地址以及一些数值的简写字母代号。第9行表示在这段代码开始运行时将seg放到eax寄存器中,“0”表示使用与上面相同位置上的输出寄存器。而((*addr))表示一个内存偏移地址值。为了在上面汇编语句中使用该地址值,嵌入式汇编程序规定把输出和输入寄存器按统一顺序编号,顺序是从输出寄存器序列从左到右从上到下以“%0”开始,分别记为%0、%1···%9.因此,输出寄存器的编号是%0(这里只有一个输出寄存器),输入寄存器前一部分(“0”(seg))的编号是%1,而后部分的编号是%2。上面第6行上的%2即代表(*(addr))这个内存偏移量。

 

                                                                                                    常用寄存器加载代码说明

代码说明代码说明
a使用寄存器eaxm使用内存地址
b使用寄存器ebxo使用内存地址并可以加偏移值
c使用寄存器ecxI使用常数0-31
d使用寄存器edxJ使用常数0-63
S使用esiK使用常数0-255
D使用ediL使用常数0-65535
q使用动态分配字节可寻址寄存器(eax,ebx,ecx或edx)M使用常数0-3
r使用任意动态分配的寄存器N使用1字节常数(0-255)
g使用通用有效的地址即可(eax,ebx,ecx,edx或内存变量)O使用常数0-31
A使用eax与edx联合(64位)=输出操作数,输出值将替换前值
+表示操作数可读可写&早期汇编的操作数。表示在使用完操作数之前,内容会被修改

             

 

转:https://www.cnblogs.com/lsf90/archive/2012/02/21/embed.html



推荐阅读
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • c语言基础编写,c语言 基础
    本文目录一览:1、C语言如何编写?2、如何编写 ... [详细]
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼*madebyebhrz*#include#include#include#include#include#include#include ... [详细]
  • C语言的经典程序有哪些
    本篇内容介绍了“C语言的经典程序有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何 ... [详细]
  • Linux下C语言的几道经典面试题小结(分享)
    本篇文章整理了几道Linux下C语言的经典面试题,相信对大家更好的理解Linux下的C语言会有很大的帮助,欢迎大家探讨指正。1、如果在Linux下使用GCC ... [详细]
  • MySQL5.6.40在CentOS764下安装过程 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • linux 字符串数组初始化,C++字符数组初始化方法的分析
    发现了一个字符数组初始化的误区,而这个往往能导致比较严重的性能问题,分析介绍如下:往往我们在初始化一个字符数组,大概有如下几 ... [详细]
  • c语言翁恺28讲,翁恺的c语言视频怎么样
    本文目录一览:1、翁凯的c语言视频多长时间2、 ... [详细]
author-avatar
mobiledu2502883785
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有