① arm linux 应用程序 如何内嵌汇编
在linux源代码中会有一部分c语言与汇编语言相交融的部分。
其中linux中汇编语言采用的不是我们通用的intel的汇编语言,而是采用的是AT&T格式的汇
编语言,它们之间有一些差别:
1
目标与源的方向不大一样
mov
ax,
bx
mov
%bx,
%ax
2
AT&T寄存器前要加入%
ax
%ax
3
AT&T立即数前面要加上$
add
ax,
4
add
%ax,$4
4
对于访问指令的操作数大小
intel的格式是在操作数前加上BYTE
PTR、DWORD
PTR等等
AT&T格式:在操作数后面加上b、l、w等
MOV
AL,
BYTE
PTR
FOO(intel)
movb
FOO,
%al
(AT&T)
5
间接寻址:
SECTION:[BASE+INDEX*SCALE+DISP]
Section:disp(base,
index,
scale)
C语言中插入汇编代码比纯粹的汇编要难,因为要设计到“如何分配使用寄存器、怎样与C语
言中变量相结合”
下面“=”代表只读,“+”代表读写
每个输出部分均以=开始
比如我想定义一个char型的变量,放入ax中
register
char
_temp
asm
("ax");
register
char
_temp
__asm__
("ax");
以上两种方式均正确
在这里我们通常看到普通的寄存器前面有两个%,代表下面的意思:第一寄存器前要有一个%
第二对于一个模板前要加入一个%
下面以一个在内核中常见的目的为了实现原子操作的一个函数为例子atomic_add来介绍
static
__inline__
void
atomic_add(int
i,
atomic_t
*v)
{
__asm__
__volatile__(
LOCK
"addl
%1,
%0"
:"=m"(v->counter)
:"ir"(i),
"m"(v->counter)
);
}
ir代表一个寄存器中的直接操作数
首先一个头部:__asm__
__volatile__();
asm();
__asm__();告诉编译器里面是汇编语言
:第一个冒号是输出部分:第二个冒号是输入部分
其实还有第三个冒号:代表着损坏部分
asm("汇编语句"
:输出部分
:输入部分
:损坏部分)
%0、%1
等等代表着一种模板操作数,其中数字到几取决于cpu寄存器数量
"m",
"v",
"o"
--内存单元
"r"
任意寄存器
"q"
表示eax、ebx、ecx、edx之一
"i",
"h"
表示立即数
"a",
"b",
"c",
"d"表示eax、ebx、ecx、edx
关键字LOCK表示在执行的时候把系统总线锁住,不让其他
cpu干扰。
② 内联汇编的GNU 汇编程序简述
Linux 中使用的基本汇编程序语法。GCC(用于 Linux 的 GNU C 编译器)使用 AT&T 汇编语法。下面列出了这种语法的一些基本规则。 asm ( assembler template
: output operands (optional)
: input operands (optional)
: list of clobbered registers
(optional)
);
本例中,汇编程序模板由汇编指令组成。输入操作数是充当指令输入操作数使用的 C 表达式。输出操作数是将对其执行汇编指令输出的 C 表达式。
内联汇编的重要性体现在它能够灵活操作,而且可以使其输出通过 C 变量显示出来。因为它具有这种能力,所以 asm 可以用作汇编指令和包含它的 C 程序之间的接口。
一个非常基本但很重要的区别在于 简单内联汇编只包括指令,而 扩展内联汇编包括操作数。要说明这一点,考虑以下示例: { int a=10, b; asm (movl %1, %%eax; movl %%eax, %0; :=r(b) /* output */ :r(a) /* input */ :%eax); /* clobbered register */}
在上例中,我们使用汇编指令使 b 的值等于 a。请注意以下几点:
b 是输出操作数,由 %0 引用,a 是输入操作数,由 %1 引用。 r 是操作数的约束,它指定将变量 a 和 b 存储在寄存器中。请注意,输出操作数约束应该带有一个约束修饰符 =,指定它是输出操作数。 要在 asm 内使用寄存器 %eax,%eax 的前面应该再加一个 %,换句话说就是 %%eax,因为 asm 使用 %0、%1 等来标识变量。任何带有一个 % 的数都看作是输入/输出操作数,而不认为是寄存器。 第三个冒号后的修饰寄存器 %eax 告诉将在 asm 中修改 GCC %eax 的值,这样 GCC 就不使用该寄存器存储任何其它的值。 movl %1, %%eax 将 a 的值移到 %eax 中, movl %%eax, %0 将 %eax 的内容移到 b 中。 因为 b 被指定成输出操作数,因此当 asm 的执行完成后,它将反映出更新的值。换句话说,对 asm 内 b 所做的更改将在 asm 外反映出来。
③ 如何在linux下c++程序里嵌入汇编语句
gcc/g++嵌入的是AT&T汇编,语句用双引号括起来,每句以\n\r结尾!
我只写一段示例,剩下的你照做可以了:
WORD lookKbits(BYTE k)
{
_asm {
“movb k,%%dl\\n\\r”
"movb $16,%%cl\\n\\r"
"sub %%dl,%%cl\\n\\r"
"movl [wordval],%%eax\\n\\r"
"shrl %%cl,%%eax\\n\\r"
}
}
④ 一个简单的内联汇编问题:
下面是在我电脑上你插入的汇编模板最终生成的汇编码,估计你电脑上应该也差不多。
0x080483c4 <+0>: push %ebp
0x080483c5 <+1>: mov %esp,%ebp
0x080483c7 <+3>: push %ebx
0x080483c8 <+4>: sub $0x10,%esp
0x080483cb <+7>: movl $0x0,-0x8(%ebp)
0x080483d2 <+14>: add 0x8(%ebp),%ebx
0x080483d5 <+17>: add 0xc(%ebp),%ebx
=> 0x080483d8 <+20>: mov %ebx,-0x8(%ebp)
0x080483db <+23>: mov -0x8(%ebp),%eax
0x080483de <+26>: add $0x10,%esp
0x080483e1 <+29>: pop %ebx
0x080483e2 <+30>: pop %ebp
0x080483e3 <+31>: ret
下面3行汇编码是用来求和的,你可以看到和最终被放到了寄存器ebx里面,但是ebx的初始值并不一定是0(因为ebx并未被清零),所以最终的和是一个不可预料的数字,这就是为什么你得到的输出不对的原因。
0x080483d2 <+14>: add 0x8(%ebp),%ebx
0x080483d5 <+17>: add 0xc(%ebp),%ebx
=> 0x080483d8 <+20>: mov %ebx,-0x8(%ebp)
你的汇编模板部分肯定写错了,你找份资料再好好看看。兄弟,看在哥哥写这么长的份儿上,可以给点分吧。
⑤ 内联汇编的介绍
内联汇编,指在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法。
⑥ 请问linux里面用的汇编是vc内嵌汇编吗 如:__asm__ ("movw %%dx,%%ax\n\t" )
不是的。linux汇编一定与windows汇编有很大不同,因为内核不同,而且vc内汇编和windows纯汇编还有区别【没那么底层】
不过你要是问基本词句,那是差不多一样的。
⑦ linux内核:什么叫做内联汇编
就是在C语言中可以插入汇编语言,,,
比如 插入汇编
----------------C语言----------------
ASM
{
mov r1,r2
stl r2,0101 代码我乱写的 我给你看个大概而已
}
----------------C语言----------------
当然 要嵌入汇编
最开始的宏定义还要加上
#include <linux/asm> 好像是这个..好久不做linux了..最近作FPGA 都糊涂了
⑧ linux内核代码 汇编部分 疑问
没研究过。
不过我记得 Linux 内核其实是两部分,真正的内核本体是在内核文件的后部,一般都是压缩的。之前是一个这个架构通用的启动代码,应该就是你这个汇编。
bootloader 的作用是把内核读取到指定地址,之后运行这个内核,这样运行的恰恰就是这段汇编写的启动代码,这个启动代码的作用就是初始化环境,之后把后面本体的内核解压缩并且写到内存开始部分(忘了叫什么名字)正好盖掉 bootloader ,并且继续运行。这样这个运行的内核才是最终的 Linux 内核。(至少 x86 是这样)
但每个 CPU 架构的启动过程又有不同的地方。应该每个 CPU 都有自己特定的头部启动代码。
你说这三个文件应该是有不同目的的。compressed 应该是解压用的,kernel 里面的应该是执行主要启动过程的。那个 common.s 应该是“通用”部分代码模块。我的 comperssed 里面还有很多 lzma 、gzip 、lzo 以及一些设备名称的东西,应该都是“模块”一类的吧。
你看看 Makefile 的编译过程应该就能开除编译调用的文件都是什么了。
还有,你看源代码最好看原版的,如果使用,那就去用针对性的。不然赶上找抽的人,可能针对某个开发板的代码,会因为太过针对而不符合通用的一些规定或者习惯。
⑨ linux能运行汇编语言么
当然可以,在
嵌入式linux
中有一部分引导程序只能用汇编写,如果不能运行,那么linux岂不是垃圾么,当然,你得有相应的
编译器
才行。