• 模拟uClinux系统调用


    这篇文章原来放在CU上的,现在挪过来了。CU上设置不可见了。

    1.  目标

              这里主要是实验一下uclinux的系统调用。

    2.   环境

             OS                :vmware + redhat 9

             编译器          :arm-elf-gcc 2.95

             ARM7模拟器:skyeye

    3.   源文件

          1个汇编(init.s),3个C文件(main.c, print.c, syscall.c),1个C头文件(unistd.h),1个Makefile,1个链接文件(syscall.lds),1个skyeye的配置文件(skyeye.conf),共8个文件

    init.s

    .equ INTCON,   0x01e00000
    .equ INTMSK,   0x01e0000c
    .equ LOCKTIME, 0x01d8000c
    .equ PLLCON,   0x01d80000
    .equ CLKCON,   0x01d80004
    .equ WTCON,    0x01d30000
    .equ I_ISPR,   0x01e00020
    .equ I_ISPC,   0x01e00024
    .equ TCFG0,    0x01d50000
    .equ TCFG1,    0x01d50004
    .equ TCON,     0x01d50008
    .equ TCNTB5,   0X01d50048
    .equ UTXH0,    0x01d00020
    .equ UFCON0,   0x01d00008
    .equ ULCON0,   0x01d00000
    .equ UCON0,    0x01d00004
    .equ UBRDIV0,  0x01d00028
    
    
    .globl _start
    _start:
        b reset
        b .
        b HandlerSWI
        b .
        b .
        b .
        b .
        b .
    
    
    reset:
        mov r0,#0x80 | 0x40 | 0x13  @ svc, disable irq,fiq
        msr cpsr_c,r0
    
        ldr sp, =0x0c700000
    
        ldr r0,=WTCON        @ disable watch dog
        ldr r1, =0x0
        str r1, [r0]
    
        ldr r0, =INTCON      @ non-vector mode, disable irq, disable fiq
        ldr r1, =0x7
        str r1, [r0]
    
        ldr r0, =LOCKTIME
        ldrb r1, =800
        strb r1, [r0]
    
        ldr r0, =PLLCON
        ldr r1, =0x34031
        str r1,[r0]
        
        ldr r0, =CLKCON
        ldr r1, =0x7ff8
        str r1, [r0]
    
        @ UART 0
        ldr r0,=UFCON0
        mov r1,#0x0
        str r1,[r0]
    
        ldr r0,=ULCON0
        mov r1,#0x03
        str r1,[r0]
        
        ldr r0,=UCON0
        mov r1,#0x05
        str r1,[r0]
    
        ldr r0,=UBRDIV0
        mov r1,#32
        str r1,[r0]
    
        ldr r0,=UTXH0        @ print 'C'
        mov r1,#'S'
        str r1,[r0]
        
        @ sp_svc
        ldr sp,=0x0c700000
        
        ldr r0, =INTMSK
        ldr r1, =0x03ffffff  @ disable all irq.
        str r1, [r0]
        
        @ move to user mode
    
        mov r0, #0x80 | 0x40 | 0x10  @ svc, disable irq,fiq
        msr cpsr_c,r0
    
        ldr sp, =0x0c600000    
    
    
        mov r0,#'
    '
        ldr r1,=UTXH0       @ print 'A'
        str r0,[r1]
    
        b Main      
    
    
    HandlerSWI:       
        stmfd sp!,{r0-r12,lr}
     
        stmfd sp!,{r0-r2}       @ in this example, we use only three paramters at most
    
        ldr r0,[lr,#-4]         @ lr is "swi #x" address, get swi instruction code
        bic r0,r0,#0xff000000   @ get #x
    
        ldmfd sp!, {r1-r3}
        
        bl swi_c_handler                  @ c function use r0,r1 as parameter, and return result with r0
    
    @    ldr r1,=UTXH0           @ print 'B'
    @    str r0,[r1]
    
        str r0,[sp]             @ change r0 to true result
    
        ldmfd sp!, {r0-r12,pc}^               @ ^,不能在用户模式使用 作用: 1.如果寄存器列表有pc, 还要把spsr复制到cpsr, 2.如果没有pc, 那么这些寄存器指的是用户寄存器,而不是当前模式的寄存器

    main.c

    #include "unistd.h"
    
    static inline __syscall0(void,hello);
    static inline __syscall2(int,add,int,a,int,b);
    static inline __syscall2(int,sub,int,a,int,b);
    static inline __syscall2(int,sum,int *,p,int,count);
    static inline __syscall3(int,sub3,int,a,int,b,int,c);
    
    int swi_c_handler(int sys_call_num,int param1,int param2,int param3){
        int result=0;
    
        switch(sys_call_num){
    
            case __NR_hello:
                sys_hello();
                break;
            
            case __NR_add:
                result = sys_add(param1,param2);
                break;
    
            case __NR_sub:
                result = sys_sub(param1,param2);
                break;
    
            case __NR_sub3:
                result = sys_sub3(param1,param2,param3);
                break;
            
            case __NR_sum:
                result = sys_sum((int *)param1,param2);
                break;
            
            default:
                print("no such call number: %d
    ",sys_call_num);
                result = -1;
        }
    
        return result;
    }
    
    
    
    void Main(){
        char *s="hello,world";
        int num[5]={4,7,10,3,8};  //32
    
        print("%s
    ",s);
        
        hello();
        print("5+8=%d
    ",add(5,8));
        print("28-13=%d
    ",sub(28,13));
        print("39-13-2=%d
    ",sub3(39,13,2));
        print("4+7+10+3+8=%d
    ",sum(num,5));
        
        while(1);
    }

    print.c

    #include
    
    void print_char(char c){
        __asm__ __volatile__ (
        "mov r0,%0 
    	"
        "ldr r1,=0x01d00020 
    	"
        "str r0,[r1] 
    	"
        :
        :"r"((long)(c))
        :"r0","r1");
    }
    
    int itoa(char * buf,int num){
        int i=0,a=num,b;
    
        while(1){
            b = a % 10;
            a = a / 10;
            buf[i++]=b+'0';
            if(a==0) break;
        }
    
        return i;
    }
    
    void print(char * fmt, ...){
        char out_buf[128],itoa_buf[10],*s;
        int n,i,index=0,itoa_len;
    
        va_list args;
        va_start(args,fmt);
    
        for(;*fmt;++fmt){
            if(*fmt!='%'){
                out_buf[index++]=*fmt;
                continue;
            }
            fmt++;
            switch(*fmt){
                case 'd':
                    n = (int)va_arg(args,int);
                    itoa_len = itoa(itoa_buf,n);
                    for(i=itoa_len-1;i>=0;i--){
                        out_buf[index++]=itoa_buf[i];
                    }
                    break;
                case 's':
                    s = (char *)va_arg(args,char *);
                    for(;*s;s++){
                        out_buf[index++]=*s;
                    }
                    break;
                default:
                    out_buf[index++]=' ';
            }
        }
    
        out_buf[index]=0; // NULL
    
        for(s=out_buf;*s;s++){
            print_char(*s);
        }
    
        va_end(args);
    }

    syscall.c

    void sys_hello(){
        print("hello, S3C44B0X!
    ");
    }
    
    
    int sys_add(int a,int b){
        return a+b;
    }
    
    
    int sys_sub(int a,int b){
        return a-b;
    }
    
    
    int sys_sub3(int a,int b,int c){
        return a-b-c;
    }
    
    int sys_sum(int * pnum, int count){
        int sum=0,i;
        for(i=0;i         sum+=pnum[i];
        }
        return sum;
    }

    unistd.h

    #ifndef __UNISTD_H_
    #define __UNISTD_H_
    
    #define __NR_SYSCALL_BASE 0X900000
    
    #define __NR_hello  (__NR_SYSCALL_BASE + 1)
    #define __NR_add    (__NR_SYSCALL_BASE + 2)
    #define __NR_sub    (__NR_SYSCALL_BASE + 3)
    #define __NR_sub3   (__NR_SYSCALL_BASE + 4)
    #define __NR_sum    (__NR_SYSCALL_BASE + 5)
    
    #define __sys1(x) #x
    #define __sys2(x) __sys1(x)
    
    #define __syscall(name) "swi " __sys2(__NR_##name) "
    	"
    
    #define __syscall0(type,name) 
    type name(){  
        long __res; 
        __asm__ __volatile__ ( 
        __syscall(name)        
        "mov %0, r0 
    	"      
        :"=r"(__res)           
        :                      
        :"r0","lr");           
        return (type)(__res);  
    }
    
    
    #define __syscall1(type,name,type1,arg1){ 
    type name(type1 arg1){   
        long __res;      
        __asm__ __volatile ( 
        "mov r0,%1 
    	"   
        __syscall(name)    
        "mov %0,r0 
    	"   
        :"=r"((long)__res)       
        :"r"((long)(arg1))        
        :"r0","lr");       
    }
    
    
    #define __syscall2(type,name,type1,arg1,type2,arg2) 
    type name(type1 arg1,type2 arg2){ 
        long __res;      
        __asm__ __volatile ( 
        "mov r0,%1 
    	"   
        "mov r1,%2 
    	"   
        __syscall(name)    
        "mov %0,r0 
    	"   
        :"=r"((long)__res)       
        :"r"((long)(arg1)),"r"((long)(arg2))        
        :"r0","r1","lr");       
    }
    
    #define __syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) 
    type name(type1 arg1,type2 arg2,type3 arg3){ 
        long __res;      
        __asm__ __volatile ( 
        "mov r0,%1 
    	"   
        "mov r1,%2 
    	"   
        "mov r2,%3 
    	"   
        __syscall(name)    
        "mov %0,r0 
    	"   
        :"=r"((long)__res)       
        :"r"((long)(arg1)),"r"((long)(arg2)),"r"((long)(arg3))       
        :"r0","r1","r2","lr");       
    }
    
    
    #endif

    syscall.lds

    OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
    OUTPUT_ARCH(arm)
    ENTRY(_start)
    SECTIONS
    {
        . = 0x00000000;
    
        .text :
        {
            init.o    (.text)
        main.o    (.text)
        print.o   (.text)
        syscall.o (.text)
        }
        
        . = ALIGN(32);
    
        .data :
        {
           *(.data)
        }
    
        . = ALIGN(32);
    
        .bss :
        {
        *(.bss)
        *(.rodata)
        }
    
    }

    Makefile

    all: syscall
    
    syscall: init.o main.o print.o syscall.o
        arm-elf-ld -T syscall.lds -o syscall init.o main.o print.o syscall.o
        arm-elf-objcopy -O binary syscall syscall.bin
    
    init.o: init.s
        arm-elf-as --gstabs -o init.o init.s
    
    main.o: main.c unistd.h
        arm-elf-gcc -gstabs -c main.c
    
    print.o: print.c
        arm-elf-gcc -gstabs -c print.c
    
    syscall.o: syscall.c
        arm-elf-gcc -gstabs -c syscall.c
    
    .PHONY: clean
    clean:
        rm -f *.o syscall syscall.bin

    skyeye.conf

    #skyeye config file for S3C44B0X
    cpu: arm7tdmi
    mach: s3c44b0x
    
    # physical memory
    mem_bank: map=M, type=RW, addr=0x00000000, size=0x00200000, file=syscall.bin
    mem_bank: map=M, type=RW, addr=0x0c000000, size=0x00800000
    
    # peripherals I/O mapping area
    mem_bank: map=I, type=RW, addr=0x01c00000, size=0x00400000
    
    # uart 0
    uart: mod=stdio

    4. 运行

            # skyeye -e syscall

  • 相关阅读:
    机器人走方格问题
    一道数列的规律题(使用递归解决)
    反转单链表
    求一个二叉树的深度以及如何判断一个二叉树是一个平衡二叉树
    打印素数
    DAY28-mysql扩展与预处理-查出问题的关键
    DAY31
    jQuery很简单很基础的
    JavaScript中的事件委托及好处
    结合个人经历总结的前端入门方法
  • 原文地址:https://www.cnblogs.com/bear129/p/8196293.html
Copyright © 2020-2023  润新知