1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
开始
对于基于ARM的RISC处理器,GNU C编译器提供了在C代码中内嵌汇编的功能。这种特性提供了C代码没有的功能,比如手动优化软件关键部分的代码、使用相关的处理器指令。 __asm__ __volatile__("hlt"); "__asm__"表示后面的代码为内嵌汇编,"asm"是"__asm__"的别名。"__volatile__"表示编译器不要优化代码,后面的指令保留原样,"volatile"是它的别名。括号里面是汇编指令。 汇编指令模板 使用内嵌汇编,要先编写汇编指令模板,然后将C语言表达式与指令的操作数相关联,并告诉GCC对这些操作有哪些限制条件。 让我们以一个简单的例子开始: asm( "mov r0, r0nt" "mov r0, r0" ); /* NOP 例子 */ 该语句的作用是将r0移动到r0中。换句话讲他并不干任何事。典型的就是NOP指令,作用就是短时的延时。可以在一个asm声明中写多个汇编指令。但是为了增加程序的可读性,最好将每一个汇编指令单独放一行。换行符和制表符的使用可以使得指令列表看起来变得美观(不加n编译会报错)。 1.”NOP"指令即空指令, 2. 运行该指令时单片机什么都不做,但是会占用一个指令的时间。 3. 当指令间需要有延时(给外部设备足够的响应时间;或是软件的延时等),可以插入“NOP”指令。 通用的内嵌汇编模版是这样的: asm(code : output operand list : input operand list : clobber list); 汇编和C语句之间的联系通过上面asm声明中可选的output operand list和input operand list。Clobber list后面再说。 下面是将C语言的一个整型变量传递给汇编,传递给C语言的另外一个整型变量。 int x = 5, y = 0; __asm__("mov %[output], %[input]n" : [output] "=r"(y) : [input] "r" (x)); 汇编指令 每一个asm语句被冒号(:)分成了四个部分。汇编指令放在第一部分中的“”中间。 "mov %[output], %[input]n" 操作数列表 接下来是冒号后的可选择的output operand list:input operand list,每一个条目是由一对[](方括号)和被他包括的符号名组成,它后面跟着限制性字符串,再后面是圆括号和它括着的C变量。 "output"前面的限制字符串是"=r",其中output"是输出操作数,"r" 表示需要将"result"与某个通用寄存器相关联,先将操作数的值读入寄存器,然后在指令中使用相应寄存器,而不是"output"本身,当然指令执行完后需要将寄存器中的值存入变量"output",从表面上看好像是指令直接对"result"进行操作,实际上GCC做了隐式处理,这样我们可以少写一 些指令。"input"前面的"r"表示该表达式需要先放入某个寄存器,然后在指令中使用该寄存器参加运算。 C表达式或者变量与寄存器的关系由GCC自动处理,我们只需使用限制字符串指导GCC如何处理即可。限制字符必须与指令对操作数的要求相匹配,否则产生的 汇编代码将会有错,读者可以将上例中的两个"r",都改为"m"(m表示操作数放在内存,而不是寄存器中),编译后得到的结果是: movl input, result 很明显这是一条非法指令,因此限制字符串必须与指令对操作数的要求匹配。例如指令movl允许寄存器到寄存器,立即数到寄存器等,但是不允许内存到内存的操作,因此两个操作数不能同时使用"m"作为限定字符。 上面NOP例子的输出如下: 破坏符列表 有时候,当你想通知GCC当前内联汇编语句可能对某些寄存器和内存进行修改,希望GCC将这一点考虑进去,此时就可以在Clobber/Modify域中进行声明这些寄存器和内存。 这种情况一般发生在一个寄存器出现在Instructionlist,但不是有Output/Input操作表达式所指 定的,也不是在一些Output/Input操作表达式使用“r”约束时有GCC为其选择的,同时此寄存器被Instructionlist修改,而这个寄存器只是供当前内联汇编使用的情况。 例如:__asm__ (“mov R0, #0x34” ::: “R0”)寄存器R0出现在Instructionlist中,且被mov指令修改,但却未被任何Output/Input操作表达式指定,所以需要在Clobber/Modify域中指定“R0”,让GCC知道这一点。 因为你在Output/Input操作表达式所指定的寄存器,或当你为一些Output/Input表达式使用“r”约束,GCC为你选择一个寄存器,编译器对这些寄存器是非常清楚的, 它知道这些寄存器是被修改的,因此不需要在Clobber/Modify域中在声明它们。除此之外,GCC对剩下的寄存器中哪些会被当前内联汇编修改一无所知。所以,如果当前内联汇编修改了这些寄存器,就最好在Clobber/Modify域中声明,让GCC针对这些寄存器做相应的处理,否则可能会造成寄存器 的不一致,造成程序执行错误。 注意事项 就像上面的NOP例子,asm声明的4个部分中,只要最尾部没有使用的部分都可以省略。但是有有一点要注意的是,上面的4个部分中只要后面的还要使用,前面的部分没有使用也不能省略,必须空但是保留冒号。为了增加代码的可读性,你可以使用换行,空格,还有C风格的注释。 在早期的C代码中还有如下写法: asm("mov %0,%1" : "=r" (output) : "m" (input));在汇编代码中操作数的引用使用的是%后面跟一个数字,%1代表第一个操作数,%2代码第二个操作数,称为占位符,往后的类推。操作数至多有10 个,用"%0","%1"...."%9"表示。这个方法目前最新的编译器还是支持的。但是它不便于维护代码。试想一下,你写了大量的汇编指令的代码,要是你想插入一个操作数,那么你就不得不从新修改操作数编号。 为什么需要汇编
|
|
|
|
只有小组成员才能发言,加入小组>>
2553 浏览 0 评论
1152浏览 2评论
750浏览 1评论
504浏览 0评论
269浏览 0评论
433浏览 0评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 17:31 , Processed in 1.339209 second(s), Total 80, Slave 62 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号