Chinaunix首页 | 论坛 | 博客
  • 博客访问: 148195
  • 博文数量: 43
  • 博客积分: 3000
  • 博客等级: 中校
  • 技术积分: 601
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-22 17:24
文章分类
文章存档

2010年(43)

我的朋友

分类: LINUX

2010-12-03 19:21:51

; 工程名:Exa2.mcp
; 文件名:Exa2.S
; 功能:使用LDR、STR指令对变量NumCount进行加1操作
; 说明:使用ARMulate软件仿真调试
NumCount    EQU        0x3fff3000            ; 定义变量NumCount
            AREA    Example2,CODE,READONLY    
            ENTRY                     
MAIN        LDR        R0,=NumCount        ; 使用LDR指令装载NumCount的地址到R0
            LDR        R1,[R0]                ; 取出变量值
            ADD        R1,R1,#1            ; NumCount=NumCount+1
            STR        R1,[R0]                ; 保存变量值
HALT        B        HALT            
            END


;工程名:Exa3.mcp
 ;文件名:Exa3.s
 ;功能:使用数据处理类指令实现以下各功能
 ;说明:使用ARMulate软件仿真调试
X        EQU        11            ; 定义X的值为11
Y        EQU        8            ; 定义Y的值为8
Z EQU 5 ; 定义Z的值为5

BIT23    EQU        (1<<23)        ; 定义BIT23的值为0x00800000展开就是0x00000000 10000000 00000000 00000000
             ; 只有宏中可以这么写
            AREA    Example3,CODE,READONLY    ; 声明代码段Example3
            ENTRY                ; 标识程序入口
            CODE32                ; 声明32位ARM指令
            
START        ; 使用MVN、SUB指令实现:R5 = 0x5FFFFFF8 - R8 * 8
            MVN        R0,#0xA0000007        ; 0xA0000007的反码为0x5FFFFFF8
            SUB R5,R0,R8,LSL #3        ; R8左移3位,结果即是 R8 * 8 R5 = R0 - R8
        
            
            ; 使用CMP指令判断(7*Y/2)>(4*X)吗?若大于则R5 = R5&0xFFFF00a0,否则R5 = R5|0x000000FF
            MOV        R0,#Y
            ADD        R0,R0,R0,LSL #3        ; 计算R0 = Y + 8*Y = 9*Y
            MOV        R0,R0,LSR #1        ; 计算R0 = 7*Y/2
            MOV        R1,#X
            MOV        R1,R1,LSL #2        ; 计算R1 = 4*X
            CMP        R0,R1                ; 比较R0和R1,即(7*Y/2)(4*X)进行比较
            LDRHI R2,=0xFFFF00a0        ;(7*Y/2)>(4*X),则R2 <= 0xFFFF00a0
            ANDHI    R5,R5,R2            ;(7*Y/2)>(4*X),则R5 = R5&R2
            ORRLS    R5,R5,#0x000000FF    ;(7*Y/2)(4*X),则R5 = R5|0x000000FF            
            
            ; 使用TST指令测试R5的bit23是否为1,若是则将bit6位清零(使用BIC指令)
            TST     R5,#BIT23
            BICNE    R5,R5,#0x00000040                    
            
            ;使用MUL和MLA实现R3=(7*Y)+(3*X)+Z的功能    
            MOV        R0,#Y
            MOV R1,#7
            MUL        R2,R0,R1         ;计算R2 = 7*Y            
            MOV        R0,#X
            MOV R1,#2
            MLA R3,R0,R1,R0         ; 计算R3 = 2*X + X            
            ADDS R3,R3,R2 ;R3= (7*Y)+(3*X)
            ADDS R3,R3,#Z; ;R3= (7*Y)+(3*X)+Z
            
            B        START            
            END    


; 工程名:Exa4.mcp
; 文件名:Exa4.S
; 功能:使用BX指令切换处理器状态
; 说明:使用ARMulate软件仿真调试
            AREA    Example4,CODE,READONLY    
            ENTRY            
            CODE32    

START            
ARM_CODE    MOV R0, #0
            BL DELAY_SUB
            ; MOV LR,PC
            ; LDR PC,= DELAY_SUB

            ADR     R0,THUMB_CODE+1 ; 利用伪指令装载THUMB_CODE地址,为什么加一,改变 状态
            BX     R0                    ; 跳转并切换处理器状态
            
            
DELAY_SUB
            MOV R1, #10
LOOP SUBS R1,R1,#1
            BNE LOOP
            MOV     PC,LR                 ; 子程序返回
      
            CODE16
