S3C2440 汇编指令
?arm匯編指令集
算術(shù)和邏輯指令
adc?:?帶進(jìn)位的加法
(addition?with?carry)
adc{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?+?op_2?+?carryadc?將把兩個操作數(shù)加起來,并把結(jié)果放置到目的寄存器中。它使用一個進(jìn)位標(biāo)志位,這樣就可以做比?32?位大的加法。下列例子將加兩個?128?位的數(shù)。
128?位結(jié)果:?寄存器?0、1、2、和?3
第一個?128?位數(shù):?寄存器?4、5、6、和?7
第二個?128?位數(shù):?寄存器?8、9、10、和?11。
adds????r0,?r4,?r8??????????????;?加低端的字
??adcs????r1,?r5,?r9??????????????;?加下一個字,帶進(jìn)位
??adcs????r2,?r6,?r10?????????????;?加第三個字,帶進(jìn)位
??adcs????r3,?r7,?r11?????????????;?加高端的字,帶進(jìn)位如果如果要做這樣的加法,不要忘記設(shè)置?s?后綴來更改進(jìn)位標(biāo)志。
add?:?加法
(addition)
add{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?+?op_2add?將把兩個操作數(shù)加起來,把結(jié)果放置到目的寄存器中。操作數(shù)?1?是一個寄存器,操作數(shù)?2?可以是一個寄存器,被移位的寄存器,或一個立即值:
add?????r0,?r1,?r2??????????????;?r0?=?r1?+?r2
??add?????r0,?r1,?#256????????????;?r0?=?r1?+?256
??add?????r0,?r2,?r3,lsl#1????????;?r0?=?r2?+?(r3?<<?1)加法可以在有符號和無符號數(shù)上進(jìn)行。
and?:?邏輯與
(logical?and)
and{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?and?op_2and?將在兩個操作數(shù)上進(jìn)行邏輯與,把結(jié)果放置到目的寄存器中;對屏蔽你要在上面工作的位很有用。?操作數(shù)?1?是一個寄存器,操作數(shù)?2?可以是一個寄存器,被移位的寄存器,或一個立即值:
and?????r0,?r0,?#3??????????????;?r0?=?保持?r0?的位?0?和?1,丟棄其余的位。and?的真值表(二者都是?1?則結(jié)果為?1):
op_1???op_2???結(jié)果
??0??????0??????0
??0??????1??????0
??1??????0??????0
??1??????1??????1
bic?:?位清除
(bit?clear)
bic{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?and?(!op_2)bic?是在一個字中清除位的一種方法,與?or?位設(shè)置是相反的操作。操作數(shù)?2?是一個?32?位位掩碼(mask)。如果如果在掩碼中設(shè)置了某一位,則清除這一位。未設(shè)置的掩碼位指示此位保持不變。
bic?????r0,?r0,?#%1011??????????;?清除?r0?中的位?0、1、和?3。保持其余的不變。bic?真值表?:
op_1???op_2???結(jié)果
??0??????0??????0
??0??????1??????0
??1??????0??????1
??1??????1??????0譯注:邏輯表達(dá)式為?op_1?and?not?op_2
eor?:?邏輯異或
(logical?exclusive?or)
eor{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?eor?op_2eor?將在兩個操作數(shù)上進(jìn)行邏輯異或,把結(jié)果放置到目的寄存器中;對反轉(zhuǎn)特定的位有用。操作數(shù)?1?是一個寄存器,操作數(shù)?2?可以是一個寄存器,被移位的寄存器,或一個立即值:
eor?????r0,?r0,?#3??????????????;?反轉(zhuǎn)?r0?中的位?0?和?1eor?真值表(二者不同則結(jié)果為?1):
op_1???op_2???結(jié)果
??0??????0??????0
??0??????1??????1
??1??????0??????1
??1??????1??????0
mov?:?傳送
(move)
mov{條件}{s}??<dest>,?<op?1>
????????????????dest?=?op_1mov?從另一個寄存器、被移位的寄存器、或一個立即值裝載一個值到目的寄存器。你可以指定相同的寄存器來實(shí)現(xiàn)?nop?指令的效果,你還可以專門移位一個寄存器:
mov?????r0,?r0??????????????????;?r0?=?r0...?nop?指令
??mov?????r0,?r0,?lsl#3???????????;?r0?=?r0?*?8如果?r15?是目的寄存器,將修改程序計(jì)數(shù)器或標(biāo)志。這用于返回到調(diào)用代碼,方法是把連接寄存器的內(nèi)容傳送到?r15:
mov?????pc,?r14?????????????????;?退出到調(diào)用者
??movs????pc,?r14?????????????????;?退出到調(diào)用者并恢復(fù)標(biāo)志位
????????????????????????????????????(不遵從?32-bit?體系)
mvn?:?傳送取反的值
(move?negative)
mvn{條件}{s}??<dest>,?<op?1>
????????????????dest?=?!op_1mvn?從另一個寄存器、被移位的寄存器、或一個立即值裝載一個值到目的寄存器。不同之處是在傳送之前位被反轉(zhuǎn)了,所以把一個被取反的值傳送到一個寄存器中。這是邏輯非操作而不是算術(shù)操作,這個取反的值加?1?才是它的取負(fù)的值:
mvn?????r0,?#4??????????????????;?r0?=?-5
??mvn?????r0,?#0??????????????????;?r0?=?-1
orr?:?邏輯或
(logical?or)
orr{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?or?op_2or?將在兩個操作數(shù)上進(jìn)行邏輯或,把結(jié)果放置到目的寄存器中;對設(shè)置特定的位有用。操作數(shù)?1?是一個寄存器,操作數(shù)?2?可以是一個寄存器,被移位的寄存器,或一個立即值:
orr?????r0,?r0,?#3??????????????;?設(shè)置?r0?中位?0?和?1or?真值表(二者中存在?1?則結(jié)果為?1):
op_1???op_2???結(jié)果
??0??????0??????0
??0??????1??????1
??1??????0??????1
??1??????1??????1
rsb?:?反向減法
(reverse?subtraction)
rsb{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_2?-?op_1sub?用操作數(shù)?two?減去操作數(shù)?one,把結(jié)果放置到目的寄存器中。操作數(shù)?1?是一個寄存器,操作數(shù)?2?可以是一個寄存器,被移位的寄存器,或一個立即值:
rsb?????r0,?r1,?r2??????????????;?r0?=?r2?-?r1
??rsb?????r0,?r1,?#256????????????;?r0?=?256?-?r1
??rsb?????r0,?r2,?r3,lsl#1????????;?r0?=?(r3?<<?1)?-?r2反向減法可以在有符號或無符號數(shù)上進(jìn)行。
rsc?:?帶借位的反向減法
(reverse?subtraction?with?carry)
rsc{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_2?-?op_1?-?!carry同于?sbc,但倒換了兩個操作數(shù)的前后位置。
sbc?:?帶借位的減法
(subtraction?with?carry)
sbc{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?-?op_2?-?!carrysbc?做兩個操作數(shù)的減法,把結(jié)果放置到目的寄存器中。它使用進(jìn)位標(biāo)志來表示借位,這樣就可以做大于?32?位的減法。sub?和?sbc?生成進(jìn)位標(biāo)志的方式不同于常規(guī),如果需要借位則清除進(jìn)位標(biāo)志。所以,指令要對進(jìn)位標(biāo)志進(jìn)行一個非操作?-?在指令執(zhí)行期間自動的反轉(zhuǎn)此位。
sub?:?減法
(subtraction)
sub{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?-?op_2sub?用操作數(shù)?one?減去操作數(shù)?two,把結(jié)果放置到目的寄存器中。操作數(shù)?1?是一個寄存器,操作數(shù)?2?可以是一個寄存器,被移位的寄存器,或一個立即值:
sub?????r0,?r1,?r2??????????????;?r0?=?r1?-?r2
??sub?????r0,?r1,?#256????????????;?r0?=?r1?-?256
??sub?????r0,?r2,?r3,lsl#1????????;?r0?=?r2?-?(r3?<<?1)減法可以在有符號和無符號數(shù)上進(jìn)行。
移位指令
???????arm?處理器組建了可以與數(shù)據(jù)處理指令(adc、add、and、bic、cmn、cmp、eor、mov、mvn、orr、rsb、sbc、sub、teq、tst)一起使用的桶式移位器(barrel?shifter)。你還可以使用桶式移位器影響在?ldr/str?操作中的變址值。
譯注:移位操作在?arm?指令集中不作為單獨(dú)的指令使用,它是指令格式中是一個字段,在匯編語言中表示為指令中的選項(xiàng)。如果數(shù)據(jù)處理指令的第二個操作數(shù)或者單一數(shù)據(jù)傳送指令中的變址是寄存器,則可以對它進(jìn)行各種移位操作。如果數(shù)據(jù)處理指令的第二個操作數(shù)是立即值,在指令中用?8?位立即值和?4?位循環(huán)移位來表示它,所以對大于?255?的立即值,匯編器嘗試通過在指令中設(shè)置循環(huán)移位數(shù)量來表示它,如果不能表示則生成一個錯誤。在邏輯類指令中,邏輯運(yùn)算指令由指令中?s?位的設(shè)置或清除來確定是否影響進(jìn)位標(biāo)志,而比較指令的?s?位總是設(shè)置的。在單一數(shù)據(jù)傳送指令中指定移位的數(shù)量只能用立即值而不能用寄存器。
下面是給不同的移位類型的六個助記符:
lsl??邏輯左移
??asl??算術(shù)左移
??lsr??邏輯右移
??asr??算術(shù)右移
??ror??循環(huán)右移
??rrx??帶擴(kuò)展的循環(huán)右移asl?和?lsl?是等同的,可以自由互換。
你可以用一個立即值(從?0?到?31)指定移位數(shù)量,或用包含在?0?和?31?之間的一個值的寄存器指定移位數(shù)量。
邏輯或算術(shù)左移
(logical?or?arithmetic?shift?left)
rx,?lsl?#n????or
??rx,?asl?#n????or
??rx,?lsl?rn????or
??rx,?asl?rn接受?rx?的內(nèi)容并按用‘n’或在寄存器?rn?中指定的數(shù)量向高有效位方向移位。最低有效位用零來填充。除了概念上的第?33?位(就是被移出的最小的那位)之外丟棄移出最左端的高位,如果邏輯類指令中?s?位被設(shè)置了,則此位將成為從桶式移位器退出時進(jìn)位標(biāo)志的值。
考慮下列:
mov????r1,?#12
??mov????r0,?r1,?lsl#2在退出時,r0?是?48。?這些指令形成的總和是?r0?=?#12,?lsl#2?等同于?basic?的?r0?=?12?<<?2
邏輯右移
(logical?shift?right)
rx,?lsr?#n????or
??rx,?lsr?rn它在概念上與左移相對。把所有位向更低有效位方向移動。如果邏輯類指令中?s?位被設(shè)置了,則把最后被移出最右端的那位放置到進(jìn)位標(biāo)志中。它同于?basic?的?register?=?value?>>>?shift。
算術(shù)右移
(arithmetic?shift?right)
rx,?asr?#n????or
??rx,?asr?rn類似于?lsr,但使用要被移位的寄存器(rx)的第?31?位的值來填充高位,用來保護(hù)補(bǔ)碼表示中的符號。如果邏輯類指令中?s?位被設(shè)置了,則把最后被移出最右端的那位放置到進(jìn)位標(biāo)志中。它同于?basic?的?register?=?value?>>?shift。
循環(huán)右移
(rotate?right)
rx,?ror?#n????or
??rx,?ror?rn循環(huán)右移類似于邏輯右移,但是把從右側(cè)移出去的位放置到左側(cè),如果邏輯類指令中?s?位被設(shè)置了,則同時放置到進(jìn)位標(biāo)志中,這就是位的‘循環(huán)’。一個移位量為?32?的操作將導(dǎo)致輸出與輸入完全一致,因?yàn)樗形欢急灰莆涣?32?個位置,又回到了開始時的位置!
帶擴(kuò)展的循環(huán)右移
(rotate?right?with?extend)
rx,?rrx這是一個?ror#0?操作,它向右移動一個位置?-?不同之處是,它使用處理器的進(jìn)位標(biāo)志來提供一個要被移位的?33?位的數(shù)量。
乘法指令??
指令格式
這兩個指令與普通算術(shù)指令在對操作數(shù)的限制上有所不同:
給出的所有操作數(shù)、和目的寄存器必須為簡單的寄存器。?
你不能對操作數(shù)?2?使用立即值或被移位的寄存器。?
目的寄存器和操作數(shù)?1?必須是不同的寄存器。?
最后,你不能指定?r15?為目的寄存器。?
mla?:?帶累加的乘法
(multiplication?with?accumulate)
mla{條件}{s}??<dest>,?<op?1>,?<op?2>,?<op?3>
????????????????dest?=?(op_1?*?op_2)?+?op_3mla?的行為同于?mul,但它把操作數(shù)?3?的值加到結(jié)果上。這在求總和時有用。
mul?:?乘法
(multiplication)
mul{條件}{s}??<dest>,?<op?1>,?<op?2>
????????????????dest?=?op_1?*?op_2mul?提供?32?位整數(shù)乘法。如果操作數(shù)是有符號的,可以假定結(jié)果也是有符號的。
比較指令??
指令格式
譯注:cmp?和?cmp?是算術(shù)指令,teq?和?tst?是邏輯指令。把它們歸入一類的原因是它們的?s?位總是設(shè)置的,就是說,它們總是影響標(biāo)志位。
cmn?:?比較取負(fù)的值
(compare?negative)
cmn{條件}{p}??<op?1>,?<op?2>
????????????????status?=?op_1?-?(-?op_2)cmn?同于?cmp,但它允許你與小負(fù)值(操作數(shù)?2?的取負(fù)的值)進(jìn)行比較,比如難于用其他方法實(shí)現(xiàn)的用于結(jié)束列表的?-1。這樣與?-1?比較將使用:
cmn?????r0,?#1??????????????????;?把?r0?與?-1?進(jìn)行比較詳情參照?cmp?指令。
cmp?:?比較
(compare)
cmp{條件}{p}??<op?1>,?<op?2>
????????????????status?=?op_1?-?op_2cmp?允許把一個寄存器的內(nèi)容如另一個寄存器的內(nèi)容或立即值進(jìn)行比較,更改狀態(tài)標(biāo)志來允許進(jìn)行條件執(zhí)行。它進(jìn)行一次減法,但不存儲結(jié)果,而是正確的更改標(biāo)志。標(biāo)志表示的是操作數(shù)?1?比操作數(shù)?2?如何(大小等)。如果操作數(shù)?1?大于操作操作數(shù)?2,則此后的有?gt?后綴的指令將可以執(zhí)行。
明顯的,你不需要顯式的指定?s?后綴來更改狀態(tài)標(biāo)志...?如果你指定了它則被忽略。
teq?:?測試等價
(test?equivalence)
teq{條件}{p}??<op?1>,?<op?2>
????????????????status?=?op_1?eor?op_2teq?類似于?tst。區(qū)別是這里的概念上的計(jì)算是?eor?而不是?and。這提供了一種查看兩個操作數(shù)是否相同而又不影響進(jìn)位標(biāo)志(不象?cmp?那樣)的方法。加上?p?后綴的?teq?還可用于改變?r15?中的標(biāo)志(在?26-bit?模式中)。詳情請參照?psr.html,在?32-bit?模式下如何做請參見這里。
tst?:?測試位
(test?bits)
tst{條件}{p}??<op?1>,?<op?2>
????????????????status?=?op_1?and?op_2tst?類似于?cmp,不產(chǎn)生放置到目的寄存器中的結(jié)果。而是在給出的兩個操作數(shù)上進(jìn)行操作并把結(jié)果反映到狀態(tài)標(biāo)志上。使用?tst?來檢查是否設(shè)置了特定的位。操作數(shù)?1?是要測試的數(shù)據(jù)字而操作數(shù)?2?是一個位掩碼。經(jīng)過測試后,如果匹配則設(shè)置?zero?標(biāo)志,否則清除它。象?cmp?那樣,你不需要指定?s?后綴。
tst?????r0,?#%1?????????????????;?測試在?r0?中是否設(shè)置了位?0。?分支指令b?:?分支
(branch)b{條件}??<地址>b?是最簡單的分支。一旦遇到一個?b?指令,arm?處理器將立即跳轉(zhuǎn)到給定的地址,從那里繼續(xù)執(zhí)行。注意存儲在分支指令中的實(shí)際的值是相對當(dāng)前的?r15?的值的一個偏移量;而不是一個絕對地址。它的值由匯編器來計(jì)算,它是?24?位有符號數(shù),左移兩位后有符號擴(kuò)展為?32?位,表示的有效偏移為?26?位(+/-?32?m)。在其他處理器上,你可能經(jīng)常見到這樣的指令:opt?1
??lda?&70
??cmp?#0
??beq?zero
??sta?&72
?.zero?rts(取自?acorn?electron?user?guide?issue?1?page?213)在?arm?處理器上,它們將變成下面這些東西:opt?????1
??adr?????r1,?#&70
??ldr?????r0,?[r1]
??cmp?????#0
??beq?????zero
??str?????r0,?[r1,?#2]
?.zero
??mov?????pc,?r14這不是一個很好的例子,但你可以構(gòu)想如何更好的去條件執(zhí)行而不是分支。另一方面,如果你有大段的代碼或者你的代碼使用狀態(tài)標(biāo)志,那么你可以使用條件執(zhí)行來實(shí)現(xiàn)各類分支:?這樣一個單一的簡單條件執(zhí)行指令可以替代在其他處理器中存在的所有這些分支和跳轉(zhuǎn)指令。opt?????1
??adr?????r1,?#&70
??ldr?????r0,?[r1]
??cmp?????r0,?#0
??strne???r0,?[r1,?#2]
??mov?????pc,?r14bl?:?帶連接的分支
(branch?with?link)bl{條件}??<地址>bl?是另一個分支指令。就在分支之前,在寄存器?14?中裝載上?r15?的內(nèi)容。你可以重新裝載?r14?到?r15?中來返回到在這個分支之后的那個指令,它是子例程的一個基本但強(qiáng)力的實(shí)現(xiàn)。它的作用在屏幕裝載器?2?(例子?4)中得以很好的展現(xiàn)....load_new_format
??????bl?????switch_screen_mode
??????bl?????get_screen_info
??????bl?????load_palette
????.new_loop
??????mov????r1,?r5
??????bl?????read_byte
??????cmp????r0,?#255
??????bleq???read_loop
??????strb???r0,?[r2,?#1]!...在這里我們見到在裝載器循環(huán)之前調(diào)用了三個子例程。接著,一旦滿足了條件執(zhí)行就在循環(huán)中調(diào)用了?read_byte?子例程。條件執(zhí)行?? ?arm?處理器的一個非常特殊的特征是它的條件執(zhí)行。我們指的不是基本的如果進(jìn)位則分支,arm?使這個邏輯階段進(jìn)一步深化為如果進(jìn)位則?xxx?-?這里的?xxx?是任何東西。為了舉例,下面是?intel?8086?處理器分支指令的一個列表:ja????jump?if?above
??jae???jump?if?above?or?equal
??jb????jump?if?below
??jbe???jump?if?below?or?equal
??jc????jump?if?carry
??jcxz??jump?if?cx?zero?(cx?is?a?register?that?can?be?used?for?loop?counts)
??je????jump?if?equal
??jg????jump?if?greater?than
??jge???jump?if?greater?than?or?equal
??jl????jump?if?less?than
??jle???jump?if?less?than?or?equal
??jmp???jump
??jna???jump?if?not?above
??jnae??jump?if?not?above?or?equal
??jnb???jump?if?not?below
??jnbe??jump?if?not?below?or?equal
??jnc???jump?if?no?carry
??jne???jump?if?not?equal
??jng???jump?if?not?greater?than
??jnge??jump?if?not?greater?than?or?equal
??jnl???jump?if?not?less?than
??jnle??jump?if?not?less?than?or?equal
??jno???jump?if?not?overflow
??jnp???jump?if?not?parity
??jns???jump?if?not?sign
??jnz???jump?if?not?zero
??jo????jump?if?overflow
??jp????jump?if?parity
??jpe???jump?if?parity?even
??jpo???jump?if?parity?odd
??js????jump?if?sign
??jz????jump?if?zero
80386?添加了:
??jecxz?jump?if?ecx?zero
作為對比,arm?處理器只提供了:
b?????分支
??bl????帶連接的分支
但?arm?提供了條件執(zhí)行,你可以不受這個表面上不靈活的方式的限制:
beq???branch?if?equal
??bne???branch?if?not?equal
??bvs???branch?if?overflow?set
??bvc???branch?if?overflow?clear
??bhi???branch?if?higher
??bls???branch?if?lower?or?the?same
??bpl???branch?if?plus
??bmi???branch?if?minus
??bcs???branch?if?carry?set
??bcc???branch?if?carry?clear
??bge???branch?if?greater?than?or?equal
??bgt???branch?if?greater?than
??ble???branch?if?less?than?or?equal
??blt???branch?if?less?than
??bleq??branch?with?link?if?equal
??....
??bllt??branch?with?link?if?less?than
還有兩個代碼,
????al?-?always,缺省條件所以不須指定
????nv?-?never,不是非常有用。你無論如何不要使用這個代碼...
當(dāng)你發(fā)現(xiàn)所有?bxx?指令實(shí)際上是同一個指令的時候,緊要關(guān)頭就到了。接著你會想,如果你可以在一個分支指令上加上所有這些條件,那么對一個寄存器裝載指令能否加上它們??答案是可以。?下面是可獲得的條件代碼的列表:eq?:?等于?如果一次比較之后設(shè)置了?z?標(biāo)志。? ?ne?:?不等于?如果一次比較之后清除了?z?標(biāo)志。? ?vs?:?溢出設(shè)置?如果在一次算術(shù)操作之后設(shè)置了?v?標(biāo)志,計(jì)算的結(jié)果不適合放入一個?32bit?目標(biāo)寄存器中。? ?vc?:?溢出清除?如果清除了?v?標(biāo)志,與?vs?相反。? ?hi?:?高于(無符號)?如果一次比較之后設(shè)置了?c?標(biāo)志并清除了?z?標(biāo)志。? ?ls?:?低于或同于(無符號)?如果一次比較操作之后清除了?c?標(biāo)志或設(shè)置了?z?標(biāo)志。? ?pl?:?正號?如果一次算術(shù)操作之后清除了?n。出于定義‘正號’的目的,零是正數(shù)的原因是它不是負(fù)數(shù)...? ?mi?:?負(fù)號?如果一次算術(shù)操作之后設(shè)置了?n?標(biāo)志。? ?cs?:?進(jìn)位設(shè)置?如果一次算術(shù)操作或移位操作之后設(shè)置了?c?標(biāo)志,操作的結(jié)果不能表示為?32bit。你可以把?c?標(biāo)志當(dāng)作結(jié)果的第?33?位。? ?cc?:?進(jìn)位清除?與?cs?相反。? ?ge?:?大于或等于(有符號)?如果一次比較之后...設(shè)置了?n?標(biāo)志并設(shè)置了?v?標(biāo)志或者...清除了?n?標(biāo)志并清除了?v?標(biāo)志。? ?gt?:?大于(有符號)?如果一次比較之后...設(shè)置了?n?標(biāo)志并設(shè)置了?v?標(biāo)志或者...清除了?n?標(biāo)志并清除了?v?標(biāo)志并且...清除了?z?標(biāo)志。? ?le?:?小于或等于(有符號)?如果一次比較之后...設(shè)置了?n?標(biāo)志并清除了?v?標(biāo)志或者...清除了?n?標(biāo)志并設(shè)置了?v?標(biāo)志并且...設(shè)置了?z?標(biāo)志。? ?lt?:?小于(有符號)?如果一次比較之后...設(shè)置了?n?標(biāo)志并清除了?v?標(biāo)志。或者...清除了?n?標(biāo)志并設(shè)置了?v?標(biāo)志。? ?al?:?總是?缺省條件,所以不用明顯聲明。? ?nv?:?從不?不是特別有用,它表示應(yīng)當(dāng)永遠(yuǎn)不執(zhí)行這個指令。是窮人的?nop。包含?nv?是為了完整性(與?al?相對),你不應(yīng)該在你的代碼中使用它。?有一個在最后的條件代碼?s,它以相反的方式工作。當(dāng)用于一個指令的時候,導(dǎo)致更改狀態(tài)標(biāo)志。這不是自動發(fā)生的?-?除非這些指令的目的是設(shè)置狀態(tài)。例如:?add?????r0,?r0,?r1
??adds????r0,?r0,?r1
??addeqs??r0,?r0,?r1
第一個例子是一個基本的加法(把?r1?的值增加到?r0),它不影響狀態(tài)寄存器。
第二個例子是同一個加法,只不過它導(dǎo)致更改狀態(tài)寄存器。
最后一個例子是同一個加法,更改狀態(tài)寄存器。不同在于它是一個有條件的指令。只有前一個操作的結(jié)果是?eq?(如果設(shè)置了?z?標(biāo)志)的時候它才執(zhí)行。
下面是條件執(zhí)行的一個工作中的例子。你把寄存器?0?與存儲在寄存器?10?中內(nèi)容相比較。
如果不等于?r10,則調(diào)用一個軟件中斷,增加它并分支回來再次做這些。否則清除?r10?并返回到調(diào)用它的那部分代碼(它的地址存儲在?r14)。
\?條件執(zhí)行的一個例子
??.loop???????????????????????????;?標(biāo)記循環(huán)開始位置
??cmp?????r0,?r10?????????????????;?把?r0?與?r10?相比較
??swine???&40017??????????????????;?不等于:?調(diào)用?swi?&40017
??addne???r0,?r0,?#1??????????????;?????????向?r0?加?1
??bne?????loop????????????????????;?????????分支到?'loop'
??mov?????r10,?#0?????????????????;?等于??:?設(shè)置?r10?為零
??ldmfd???r13!,?{r0-r12,pc}???????;?????????返回到調(diào)用者
注解:
????swi?編號就象我寫的這樣。在?risc?os?下,它是給?econet_doimmediate?的編號。不要字面的接受它,這只是一個例子!
????你可能以前沒見過?ldmfd,它從棧中裝載多個寄存器。在這個例子中,我們從一個完全正式的棧中裝載?r0?至?r12?和?r14。關(guān)于寄存器裝載和存儲的更多信息請參閱?str.html。
????我說要裝載?r14。那么為什么要把它放入?pc?中??原因是此時?r14?存儲的值包含返回地址。我們也可以采用:
????ldmfd??????r13!,?{r0-r12,r14}
????mov????????pc,?r14
????但是直接恢復(fù)到?pc?中可以省略這個?mov?語句。
????最后,這些寄存器很有可能被一個?swi?調(diào)用所占用(依賴于在調(diào)用期間執(zhí)行的代碼),所以你最好把你的重要的寄存器壓入棧中,以后在恢復(fù)它們。
swi?指令??
?
swi?:?軟件中斷
(software?interrupt)
swi{條件}??<24?位編號>
指令格式
這是一個簡單的設(shè)施,但可能是最常用的。多數(shù)操作系統(tǒng)設(shè)施是用?swi?提供的。沒有?swi?的?risc?os?是不可想象的。
nava?whiteford?解釋了?swi?是如何工作的(最初在?frobnicate?issue?12?)...
swi?是什么?
swi?表示?software?interrupt。在?risc?os??中使用?swi?來訪問操作系統(tǒng)例程或第三方生產(chǎn)的模塊。許多應(yīng)用使用模塊來給其他應(yīng)用提供低層外部訪問。
swi?的例子有:
????文件器?swi,它輔助讀寫磁盤、設(shè)置屬性等。
????打印機(jī)驅(qū)動器?swi,用來輔助使用打印并行端口。
????freenet/acorn?tcp/ip?協(xié)議棧?swi,用?tcp/ip?協(xié)議在?internet?上發(fā)送和接收數(shù)據(jù)。
在以這種方式使用的時候,swi?允許操作系統(tǒng)擁有一個模塊結(jié)構(gòu),這意味著用來建立完整的操作系統(tǒng)的所需的代碼可以被分割成許多小的部分(模塊)和一個模塊處理程序(handler)。
當(dāng)?swi?處理程序得到對特定的例程編號的一個請求的時候,它找到這個例程的位置并執(zhí)行它,并傳遞(有關(guān)的)任何數(shù)據(jù)。
它是如何工作的?
首先查看一下如何使用它。一個?swi?指令(匯編語言)看起來如下:
swi?&02
或
swi?"os_write0"
這些指令實(shí)際上是相同的,將被匯編成相同的指令。唯一的不同是第二個指令使用一個字符串來表示?swi?編號?&02。在使用采用了字符串編號的程序的時候,在執(zhí)行之前首先查找這個字符串。?在這里我們不想處理字符串,因?yàn)樗荒芙o出它要進(jìn)行什么的一個真實(shí)表示。它們通常用于增進(jìn)一個程序的清晰程度,但不是實(shí)際執(zhí)行的指令。讓我們再次看一下第一個指令:swi?&02
這是什么意思??字面的意思是進(jìn)入?swi?處理程序并傳遞值?&02。在?risc?os?中這意味著執(zhí)行編號是?&02?的例程。
它是如何這么作的??它如何傳遞?swi?編號和進(jìn)入?swi?處理程序?
如果你查看內(nèi)存的開始?32?字節(jié)(位于?0-&1c)并反匯編它們(查開實(shí)際的?arm?指令)你將見到如下:
地址???????內(nèi)容???????????????反匯編
00000000?:?0..??:?e5000030?:?str?????r0,[r0,#-48]
00000004?:?.ó???:?e59ff31c?:?ldr?????pc,&00000328
00000008?:?.ó???:?e59ff31c?:?ldr?????pc,&0000032c
0000000c?:?.ó???:?e59ff31c?:?ldr?????pc,&00000330
00000010?:?.ó???:?e59ff31c?:?ldr?????pc,&00000334
00000014?:?.ó???:?e59ff31c?:?ldr?????pc,&00000338
00000018?:?.ó???:?e59ff31c?:?ldr?????pc,&0000033c
0000001c?:??2???:?e3a0a632?:?mov?????r10,#&3200000
讓我們仔細(xì)看一下。
除了第一個和最后一個指令之外(它們是特殊情況)你見到的都是把一個新值裝載到?pc?(程序計(jì)數(shù)器)的指令,它們告訴計(jì)算機(jī)到哪里去執(zhí)行下一個指令。
還展示了這個值是從內(nèi)存中的一個地址接受來的。(你可以在?!zap?主菜單上使用“read?memory”選項(xiàng)去自己查看一下。)
這看起來好象與?swi?沒多少關(guān)系,下面做進(jìn)一步的說明。
一個?swi?所做的一切就是把模式改變成超級用戶并設(shè)置?pc?來執(zhí)行在地址?&08?處的下一個指令!
把處理器轉(zhuǎn)換到超級用戶模式會切換掉兩個寄存器?r13?和?r14?并用?r13_svc?和?r14_svc?替換它們。
在進(jìn)入超級用戶模式的時候,還把?r14_svc?設(shè)置為在這個?swi?指令之后的地址。
這個實(shí)際上就象一個連接到地址?&08?的分支指令(bl?&08),但帶有用于一些數(shù)據(jù)(swi?編號)的空間。
象我說過的那樣,地址?&08?包含跳轉(zhuǎn)到另一個地址的一個指令,就是實(shí)際的?swi?程序的地址!
此時你可能會想“稍等一會!?還有?swi?編號呢?”。實(shí)際上處理器忽略這個值本身。swi?處理程序使用傳遞來的?r14_svc?的值來獲取它。
下面是完成它的步驟(在存儲寄存器?r0-r12?之后):
????它從?r14?中減去?4?來獲得?swi?指令的地址。
????把這個指令裝載到一個寄存器。
????清除這個指令的高端?8?位,去掉了?opcode?而只剩下的?swi?編號。
????使用這個值來找到要被執(zhí)行的代碼的例程的地址(使用查找表等)。
????恢復(fù)寄存器?r0-r12。
????使處理器離開超級用戶模式。
????跳轉(zhuǎn)到這個例程的地址。
容易吧!?;)
下面是一個例子,來自?arm610?datasheet:
0x08?b?supervisor
entrytable
?dcd?zerortn
?dcd?readcrtn
?dcd?writeirtn
?...
zero???equ?0
readc??equ?256
writei?equ?512
?
;?swi?包含需要的例程在位?8-23?中和數(shù)據(jù)(如果有的話)在位?0-7?中。
;?假定?r13_svc?指向了一個合適的棧
stmfd?r13,?{r0-r2?,?r14}
?;?保存工作寄存器和返回地址。
ldr?r0,[r14,#-4]
?;?得到?swi?指令。
bic?r0,r0,?#0xff000000
?;?清除高端的?8?位。
mov?r1,?r0,?lsr?#8
?;?得到例程偏移量。
adr?r2,?entrytable
?;?得到入口表(entrytable)的開始地址。
ldr?r15,[r2,r1,lsl?#2]
?;?分支到正確的例程
writeirtn
?;?寫?r0?中的位?0?-?7?中的字符。
.............
?ldmfd?r13,?{r0-r2?,?r15}^
?;?恢復(fù)工作空間,并返回、恢復(fù)處理器模式和標(biāo)志。
這就是?swi?指令的基本處理步驟。
總結(jié)
以上是生活随笔為你收集整理的S3C2440 汇编指令的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米9买6+128还是8+128(小米官
- 下一篇: S3C2440中断跳转分析