① 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豈不是垃圾么,當然,你得有相應的
編譯器
才行。