THUMB_CODE ;标号的地址就是离他最近的语句的地址
            MOV        R0,#10                ; R0 = 10
            MOV        R1,#20                ; R1 = 20
            ADD        R0,R1                ; R0 = R0+R1
            LDR     R0,=ARM_CODE ;执行距离标号最近的语句
            BX     R0
            END


; 工程名:Exa5.mcp
; 文件名:Exa5.S
; 功能:计算X的n次方的值
; 说明:X和n均为无符号整数
X        EQU        9            ; 定义X的值为9
n        EQU        8            ; 定义n的值为8            
            AREA    Example5, CODE,READONLY    ; 声明代码段Example5
            ENTRY            ; 标识程序入口
            CODE32            ; 声明32位ARM指令            
START        LDR        SP,=0x40003F00        ; 设置堆栈(满递减堆栈,使用STMFD/LMDFD指令)
            LDR        R0,=X
            LDR        R1,=n
            BL        POW                    ; 调用子程序POW,返回值为R0            
HALT        B        HALT        
    
; 名称:POW
; 功能:整数乘方运算。
; 入口参数:R0        底数
; R1        指数
; 出口参数:R0        运算结果
; 占用资源:R0、R1
; 说明:本子程序不考虑溢出问题
POW            
            STMFD    SP!,{R1-R12,LR}        ; 寄存器入栈保护
            MOVS    R2,R1                ; 将指数值复制到R2,并影响条件码标志
            
            MOVEQ    R0,#1                ; 若指数为0,则设置R0=1
            BEQ        POW_END                ; 若指数为0,则返回
            
            CMP        R2,#1
            BEQ        POW_END                ; 若指数为1,则返回。(此时R0没有被更改)
            
            MOV        R1,R0                ; 设置DO_MUL子程序的入口参数R0和R1
            SUB        R2,R2,#1            ; 计数器R2 = 指数值减1
POW_L1        BL        DO_MUL                ; 调用DO_MUL子程序,R0 = R1 * R0
            SUBS    R2,R2,#1            ; 每循环一次,计数器R2减1
            BNE        POW_L1                ; 若计数器R2不为0,跳转到POW_L1            
        
POW_END        LDMFD    SP!,{R1-R12,PC}        ; 寄存器出栈,返回

; 名称:DO_MUL
; 功能:32位乘法运算。
; 入口参数:R0        乘数
; R1     被乘数
; 出口参数:R0        计算结果
; 占用资源:R0、R1
; 说明:本子程序不会破坏R1
DO_MUL        MUL        R0,R1,R0            ; R0 = R1 * R0
            MOV        PC,LR                ; 返回            
            
            END    


; 工程名:Exa6.mcp
; 文件名:Exa6.S
; 功能:计算1+2+...+N的值
; 说明:N≥0,当N=0时结果为0;当N=1时结果为1。

N        EQU        100                ; 定义N的值为100
            
            AREA    Example6,CODE,READONLY    ; 声明代码段Example6
            ENTRY                ; 标识程序入口
            CODE32                ; 声明32位ARM指令

ARM_CODE    LDR        SP,=0x40003F00    ; 设置堆栈指针
            ADR        R0,THUMB_CODE+1
            BX        R0            ; 跳转并切换处理器状态
            
            LTORG                ; 声明文字池

            CODE16                ; 声明16位Thumb指令
THUMB_CODE    LDR        R0,=N        ; 设置子程序SUM_N的入口参数
            BL        SUM_N        ; 调用子程序SUM_N
                    
            B        THUMB_CODE
    
; 名称:SUM_N
; 功能:计算1+2+...+N的值
; 入口参数:R0        N的值
; 出口参数:R0        运算结果
; 占用资源:R0
; 说明:当N=0时结果为1;当N=1时结果为1。
; 若运算溢出,结果为0。
SUM_N            
            PUSH    {R1-R7,LR}    ; 寄存器入栈保护
            MOVS    R2,R0        ; 将N的值复制到R2,并影响条件码标志
            BEQ        SUM_END        ; 若N的值为0,则返回。(此时R0没有被更改)
            
            CMP        R2,#1
            BEQ        SUM_END        ; 若N的值为1,则返回。(此时R0没有被更改)
            
            MOV        R1,#1        ; 初始化计数器R1=1
            MOV        R0,#0        ; 初始化结果寄存器R0=0
SUM_L1        ADD        R0,R1        ; R0 = R0 + R1
            BCS        SUM_ERR        ; 结果溢出,跳转到SUM_ERR        
            CMP        R1,R2        ; 将计数器的值与N比较
            BHS        SUM_END        ; 若计数器的值≥N,则运算结束
            ADD        R1,#1
            B        SUM_L1
            
SUM_ERR        MOV        R0,#0            
        
SUM_END        POP        {R1-R7,PC}    ; 寄存器出栈,返回
            
            END    


阅读(3338) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~