时光荏苒,马小菜来到武当已经一月有余了,他每天的任务只是打柴挑水、烧火做饭等,和武艺修习几乎没有半点联系。当时被大师兄指派到厨房做事的时候,大师兄说了几句马小菜不太懂的话“天将降大任于斯人也,必先苦其心志,劳其筋骨。。。”,可怜马小菜目不识丁,未明白其中深理。不过还是天天埋头苦干,任劳任怨。
厨房的掌勺大厨是一位和蔼可亲的大叔,听闻师兄们说这位大叔姓丁,单名一个克字。经常被人“庖丁—庖丁”的叫,于是厨房的那一帮新人都以“庖大叔”相称。庖大叔的绝活是厨房工作做得非常出色,不但菜炒得好吃,切菜炒菜的速度更是一流,并且每一个动作都有相应的说辞。比如拿切菜为例,切片时“凌空飞渡”,只见一道道白光左右纷飞过后,萝卜已经成了透光的薄片了;切丝时则是“万马奔腾”,只闻得一阵阵“啲哆啲哆”的刀与砧板的接触声过后,莴笋就由片变丝了。
一天,马小菜因为不明白大师兄当初说的话的意思,就去请教庖大叔,结果被庖大叔白了一眼,问道:“你是否没念过书?”,马小菜点点头。庖大叔大笑一声,“哈哈,那我来当先生教你念书吧”。然后低声嘀咕道“嘿嘿,我这种大老粗也可以当先生了。。。”,马小菜当然愿意跟着他学习了,终归是好事一件嘛。从此马小菜晚上要比别人晚睡三小时,跟着庖大叔识字,学之乎则也。对于学习,马小菜总是干劲十足。
后面,庖大叔也传了马小菜最基本的内功心法--ARM心法,由于比较笨拙,短短数百字,读了三天才算勉强能背。然后每天没事的时候都会默念该心法,打柴时、挑水时,连做梦时都在背诵心法,后来则是横竖倒背入流ARM内功心法了。
终于,马小菜在干过一年苦力之后,正式开始了他的梦幻学武之旅。
最开始学的乃是武当心法—太一心法。一日,马小菜被大师兄叫到太一室,由掌门亲自传授,掌门云虚道长注视马小菜很久后,然后微笑的点点头。而后掌门开始发话了:“马小菜,为师今日传你我武当的玄功心法--太一心法。”,马小菜立刻跪谢师父并拿出纸笔来帮助记忆,他并没有超强的记忆力。师父继续道:“该心法共有九法,分别是:一灵独觉法、泯外守中法、冥心守一法、系心守窍法、心息相依法、息心止念法、息妄全真法、返还先天法、无我太一法,……”
===================================================================================
寻址方式是根据指令中给出的地址码字段来实现寻找真实操作数地址的方式, ARM处理器共有9中寻址方式:
1.寄存器寻址
操作数的值在寄存器中,指令执行时直接取出寄存器的值来操作
MOVR1,R2 ;R2->R1
SUB R0,R1,R2 ;R1-R2->R0
2.立即寻址
立即数要以#为前缀,表示16进制数值时以 0x打头表示
MOVR0,#0XFF00 ;0XFF00->R0
SUBS R0,R0,#1 ;R0-1->R0
并不是每个整数都可以作为立即数,立即数必须是一个8位的常数(0-0xFF)循环右移偶数位(0-0xF的2倍)得到
3.寄存器移位寻址
寄存器移位寻址是ARM指令集特有的寻址方式,当第2操作数是寄存器移位寻址时,第2个寄存器操作数在与第1个操作数结合之前,先进行移位操作
MOV R0,R2,LSL#3 ;R2的值左移3位,存入R0,即R0=R2*8
ANDS R1,R1,R2,LSL R3 ;R2的值左移R3位,然后和R1相与操作,结果放入R1
可以采用的移位操作如下:
LSL: 逻辑左移(logicalShift Left),寄存器中的低端空出位补0
LSR: 逻辑右移(logicalShift Right),寄存器中的高端空出位补0
ASR: 算术右移(ArithmeticShift Right),移位过程中保持符号位不变,即如果源操作数为正数,则字的高端空出位补0,否则补1
ROR: 循环右移(RotateRight),由字的低端移出的位填入字的高端空出的位
RRX: 带扩展的循环右移(RotateRight with eXtend),操作数右移一位,高端空出位用原C标志位填充
=>> 移位操作符后面没有逗号的哦,
4.寄存器间接寻址
操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。寄存器要用中括号扩起来
LDRR1,[R2] ;将R2中的数值作为地址,取出该地址中的数据保存在RI中
SWPR1,R1,[R2] ;将R2中的数值作为地址,取出该地址中的数值与R1中的数值交换
5.基址寻址
将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能部件寄存器访问等
LDR R2,[R3,#0XC0] ;读取R3+0XC0地址中的数据,放入R2
STR R1,[R0,#-2] ;将R0中数值减2作为地址,把R1中的内容保存到此地址单元中去
LDRR1,[R0,R3,LSL #1] ;将R0+R3*2地址上的存储单元的内容读出,存入R1
6.多寄存器寻址
一次可以传送多个寄存器的值,允许一条指令传送16个寄存器的任何子集或所有寄存器
LDMIA R1!,{R2-R7,R12} ;将R1指向的地址单元中的数据读出到R2~R7,R12中(R1自动加1)
STMIA R0, {R3-R6,R10} ;将R3-R6,R10中的数据保存到R0指向的地址单元中(R0自动加1)
使用多寄存器寻址指令时,寄存器子集的顺序由小到大排列,连续的可用 –连接,否则用 ,分隔
7. 堆栈寻址
使用一个专门的寄存器(堆栈指针,通常都是R13)指向一块存储区域(堆栈),指针所指向的存储单元就是堆栈的栈顶。
递增堆栈:向高地址方向生长
递减堆栈:向低地址方向生长
满堆栈:堆栈指针指向最后压入堆栈的有效数据项
空堆栈:堆栈指针指向下一个要放入数据的空位置
满递增:LDMFA STMFA
空递增:LDMEA STMEA
满递减:LDMFD STMFD
空递减:LDMED STMED
STMFD SP!,{R1-R7,LR} ;将R1-R7,LR入栈,满递减堆栈
LDMFD SP!,{R1-R7,LR} ;数据出栈,放入R1-R7,LR寄存器
8. 块拷贝寻址
多寄存器传送指令用于将一块数据从存储器的某一位置拷贝到另一位置
STMIA R0!,{R1-R7} ;将R1-R7的数据保存到R0指向的存储器单元中,存储器指针(R0)在保存第一
个值之后增加,增长方向为向上增长[+1]
STMIB R0!,{R1-R7} ;将R1-R7的数据保存到R0指向的存储器单元中,存储器指针(R0)在保存第一
个值之前增加,增长方向为向上增长[+1]
STMDA R0!,{R1-R7} ;将R1-R7的数据保存到R0指向的存储器单元中,存储器指针(R0)在保存第
一个值之后增加,增长方向为向下增长[-1]
STMDA R0!,{R1-R7} ;将R1-R7的数据保存到R0指向的存储器单元中,存储器指针(R0)在保存第
一个值之前增加,增长方向为向下增长[-1]
9. 相对寻址
相对寻址是基址寻址的一种变通。由PC指针提供基址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址
BL ROUTE1 ;调用到ROUTE1子程序
BEQ LOOP ;条件跳转到LOOP标号处
…
LOOP MOV R6,#1
…
ROUTE1
…