1. linux 內核0.11閱讀困惑
1、你說的「圖5-3顯示, fs先入棧,ebx後入棧」是不對的,恰好反了。
書上原話"在開始內執行程序容之前,堆棧指針 esp 指在中斷返回地址一欄 ( 圖中 esp0 處 ) 。當把將要調用的 C 函數do_divide_error()或其它 C 函數地址入棧後,指針位置是 esp1 處",這已經說明esp0的地址高於esp1的地址。同理ebx地址高於fs地址,即ebx先入棧。
2、3都是關於gnu內嵌匯編問題,需要自己看書的。
#define outb_p(value,port) \
__asm__ ("outb %%al,%%dx\n" \
"\tjmp 1f\n" \
"1:\tjmp 1f\n" \
"1:"::"a" (value),"d" (port))
相當於:
mov (value),%eax
mov (port),%edx
outb %al,(%dx)
就是給某個埠port發數據value的,<<微機介面>>里很多例子,例如給中斷控制器8259A初始化就是這樣做的。
2. 誰知道在linux下的常用後綴名啊
在Linux系統中,可執行文件沒有統一的後綴,系統從文件的屬性來區分可執行文件版和不可執行文件。而gcc則通權過後綴來區別輸入文件的類別,下面我們來介紹gcc所遵循的部分約定規則。
.c為後綴的文件,C語言源代碼文件;
.a為後綴的文件,是由目標文件構成的檔案庫文件;
.C,.cc或.cxx 為後綴的文件,是C++源代碼文件;
.h為後綴的文件,是程序所包含的頭文件;
.i 為後綴的文件,是已經預處理過的C源代碼文件;
.ii為後綴的文件,是已經預處理過的C++源代碼文件;
.m為後綴的文件,是Objective-C源代碼文件;
.o為後綴的文件,是編譯後的目標文件;
.s為後綴的文件,是匯編語言源代碼文件;
.S為後綴的文件,是經過預編譯的匯編語言源代碼文件。
3. 關於Linux中禁用中斷和鎖定的關系問題
首先原子操作是通過local_irq_enable()這個宏來實現,這個宏實現了硬體中斷和軟體中斷的屏版蔽。這樣CPU就不權能被軟體中斷,如線程搶占。而當硬體中斷產生時,會將其結果保存到中斷控制器的SRCPND(resource-pend)寄存器中,然後將SRCPND的內容送去做中斷屏蔽檢測,這一工作由設置MASK寄存器相應的位完成,如果全部屏蔽,硬體中斷就不會產生了。當然了,每種處理器都有自己的中斷處理方法,通常的流程是這樣。
4. 如何在C語言中嵌入匯編
以下所說嵌入的匯編都是 的C語言中嵌入ARM匯編。
1)2個參數的內嵌語句
這種形式的匯編用於簡單的語句,參數限制輸入和輸出語法格式如下:
asm(code : output operand list : inputoperand list : clobber list);
匯編和C語句這間的聯系是通過上面asm聲明中可選的output operand list和input operand list。Clobber list後面再講。
下面是將C語言的一個整型變數傳遞給匯編,邏輯左移一位後在傳遞給C語言的另外一個整型變數。
/* Rotating bits example */
asm("mov %[result], %[value], ror#1" : [result] "=r" (y) : [value] "r" (x));
每一個asm語句被冒號(:)分成了四個部分。
匯編指令放在第一部分中的「」中間。
"mov %[result], %[value], ror #1"
接下來是冒號後的可選擇的output operand list,每一個條目是由一對[](方括弧)和被他包括的符號名組成,它後面跟著限制性字元串,再後面是圓括弧和它括著的C變數。這個例子中只有一個條目。
[result] "=r" (y)
接著冒號後面是輸入操作符列表,它的語法和輸入操作列表一樣
[value] "r" (x)
為了增加代碼的可讀性,你可以使用換行,空格,還有C風格的注釋。
asm("mov %[result], %[value], ror#1"
: [result]"=r" (y) /* Rotation result. */
: [value]"r" (x) /* Rotated value. */
: /* No clobbers */
);
在代碼部分%後面跟著的是後面兩個部分方括弧中的符號,它指的是相同符號操作列表中的一個條目。
%[result]表示第二部分的C變數y,%[value]表示三部分的C變數x;
符號操作符的名字使用了獨立的命名空間。這就意味著它使用的是其他的符號表。簡單一點就是說你不必關心使用的符號名在C代碼中已經使用了。在早期的C代碼中,循環移位的例子必須要這么寫:
asm("mov %0, %1, ror #1" :"=r" (result) : "r" (value))
在匯編代碼中操作數的引用使用的是%後面跟一個數字,%1代表第一個操作數,%2代碼第二個操作數,往後的類推。這個方法目前最新的編譯器還是支持的。但是它不便於維護代碼
實例代碼:
2) 帶.s文件的匯編
編譯命令:
arm-linux-gcc main.cAsmfile_gnu.s -o mains
main.c
#include<stdio.h>
extern voidpcm8_2_pcm16(unsigned char* pIn, int nInlen, short* pOut);
extern voidpcm16_2_pcm8(short* pIn, int nInlen,unsigned char* pOut);
int main()
{
unsigned char* pIn="1234";
short pInd[256];
unsigned char pOutd[256];
int nInlen=4;
int i = 0;
short pOut[256];
for(i=0;i<4;i++)
printf(" 0x%x ",pIn[i]);
printf(" ");
memset((char *)pOut,0,256*2);
memset((char *)pInd,0,256*2);
memset((char *)pOutd,0,256*2);
pcm8_2_pcm16(pIn,nInlen,pOut);
for(i=0;i<4;i++)
printf(" 0x%x ",pOut[i]);
printf(" ");
memcpy((char *)pInd,(char *)pOut,256*2);
pcm16_2_pcm8(pInd,nInlen,pOutd);
for(i=0;i<4;i++)
printf(" 0x%x ",pOutd[i]);
printf(" ");
return 0;
}
Asmfile_gnu.s
.text
.global pcm8_2_pcm16
.global pcm16_2_pcm8
#*******************************#
#********* ENCODER 實現將第一個輸入參數
#左移8位然後異或0x8000 然後拷貝到第三個參數
#DECODE 取第一個參數所指的數據先異或0x8000
#然後右移8位將數據拷貝到第三個參數
#*******************************
pcm8_2_pcm16:
MOV R6,#0
MOV R7,#0
ENCODER:
LDRB R5,[R0,R6]
MOV R8,R5,LSL#8
EOR R9,R8,#0x8000
STRH R9,[R2,R7]
ADD R7,R7,#2
ADD R6,R6,#1
SUB R1,R1,#1
CMP R1,#0
BNE ENCODER
B OVER
pcm16_2_pcm8:
MOV R6,#0
MOV R7,#0
DECODE:
LDRH R5,[R0,R6]
EOR R8,R5,#0x8000
MOV R9,R8,LSR#8
STRB R9,[R2,R7]
ADD R7,R7,#1
ADD R6,R6,#2
SUB R1,R1,#1
CMP R1,#0
BNE DECODE
OVER:
.end