日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

汇编语言笔记-ARM架构指令集

發布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 汇编语言笔记-ARM架构指令集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 指令的執行
  • 指令后綴
  • 指令集
    • 數據傳送指令
      • 處理器內數據傳送
    • 存儲器訪問指令
      • 不同數據大小的存儲器訪問
      • 存儲器訪問方式(地址表達式)(部分省略)
        • 立即數偏移(前序)
        • 寄存器偏移
        • 多加載和多存儲
        • 壓棧和出棧
    • 算術運算
    • 邏輯運算
    • 移位
    • 數據轉換
      • 展開
      • 反轉
    • 位域處理
    • 比較和測試
    • 程序流控制
      • 跳轉
      • 函數調用
      • 條件跳轉
      • 比較并跳轉
      • 條件執行(IT指令)
      • 表格跳轉
    • 飽和運算
    • 異常相關
    • 休眠模式相關
    • 存儲器屏障
    • 其它指令

???????偽指令和指令的區別:只存在于匯編語言中,而不存在于機器語言中。幫助編譯器將匯編語言(或者其它高級語言)轉換成機器語言(偽指令被編譯時被等效的指令替換)。

ARM架構的操作狀態有Thumb狀態和ARM狀態之分(當然還有調試狀態):

?Thumb狀態ARM狀態
指令集Thumb指令集ARM指令集
指令長度16位(半字指令)32位
指令執行條件大多數指令無條件執行大多數指令有條件執行
優點低功耗,存儲空間要求低代碼需要的指令數少,性能高

Cortex-M系列不支持ARM狀態,因此本文內容基于Thumb狀態進行撰寫。

Thumb指令集的操作數和指令地址仍為32位

指令的執行

???????程序要執行的指令都保存在存儲器中(指令轉化為機器碼,也稱操作碼)。當計算機需要執行一條指令時,首先產生這條指令的地址,并根據地址號打開相應的存儲單元并取出指令代碼,最后CPU根據指令代碼的要求以及指令中的操作數去執行相應的操作。

指令后綴

后綴描述
S更新APSR(應用程序狀態寄存器,如進位、溢出、零和負標志),例如:ADDS R0,R1;該ADD操作會更新APSR
EQ, NE, CS, CC, MI,PL,VS,VC,HI,LS,GE, LT, GT, LE條件執行后綴,若滿足相應條件則執行后面的語句,例如:BEQ label;若之前的操作得到相等的狀態(狀態寄存器Z置位),則跳轉至 label,各個條件碼的介紹如條件碼介紹表所示
.N,.W指定使用的是16位指令( narrow)或32位指令(wide)
.32,.F32指定32位單精度運算,對于多數工具鏈,32后綴是可選的
.64,.F64指定64位單精度運算,對于多數工具鏈,64后綴是可選的

可以通過S后綴的指令影響狀態寄存器的標志位,再通過各類條件碼后綴執行相應判斷

條件碼助記符條件碼標志含義
EQ0000Z=1相等
NE0001Z=0不相等
CS/HS0010C=1無符號數大于或等于
CC/LO0011C=0無符號數小于
MI0100N=1負數
PL0101N=0正數
VS0110V=1溢出
VC0111V=0沒有溢出
HI1000C=1,Z=0無符號數大于
LS1001C=0或Z=1無符號數小于或等于
GE1010N=V帶符號數大于或等于
LT1011N!=V帶符號數小于
GT1100Z=0,N=V帶符號數大于
LE1101Z=1或N!=V帶符號數小于或等于

???????條件碼應用舉例:
???????1、比較兩個值大小,C語言代碼如下:

if(a > b) a++; else b++;

???????對應的ARM指令代碼如下:(設R0為a,R1為b)

CMP R0, R1 ;R0與R1比較 ADDHI R0,R0,#1 ;若R0 > R1,則R0 = R0 + 1 ADDLS R1,R1,#1 ;若R0 <= R1,則R1 = R1 + 1

???????2、若兩個條件均成立,則將這兩個數值相加,C語言代碼如下:

if((a != 10)&&(b != 20)) a = a + b;

???????對應的ARM指令代碼為:

CMP R0,#10 ;比較R0是否為10 CMPNE R1,#20 ;若R0不為10,則比較R1是否為20 ADDNE R0,R0,R1 ;若R0不為10且R1不為20,則執行 R0 = R0+R1

???????3、若兩個條件有一個成立,則將這兩個數值相加,C語言代碼如下:

if((a!=10)||(b!=20)) a=a+b;

???????對應的ARM指令代碼為:

CMP R0,#10 CMPEQ R1,#20 ADDNE R0,R0,R1

指令集

Rx、Ry、Rz為寄存器,#num32為小于0xFFFF FFFF(32位)的立即數(即未溢出),ADDR為[地址表達式],Fun_lab表示函數標號,num_lab表示變量或常量標號,cond表示條件碼

數據傳送指令

處理器內數據傳送

指令名稱語法指令作用注意
MOVMOV Rx,Ry/#num32將源操作數的值賦給目的操作數
MRSMRS Rx,Rs同MOV源操作數應為特殊寄存器
MSRMSR Rs,Rx同MOV目的操作數應為特殊寄存器
MOVWMOVW Rx,#num16將源操作數賦給目的操作數的低16位高位清零
MOVTMOVT Rx,#num16將源操作數賦給目的操作數的高16位低位不變

MOV指令傳遞的立即數應在0~0xFFFF范圍內或可以通過8bit連續有效位通過移位或復制全部奇數或偶數字節能得到

存儲器訪問指令

不同數據大小的存儲器訪問

數據類型讀存儲器指令寫存儲器指令語法
32位LDRSTRLDR Rx,ADDR;將地址ADDR上的值賦給Rx
STR Rx,ADDR;將Rx的值賦給地址為ADDR的存儲空間
16位有符號LDRSH
16位無符號LDRHSTRH
8位有符號LDRSB
8位無符號LDRBSTRB
多個32位LDMSTMLDM、STM
雙字(64位)LDRDSTRDLDRD/STRD R1,R2,ADDR;從地址ADDR上讀出兩個字并分別賦給兩個寄存器
棧操作(32位)POPPUSHPUSH、POP
LDR R0, =X ;將變量X的地址賦給R0MOV R1,#0xFFFFBFFF ;R1=0xFFFFBFFFSTRH R1,[R0] ;將R1的低16位值賦給X,X=0xBFFFLDR R2,[R0] ;R2=0xBFFFLDRSH R3,[R0] ;R3=0xFFFFBFFFLDRH R4,[R0] ;R4=0xBFFFSTR R1,[R0] ;將R1的值賦給X(相當于C語言通過指針為變量賦值),X=0xFFFFBFFFLDR R2,[R0] ;R2=0xFFFFBFFFLDRSH R3,[R0] ;R3=0xFFFFBFFFLDRH R4,[R0] ;R4=0xBFFF

有符號讀和無符號讀的區別在于,同樣的數據0x83,通過LDRB讀取是0x0000 0083,通過LDRSB指令讀取是0xFFFF FF83,即無符號讀將對應8位數據進行符號位擴展

LDR等指令的操作數為立即數時,范圍為±4095

LDR不一定是指令,當使用格式為LDR 寄存器,=立即數時為偽操作,作用是將該立即數賦給寄存器,與MOV指令的區別在于,MOV指令賦的立即數有限制

存儲器訪問方式(地址表達式)(部分省略)

立即數偏移(前序)

???????數據傳輸使用的存儲器地址為:寄存器中的數值+立即數常量(偏移地址)

LDRB R0,[R1,#0x3];從地址R1+0x3中讀取一個字節并將其存入R0

加入感嘆號(!)可更新存放地址的寄存器的值(寫回):
LDRB R0,[R1,#0x3]!;從地址R1+0x3中讀取一個字節并將其存入R0后令R1=R1+0x3

可以使用寄存器R15(PC)作為寄存器,PC寄存器的值為當前指令地址

寄存器偏移

???????類似立即數偏移,但這里的寄存器可以通過移位指令進行移位:

LDR R3,[R0, R2, LSL #2];將存儲器[R0+(R2<<2)]讀入R3 LDR R3,[R0, R2];將存儲器[R0+R2]讀入R3

???????注意:這里進行的是前序偏移,也就是以地址偏移后的值為地址進行取值,下面介紹一下后序尋址:

???????后序尋址是取地址上的值,后進行地址偏移:

LDR R0, [R1], #offset;讀取存儲器[R1],然后R1被賦值為R1+偏移

后序尋址不能使用R14(SP)或R15(PC)。

多加載和多存儲

???????介紹:連續取出一個地址上連續的多個數據

LDM和STM可添加相應后綴以控制地址增長方向及地址變化方式,可添加后綴如下表所示。

可添加后綴作用等效后綴
IB地址增加后完成操作FA
IA完成操作后地址增加EA
DB地址減少后完成操作FD
DA完成操作后地址減少ED

注意,在Cortex-M4上似乎只能使用IA和DB后綴,另外兩個可能需要ARM狀態。

指令作用注意事項
LDMIA(/LDMEA)以目的操作數的值為地址,讀取多個值(數量和源操作數的數量一致)“IA/EA”后綴表示操作后地址增加
LDMDB同“LMDIA”“DB/FD”后綴代表操作后地址減小
STMIA以目的操作數的值為地址,寫入多個值(數量和源操作數的數量一致)“IA”后綴表示操作后地址增加
STMDB同“STMIA”“DB”后綴代表操作后地址減小
MOV R1,#0xFFFFAFFF STR R1,[R0] MOV R1,#0xFFFFBFFF STR R1,[R0,#4]MOV R1,#0xFFFFCFFF STR R1,[R0,#8]MOV R1,#0xFFFFDFFF STR R1,[R0,#12]LDMIA R0,{R5-R8} ;R5~R8分別是0xFFFFAFFF、B、C、DADD R0,#16LDMDB R0,{R1-R4} ;R1~R4分別是0xFFFFAFFF、B、C、D

???????注意:地址增加/減少最終并不會影響目的操作數的值,即不會“寫回”。

源操作數應為多個寄存器,格式如下:
1.以“{”為開始,“}”為結束。
2.可以使用“-”表示范圍:R2-R5表示R2、R3、R4、R5四個寄存器。
3.通過“,”將各個寄存器隔開。
注意:{R1-R4}、{R1,R2,R3,R4}、{R4,R3,R2,R1}三者等效,順序都是R1 ~ R4

加入感嘆號(!)可更新存放地址的寄存器的值(寫回):
LDMIA R0!,[R1,R3-R5];從地址R0中讀取4個字并將其分別賦給R1、R3、R4、R5四個寄存器后令R0=R0+4

壓棧和出棧

???????壓棧指令PUSH和出棧指令POP的操作數可以為多個寄存器,格式如:多寄存器格式

PUSH {R4-R6, LR} ;在子程序開始處將R4-R6和LR(鏈接寄存器)中的值入棧 POP {R4-R6, PC} ;從棧中恢復R4-R6和返回地址,返回地址存入PC以返回子程序

算術運算

指令名稱語法指令作用注意
ADDADD Rx,Ry/#num32
ADD Rx,Ry,Rz/#num32
Rx=Rx+Ry
Rx=Ry+Rz加法運算
源操作數可以為立即數,立即數限制與MOV同:限制
ADDWADD Rx,#num12
ADD Rx,Ry,#num12
同ADD源操作數至少有一個是立即數,且不超過12位。
ADC同ADDRx=Rx+Ry+CF
Rx=Ry+Rz+CF,帶進位的加法運算
在ADD的基礎上加上進位標志位的值(0/1)
SUB同ADD減法運算可添加W后綴(SUBW)
SBC同ADD帶借位的減法運算在SUB的基礎上減去借位標志位的值(0/1)
RSB同ADDRx=Ry-Rx
Rx=Rz-Ry減法反轉,結果為-SUB
MUL同ADD32位乘法
UDIV同ADD無符號除法
SDIV同ADD有符號除法

注意:許多數據處理指令會有多種形式,形式差別包括操作數數量(2 ~ 3)以及操作數種類(寄存器、立即數、存儲器),以ADD為例:
操作數數目為2:ADD Rx,Ry;Rx=Rx+Ry
操作數數目為3:ADD Rx,Ry,Rz;Rx=Ry+Rz

如果具有兩個源操作數,這不可都為立即數,且立即數不可為第一源操作數。

邏輯運算

指令名稱語法指令作用
ANDAND Rx,Ry/#num
AND Rx,Ry,Rz/#num
按位進行與運算
ORR同AND按位進行或運算
BIC同ANDRx=Rx&(~Ry)
Rx=Ry&(~Rz)進行非與操作
ORN同AND進行或非操作
EOR同AND進行異或操作
MVNAND Rx,Ry/#num進行取反操作(位非)

邏輯運算的立即數應是可以通過8bit連續有效位通過移位或復制全部奇數或偶數字節能得到的立即數。

移位

指令名稱語法指令作用注意
ASRASR Rx,Ry/#num
ASR Rx,Ry,Rz/#num
Rx=Rx<<Ry/#num
Rx=Ry<<Rz/#num
算術右移
右移指定位數,并往左側補原符號位
LSL同ASR邏輯左移左移指定位數,并往右側補0
LSR同ASR邏輯右移右移指定位數,并往左側補0
ROR同ASR循環右移右移x位=左移32-x位
RRXRRX Rx,Ry將進位標志并在最右側后進行循環移動一位

移位指令使用的立即數范圍為1 ~ 32

對于上述移位指令,更加常用的用法是,在進行數據操作時進行移位:
指令名 Rx,Ry,移位指令名 #num/Rz,如
MOV R0,Ry,LSL #2
注意:RRX作為移位指令名時,不需要立即數或寄存器作為移位位數

圖解:

數據轉換

展開

指令名稱語法指令作用
SXTBSXTB Rx,Ry將源操作數[7,0]有符號地展開
SXTH同SXTB將源操作數[15,0]有符號地展開
UXTB同SXTB將源操作數[7,0]無符號地展開
UXTH同SXTB將源操作數[15,0]無符號地展開

舉例:

MOV R0,#0xBB ;R0=0x0000 00BBSXTB R1,R0 ;R1=0xFFFF FFBBSXTH R1,R0 ;R1=0x0000 00BBUXTB R1,R0 ;R1=0x0000 00BBUXTH R1,R0 ;R1=0x0000 00BB

可在源操作數后加入{,ROR #n}進行先移位后展開,n的取值為0、8、16、24,且僅能ROR

反轉

指令名稱語法指令作用
REVREV Rx,Ry反轉字中的字節,如圖解所示
REV16同REV反轉每個半字中的字節
REVSH同REV反轉低半字中的字節并將結果有符號展開

圖解:

???????舉例:

MOV R1,#0x01MOV R0,R1,LSL #24ADD R1,#1ADD R0,R1,LSL #16ADD R1,#1ADD R0,R1,LSL #8ADD R1,#1ADD R0,R1 ;R0=0x0102 0304REV R2,R0 ;R2=0x0403 0201REV16 R3,R0 ;R3=0x0201 0403REVSH R4,R0 ;R4=0x0000 0403

位域處理

指令名稱語法指令作用
BFCBFC Rx,#num_1,#num_2將寄存器Rx中num_1到num_1+num_2-1對應的位清零,即將寄存器對應位清零,num_1為清零的最低位,num_2為清零寬度
BFIBFI Rx,Ry,#num_1,#num_2寄存器Ry中的0到num_2-1位賦給R1的num_1到num_1+num_2-1對應的位
CLZCLZ Rx,Ry將源操作數中從31位開始連續為0的個數賦給目的操作數,即計算前導零的個數
RBITRBIT Rx,Ry將源操作數按位反轉,即0和31位互換,1和30位互換…
SBFXSBFX Rx,Ry,#num_1,#num_2將寄存器Ry中的num_1到num_1+num_2-1對應的位有符號的展開并賦給Rx:舉例
UBFX同SBFX同SBFX,但將對應的位無符號展開

LDR R0, =0x5678ABCD UBFX R1,R0,#4,#8;將R0的4~11位無符號展開后賦給R1,即R1=0x0000 00BC SBFX R1,R0,#4,#8;將R0的4~11位有符號展開后賦給R1,即R1=0xFFFF FFBC

注意,這里的LDR是LDR偽指令,與LDR指令不同,=表示將后面的值賦給寄存器R0
這里LDR偽指令和MOV指令的區別是,MOV指令并不能傳遞所有的32位立即數,具體限制:MOV立即數限制。

比較和測試

指令名稱語法指令作用
CMPCMP Rx,Ry/#num計算Rx-Ry/#num,并更新APSR寄存器
CMN同CMP計算Rx+Ry/#num,并更新APSR寄存器
TST同CMP計算Rx&Ry/#num(按位與),并更新APSR寄存器的N和Z位
TEQ同CMP計算Rx⊕Ry/#num(按位異或),并更新APSR寄存器的N和Z位

這4個指令使用的立即數同樣有限制,同MOV:具體限制:MOV立即數限制。

上述計算的結果不會保存,如CMP指令,不會把Rx-Ry的差值賦給Rx

程序流控制

跳轉

???????引起跳轉操作的指令:
???????- 跳轉指令
???????- 更新R15(PC)的數據處理指令(MOV、ADD等)
???????- 寫入PC的讀存儲器指令(LDR、LDM、POP等)

指令名稱語法指令作用
BB label跳轉到標號對應的地址,屬于相對跳轉(會計算標號和當前PC的差),跳轉范圍為±2KB(可添加.W后綴使用32位版本的指令)
BXBX Rx跳轉到存放于寄存器Rx中的地址值,并基于Rx第0位設置處理器執行狀態(Cortex-M只支持Thumb狀態,因此第0位必須為1)

函數調用

指令名稱語法指令作用
BLBL label跳轉到標號位置并將返回地址保存到鏈接寄存器R14(LR)中
BLXBLX Rx跳轉到存放于寄存器Rx中的地址值并將返回地址保存到LR中,以及更新EPSR中的T位為Rx的最低位

程序計數器R15(PC)為跳轉目標地址(即將標號/地址賦給PC)
返回地址即BL/BLX指令后的指令的地址
由于Cortex-M只支持Thumb狀態,因此使用BLX指令時,Rx的第0位必須為1

函數調用和標號跳轉的區別在于,函數調用需要將返回地址保存,這也是BL和BLX與B和BX的區別

條件跳轉

???????通過指令改變標志寄存器后根據條件碼運行程序。

???????指令格式:B(cond) label/B(cond).W label

B(cond)表示指令B和條件碼cond相連,中間無空格

???????各個條件碼如條件碼助記符所示。

???????舉例:

CMP R0,#2 ;比較R0和1的值,并根據結果修改應用程序狀態寄存器APSR BEQ LOOP ;注意,BEQ是B和EQ結合,但APSR的Z位置位,即符合條件碼EQ,則跳轉到LOOP對應的位置

可用于if語句之類的分支選項

比較并跳轉

指令名稱語法指令作用
CBZCBZ Rx label當Rx為0時跳轉到標號對應的位置
CBNZ同CBZ當Rx不為0時跳轉到標號對應的位置

標號的相對偏移量應該在0x00 ~ 0x7E內

可用于循環中的條件判斷

指令不影響APSR的值

條件執行(IT指令)

???????指定下面語句執行的條件

???????語法:

IT(T/E)(T/E)(T/E) cond;(T/E)數量為0~3,決定下面指令的數量 ins_1(cond) ;若數量為0,則下面不需要寫,ins_1表示指令,這里的cond和上一行的cond相同 ins_2(cond/~cond) ;若數量為1,則需要寫到這一句(當然下面的不用寫),當第一個(T/E)為T時,這里的cond和第一行的cond相同,為E時相反 ins_3(cond/~cond) ; ins_4(cond/~cond) ;

???????舉例:

ITETT NE ADDNE R0, R0, R1 ADDEQ R0, R0, R3 ADDNE R2, R4, #1 MOVNE R5, R3

表格跳轉

指令名稱語法指令作用
TBBTBB語法及示例進行字節跳轉(偏移),偏移范圍為0 ~ 512(2*2^8)字節
TBHTBH語法及示例進行字節跳轉(偏移),偏移范圍為0 ~ 128k(2*2^16)字節

LDR R0, =1 ;偏移量TBB [PC, R0] ;TBB語法,其中PC可以替換為其它寄存器,一般用PC實現跳轉,R0為偏移量,該語句執行后,(由于處理器特性),PC=PC+4,即指向下面的語句(這里是標號Table_start) Table_start ;跳轉表起始,指向該標號后,PC=PC+R0(偏移量),即跳轉到下面的DCB語句進行賦值DCB ((Dest0-Table_start)/2);數據為8位因此使用DCB,作用:為PC賦值,進而跳轉到對應的標號。DCB ((Dest1-Table_start)/2);由于R0=1,PC會執行到此語句,之后PC=Table_start+2*((Dest1-Table_start)/2)=Dest1,進而跳轉到對應的編號DCB ((Dest2-Table_start)/2)DCB ((Dest3-Table_start)/2) Dest0LDR R1, =0B Table_end Dest1 ;即跳轉到這里執行LDR R1, =1B Table_end ;執行后跳出 Dest2LDR R1, =2B Table_end Dest3LDR R1, =3 Table_end

LDR R0, =3 ;偏移量TBH [PC, R0, LSL #1] ;同TBB,“LSL #1”不可更換 Table_startDCI ((Dest0-Table_start)/2);數據為16位因此使用DCIDCI ((Dest1-Table_start)/2)DCI ((Dest2-Table_start)/2)DCI ((Dest3-Table_start)/2) Dest0LDR R1, =0;B Table_end Dest1LDR R1, =1B Table_end Dest2 LDR R1, =2B Table_end Dest3LDR R1, =3 Table_end

上述的TBB和TBH實際上實現的是表格跳轉,使用PC時可以實現分支選擇,即c語言中的switch語句

飽和運算

指令名稱語法指令作用
SSATSSAT Rx,#num,Ry將Ry局限到-2 ^(num-1)-1 ~ 2 ^(num-1)并將該值賦給Rx
USATUSAT Rx,#num,Ry將Ry局限到0 ~ 2 ^(num-1)并將該值賦給Rx

注意,num為位數限制,因此1 <= num <= 32

Ry后可加位移運算,但僅局限于ASR與LSL

???????示例:

LDR R0,=0x00020000SSAT R1,#16,R0 ;R1=0x00007FFFSSAT R1,#17,R0 ;R1=0x00020000USAT R1,#16,R0 ;R1=0x00008000USAT R1,#17,R0 ;R1=0x00020000LDR R0,=0xFFF20000SSAT R1,#16,R0 ;R1=0xFFFF8000USAT R1,#16,R0 ;R1=0x00000000

異常相關

指令名稱語法指令作用
SVCSVC num觸發SVC中斷,可用于執行狀態的切換。num為優先級,范圍為0x00 ~ 0xFF,并且該立即數前面可不加"#"
CPSCPSIE/CPSID I/F"IE"后綴用于使能中斷,"ID"后綴用于禁止中斷

休眠模式相關

指令名稱語法指令作用
WFI(Wait for interrupt)WFI進入休眠(中斷可喚醒)
WFE(Wait for event)WFE進入休眠,等待事件(中斷、復位、外部輸入等)發生后喚醒
SEVSEV發送事件

存儲器屏障

指令名稱語法指令作用
DMBDMB數據存儲器屏障。確保在執行新的存儲器訪問前所有的存儲器訪問都已經完成
DSBDSB數據同步屏障。確保在下一條指令執行前所有的存儲器訪問都已經完成
ISBISB指令同步屏障。清空流水線,確保在執行新的指令前,之前所有的指令都已完成

???????應用場景:


其它指令

指令名稱語法指令作用
NOPNOP空語句,無任何功能,可用于指令對齊或延時
BKPTBKPT numnum立即數,且此時其前面可不加"#",大小為0x00 ~ 0xFF。該指令的作用是實現軟件斷點,特殊的num值會使處理器執行某些動作

本文基于keil5,芯片STM32F429IGx撰寫,參考書籍:《ARM Cortex-M3與Cortex-M4權威指南》

總結

以上是生活随笔為你收集整理的汇编语言笔记-ARM架构指令集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。