MIPS体系结构剖析,编程与实践[6]

linux内核信号处理机制--do_signal函数讲解 (适用mips架构)     Linux为了允许用户态进程之间的通信而引入signal.此外, 内核使用signal给进程通知系统事件 对于信号signal,你要记住的基本点如下:   信号分实时信号(编码值为[32,64])和非实时信号编码值为[1,31]    ----实时意味着相同信号多次发送都会被加入悬挂信号队列,而不丢失   信号处理方式包括默认处理(eg:SIGKILL,SIGSTO... 阅读详情
第六章 MIPS-Linux Kernel 分析(2)
上次说道SAVE_ALL里有些玄机,这里把include/asm-mips/stackframe.h
对着注解一下,希望能说清楚一些.
(因为时间关系,我写的文档将主要以这种文件注解为主,加上我认为有用
的背景知识或者分析.)
 
/* 
 一些背景知识
 
 一.mips汇编有个约定(后来也有些变化,我们不管,o32,n32),32个通用寄存器不是一视同仁
  的,而是分成下列部分:
      寄存器号            符号名            用途
        0                 始终为0     看起来象浪费,其实很有用
        1                 at          保留给汇编器使用
        2-3               v0,v1       函数返回值
        4-7               a0-a3       前头几个函数参数
        8-15              t0-t7       临时寄存器,子过程可以不保存就使用
        24-25             t8,t9       同上
        16-23             s0-s7       寄存器变量,子过程要使用它必须先保存
                                      然后在退出前恢复以保留调用者需要的值
        26,27             k0,k1       保留给异常处理函数使用
        28                gp          global pointer;用于方便存取全局或者静态变量
        29                sp          stack pointer
        30                s8/fp       第9个寄存器变量;子过程可以用它做frame pointer
        31                 ra         返回地址
   硬件上这些寄存器并没有区别(除了0号),区分的目的是为了不同的编译器产生的代码
   可以通用
 
  二. r4k MIPS CPU中和异常相关的控制寄存器(这些寄存器由协处理器cp0控制,有独立的存取方法)有:
      1.status 状态寄存器
      31  28 27 26 25 24        16 15          8 7 6  5 4 3  2   1   0
     ------------------------------------------------------------------
     | cu0-3|RP|FR|RE| Diag Status|   IM7-IM0  |KX|SX|UX|KSU|ERL|EXL|IE|
     ------------------------------------------------------------------
     其中KSU,ERL,EXL,IE位在这里很重要:
       KSU: 模式位 00 -kernel  01--Supervisor 10--User
       ERL: error level,0->normal,1->error
       EXL: exception level,0->normal,1->exception,异常发生是EXL自动置1
       IE: interrupt Enable, 0 -> disable interrupt,1->enable interrupt
       (IM位则可以用于enbale/disable具体某个中断,ERL||EXL=1 也使得中断不能响应)
      系统所处的模式由KSU,ERL,EXL决定:
        User mode: KSU = 10 && EXL=0 && ERL=0
        Supervisor mode(never used): KSU=01 && EXL=0 && ERL=0
        Kernel mode: KSU=00 || EXL=1 || ERL=1
      2.cause寄存器
       31 30 29 28 27          16 15           8 7 6          2  1  0
      ----------------------------------------------------------------
      |BD|0 | CE  |     0        | IP7 - IP0    |0|Exc code     | 0  |
      ----------------------------------------------------------------
      异常发生时cause被自动设置
      其中:
        BD指示最近发生的异常指令是否在delay slot中
        CE发生coprocessor unusable异常时的coprocessor编号(mips有4个cp)
        IP: interrupt pending, 1->pending,0->no interrupt,CPU有6个中断
            引脚,加上两个软件中断(最高两个)
        Exc code:异常类型,所有的外设中断为0,系统调用为8,... 
      3.EPC
         对一般的异常,EPC包含:
           . 导致异常的指令地址(virtual)
           or. if 异常在delay slot指令发生,该指令前面那个跳转指令的地址
         当EXL=1时,处理器不写EPC
      4.和存储相关的:
        context,BadVaddr,Xcontext,ECC,CacheErr,ErrorEPC
        以后再说
 
      一般异常处理程序都是先保存一些寄存器,然后清除EXL以便嵌套异常,
      清除KSU保持核心态,IE位看情况而定;处理完后恢复一些保存内容以及CPU状态
 
   */
 
/* SAVE_ALL 保存所有的寄存器,分成几个部分,方便不同的需求选用*/
/*保存AT寄存器,sp是栈顶PT_R1是at寄存器在pt_regs结构的偏移量
  .set xxx是汇编指示,告诉汇编器要干什么,不要干什么,或改变状态
 */
#define SAVE_AT                                          /
               .set    push;                            /
               .set    noat;                            /
               sw      $1, PT_R1(sp);                   /
               .set    pop
 
/*保存临时寄存器,以及hi,lo寄存器(用于乘法部件保存64位结果)
 可以看到mfhi(取hi寄存器的值)后并没有立即保存,这是因为
 流水线中,mfhi的结果一般一拍不能出来,如果下一条指令就想
 用v1则会导致硬件停一拍,这种情况下让无关的指令先做可以提高
 效率.下面还有许多类似的例子
 */
#define SAVE_TEMP                                        /
               mfhi    v1;                              /
               sw      $8, PT_R8(sp);                   /
               sw      $9, PT_R9(sp);                   /
               sw      v1, PT_HI(sp);                   /
               mflo    v1;                              /
               sw      $10,PT_R10(sp);                  /
               sw      $11, PT_R11(sp);                 /
               sw      v1,  PT_LO(sp);                  /
               sw      $12, PT_R12(sp);                 /
               sw      $13, PT_R13(sp);                 /
               sw      $14, PT_R14(sp);                 /
               sw      $15, PT_R15(sp);                 /
               sw      $24, PT_R24(sp)
 
/* s0-s8 */
#define SAVE_STATIC                                      /
               sw      $16, PT_R16(sp);                 /
               sw      $17, PT_R17(sp);                 /
               sw      $18, PT_R18(sp);                 /
               sw      $19, PT_R19(sp);                 /
               sw      $20, PT_R20(sp);                 /
               sw      $21, PT_R21(sp);                 /
               sw      $22, PT_R22(sp);                 /
               sw      $23, PT_R23(sp);                 /
               sw      $30, PT_R30(sp)
 
#define __str2(x) #x
#define __str(x) __str2(x)
 
 
 
/*ok,下面对这个宏有冗长的注解*/
#define save_static_function(symbol)                                    /
__asm__ (                                                               /
        ".globl/t" #symbol "/n/t"                                       /
        ".align/t2/n/t"                                                 /
        ".type/t" #symbol ", @function/n/t"                             /
        ".ent/t" #symbol ", 0/n"                                        /
        #symbol":/n/t"                                                  /
        ".frame/t$29, 0, $31/n/t"                                       /
        "sw/t$16,"__str(PT_R16)"($29)/t/t/t# save_static_function/n/t"  /
        "sw/t$17,"__str(PT_R17)"($29)/n/t"                              /
        "sw/t$18,"__str(PT_R18)"($29)/n/t"                              /
        "sw/t$19,"__str(PT_R19)"($29)/n/t"                              /
        "sw/t$20,"__str(PT_R20)"($29)/n/t"                              /
        "sw/t$21,"__str(PT_R21)"($29)/n/t"                              /
        "sw/t$22,"__str(PT_R22)"($29)/n/t"                              /
        "sw/t$23,"__str(PT_R23)"($29)/n/t"                              /
        "sw/t$30,"__str(PT_R30)"($29)/n/t"                              /
        ".end/t" #symbol "/n/t"                                         /
        ".size/t" #symbol",. - " #symbol)
 
/* Used in declaration of save_static functions.  */
#define static_unused static __attribute__((unused))
 
/*以下这一段涉及比较微妙的问题,没有兴趣可以跳过*/
 
/* save_static_function宏是一个令人迷惑的东西,它定义了一个汇编函数,保存s0-s8
   可是这个函数没有返回!实际上,它只是一个函数的一部分:
   在arch/mips/kernel/signal.c中有:
       save_static_function(sys_rt_sigsuspend);
       static_unused int
       _sys_rt_sigsuspend(struct pt_regs regs)
       {
               sigset_t *unewset, saveset, newset;
                       size_t sigsetsize;
   这里用save_static_function定义了sys_rt_sigsuspend,而实际上如果
   你调用sys_rt_sigsuspend的话,它保存完s0-s8后,接着就调用_sys_rt_sigsuspend!
   看它链接后的反汇编片段:
      80108cc8 <sys_rt_sigsuspend>:
      80108cc8:       afb00058        sw      $s0,88($sp)
      80108ccc:       afb1005c        sw      $s1,92($sp)
      80108cd0:       afb20060        sw      $s2,96($sp)
      80108cd4:       afb30064        sw      $s3,100($sp)
      80108cd8:       afb40068        sw      $s4,104($sp)
      80108cdc:       afb5006c        sw      $s5,108($sp)
      80108ce0:       afb60070        sw      $s6,112($sp)
      80108ce4:       afb70074        sw      $s7,116($sp)
      80108ce8:       afbe0090        sw      $s8,144($sp)
 
      80108cec <_sys_rt_sigsuspend>:
      80108cec:       27bdffc8        addiu   $sp,$sp,-56
      80108cf0:       8fa80064        lw      $t0,100($sp)
      80108cf4:       24030010        li      $v1,16
      80108cf8:       afbf0034        sw      $ra,52($sp)
      80108cfc:       afb00030        sw      $s0,48($sp) ---> notice
      80108d00:       afa40038        sw      $a0,56($sp)
      80108d04:       afa5003c        sw      $a1,60($sp)
      80108d08:       afa60040        sw      $a2,64($sp)
      ...
 
   用到save_static_function的地方共有4处:
         signal.c:save_static_function(sys_sigsuspend);
         signal.c:save_static_function(sys_rt_sigsuspend);
         syscall.c:save_static_function(sys_fork);
         syscall.c:save_static_function(sys_clone);
   我们知道s0-s8如果在子过程用到,编译器本来就会保存/恢复它的(如上面的s0),
   那为何要搞这个花招呢?我分析之后得出如下结论:
  (警告:以下某些内容是我的推测,可能不完全正确)
 
   先看看syscall的处理,syscall也是mips的一种异常,异常号为8.上次我们说
   了一般异常是如何工作的,但在handle_sys并非用BUILD_HANDLER生成,而是在
   scall_o23.S中定义,因为它又有其特殊之处.
         1.缺省情况它只用了SAVE_SOME,并没有保存at,t*,s*等寄存器,因为syscall
         是由应用程序调用的,不象中断,任何时候都可以发生,所以一般编译器就可以
         保证不会丢数据了(at,t*的值应该已经无效,s*的值会被函数保存恢复).
           这样可以提高系统调用的效率
         2.它还得和用户空间打交道(取参数,送数据)
   还有个别系统调用需要在特定的时候手工保存s*寄存器,如上面的几个.为什么呢?
   对sigsuspend来说,它将使进程在内核中睡眠等待信号到来,信号来了之后将直接
   先回到进程的信号处理代码,而信号处理代码可能希望看到当前进程的寄存器
   (sigcontext),这是通过内核栈中的pt_regs结构获得的,所以内核必需把s*寄存器
   保存到pt_regs中.对于fork的情况,则似乎是为了满足vfork的要求.(vfork时,子进程
   不拷贝页表(即和父进程完全共享内存),注意,连copy-on-write都没有!父进程挂起
   一直到子进程不再使用它的资源(exec或者exit)).fork 系统调用使用ret_from_fork
   返回,其中调用到了RESTORE_ALL_AND_RET(entry.S),需要恢复s*.
 
   这里还有一个很容易混乱的地方: 在scall_o32.S和entry.S中有几个函数(汇编)是同名
   的,如restore_all,sig_return等.总体来说scall_o32.S中是对满足o32(old 32bit)汇编
   约定的系统调用处理,可以避免保存s*,而entry.S中是通用的,保存/恢复所由寄存器
   scall_o32.S中也有一些情况需要保存静态寄存器s*,此时它就会到ret_from_syscall
   而不是本文件中的o32_ret_from_syscall返回了,两者的差别就是恢复的寄存器数目
   不同.scall_o32.S中一些错误处理直接用ret_from_syscall返回,我怀疑会导致s*寄存器
   被破坏,有机会请各路高手指教.
 
   好了,说了一通系统调用,无非是想让大家明白内核中寄存器的保存恢复过程,以及
   为了少做些无用功所做的努力.下面看为什么要save_static_function:为了避免
   s0寄存器的破坏.
     如果我们使用
        sys_rt_sigsuspend()
        {   ..
           save_static;
           ...
        }
    会有什么问题呢,请看,
 
    Nasty degree - 3 days of tracking.
 
    The symptom was pthread cannot be created.  In the end the caller will 
    get a BUS error.
 
    What exactly happened has to do with how registers are saved.  Below
    attached is the beginning part of sys_sigsuspend() function.  It is easy
    to see that s0 is saved into stack frame AFTER its modified.  Next time
    when process returns to userland, the s0 reg will be wrong!
 
    So the bug is either
 
    1) that we need to save s0 register in SAVE_SOME and not save it in
    save_static; or that
 
    2) we fix compiler so that it does not use s0 register in that case (it
            does the same thing for sys_rt_sigsuspend)
 
    I am sure Ralf will have something to say about it.  :-)  In any case, I
    attached a patch for 1) fix.
 
sys_sigsuspend(struct pt_regs regs)
{
        8008e280:   27bdffc0        addiu   $sp,$sp,-64
        8008e284:   afb00030        sw      $s0,48($sp)
                   sigset_t *uset, saveset, newset;
 
                    save_static(&regs);
        8008e288:   27b00040        addiu   $s0,$sp,64   /* save_static时
                                                            s0已经破坏*/
        8008e28c:   afbf003c        sw      $ra,60($sp)
        8008e290:   afb20038        sw      $s2,56($sp)
        8008e294:   afb10034        sw      $s1,52($sp)
        8008e298:   afa40040        sw      $a0,64($sp)
        8008e29c:   afa50044        sw      $a1,68($sp)
        8008e2a0:   afa60048        sw      $a2,72($sp)
        8008e2a4:   afa7004c        sw      $a3,76($sp)
        8008e2a8:   ae100058        sw      $s0,88($s0)
        8008e2ac:   ae11005c        sw      $s1,92($s0)
 
#ifdef CONFIG_SMP
#  define GET_SAVED_SP                                   /
                mfc0    k0, CP0_CONTEXT;                 /
                lui     k1, %hi(kernelsp);               /
                srl     k0, k0, 23;                      /
               sll     k0, k0, 2;                       /
                addu    k1, k0;                          /
                lw      k1, %lo(kernelsp)(k1);        
 
#else
#  define GET_SAVED_SP                                   /
/*实际上就是k1 = kernelsp, kernelsp保存当前进程的内核栈指针 */
               lui     k1, %hi(kernelsp);               /
               lw      k1, %lo(kernelsp)(k1);           
#endif
 
/*判断当前运行态,设置栈顶sp
  保存寄存器--参数a0-a3:4-7,返回值v0-v1:2-3,25,28,31以及一些控制寄存器,
  */
#define SAVE_SOME                                        /
               .set    push;                            /
               .set    reorder;                         /
               mfc0    k0, CP0_STATUS;                  /
               sll     k0, 3;     /* extract cu0 bit */ /
               .set    noreorder;                       /
               bltz    k0, 8f;                          /
                move   k1, sp;                          /
               .set    reorder;                         /
               /* Called from user mode, new stack. */  /
                GET_SAVED_SP                             /
8:                                                       /
               move    k0, sp;                          /
               subu    sp, k1, PT_SIZE;                 /
               sw      k0, PT_R29(sp);                  /
                sw     $3, PT_R3(sp);                   /
               sw      $0, PT_R0(sp);                  /
               mfc0    v1, CP0_STATUS;                  /
               sw      $2, PT_R2(sp);                   /
               sw      v1, PT_STATUS(sp);               /
               sw      $4, PT_R4(sp);                   /
               mfc0    v1, CP0_CAUSE;                   /
               sw      $5, PT_R5(sp);                   /
               sw      v1, PT_CAUSE(sp);                /
               sw      $6, PT_R6(sp);                   /
               mfc0    v1, CP0_EPC;                     /
               sw      $7, PT_R7(sp);                   /
               sw      v1, PT_EPC(sp);                  /
               sw      $25, PT_R25(sp);                 /
               sw      $28, PT_R28(sp);                 /
               sw      $31, PT_R31(sp);                 /
               ori     $28, sp, 0x1fff;                 /
               xori    $28, 0x1fff;                     /
               .set    pop
 
#define SAVE_ALL                                         /
               SAVE_SOME;                               /
               SAVE_AT;                                 /
               SAVE_TEMP;                               /
               SAVE_STATIC
 
#define RESTORE_AT                                       /
               .set    push;                            /
               .set    noat;                            /
               lw      $1,  PT_R1(sp);                  /
               .set    pop;
 
#define RESTORE_TEMP                                     /
               lw      $24, PT_LO(sp);                  /
               lw      $8, PT_R8(sp);                   /
               lw      $9, PT_R9(sp);                   /
               mtlo    $24;                             /
               lw      $24, PT_HI(sp);                  /
               lw      $10,PT_R10(sp);                  /
               lw      $11, PT_R11(sp);                 /
               mthi    $24;                             /
               lw      $12, PT_R12(sp);                 /
               lw      $13, PT_R13(sp);                 /
               lw      $14, PT_R14(sp);                 /
               lw      $15, PT_R15(sp);                 /
               lw      $24, PT_R24(sp)
 
#define RESTORE_STATIC                                   /
               lw      $16, PT_R16(sp);                 /
               lw      $17, PT_R17(sp);                 /
               lw      $18, PT_R18(sp);                 /
               lw      $19, PT_R19(sp);                 /
               lw      $20, PT_R20(sp);                 /
               lw      $21, PT_R21(sp);                 /
               lw      $22, PT_R22(sp);                 /
               lw      $23, PT_R23(sp);                 /
               lw      $30, PT_R30(sp)
 
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
#define RESTORE_SOME                                     /
               .set    push;                            /
               .set    reorder;                         /
               mfc0    t0, CP0_STATUS;                  /
               .set    pop;                             /
               ori     t0, 0x1f;                        /
               xori    t0, 0x1f;                        /
               mtc0    t0, CP0_STATUS;                  /
               li      v1, 0xff00;                      /
               and     t0, v1;                         /
               lw      v0, PT_STATUS(sp);               /
               nor     v1, $0, v1;                     /
               and     v0, v1;                         /
               or      v0, t0;                         /
               mtc0    v0, CP0_STATUS;                  /
               lw      $31, PT_R31(sp);                 /
               lw      $28, PT_R28(sp);                 /
               lw      $25, PT_R25(sp);                 /
               lw      $7,  PT_R7(sp);                  /
               lw      $6,  PT_R6(sp);                  /
               lw      $5,  PT_R5(sp);                  /
               lw      $4,  PT_R4(sp);                  /
               lw      $3,  PT_R3(sp);                  /
               lw      $2,  PT_R2(sp)
 
#define RESTORE_SP_AND_RET                               /
               .set    push;                           /
               .set    noreorder;                      /
               lw      k0, PT_EPC(sp);                  /
               lw      sp,  PT_R29(sp);                 /
               jr      k0;                              /
                rfe;                                  /
                ^^^^^
/* 异常返回时,把控制转移到用户代码和把模式从内核态改为用户态要同时完成
   如果前者先完成,用户态指令有机会以内核态运行导致安全漏洞;
   反之则会由于用户态下不能修改状态而导致异常
   r3000以前使用rfe(restore from exception)指令,这个指令把status寄存器
   状态位修改回异常发生前的状态(利用硬件的一个小堆栈),但不做跳转.我们使用一个
   技巧来完成要求:在一个跳转指令的delay slot中放rte.因为delay slot的指令
   是一定会做的,跳转完成时,status也恢复了.
   MIPS III(r4000)以上的指令集则增加了eret指令来完成整个工作: 它清除
   status寄存器的EXL位并跳转到epc指定的位置.
*/
 
               .set    pop
 
#else
 
#define RESTORE_SOME                                     /
               .set    push;                            /
               .set    reorder;                         /
               mfc0    t0, CP0_STATUS;                  /
               .set    pop;                             /
               ori     t0, 0x1f;                        /
               xori    t0, 0x1f;                        /
               mtc0    t0, CP0_STATUS;                  /
               li      v1, 0xff00;                      /
               and     t0, v1;                         /
               lw      v0, PT_STATUS(sp);               /
               nor     v1, $0, v1;                     /
               and     v0, v1;                         /
               or      v0, t0;                         /
               mtc0    v0, CP0_STATUS;                  /
               lw      v1, PT_EPC(sp);                  /
               mtc0    v1, CP0_EPC;                     /
               lw      $31, PT_R31(sp);                 /
               lw      $28, PT_R28(sp);                 /
               lw      $25, PT_R25(sp);                 /
               lw      $7,  PT_R7(sp);                  /
               lw      $6,  PT_R6(sp);                  /
               lw      $5,  PT_R5(sp);                  /
               lw      $4,  PT_R4(sp);                  /
               lw      $3,  PT_R3(sp);                  /
               lw      $2,  PT_R2(sp)
 
#define RESTORE_SP_AND_RET                               /
               lw      sp,  PT_R29(sp);                 /
               .set    mips3;                          /
               eret;                                  /
               .set    mips0
 
#endif
 
#define RESTORE_SP                                       /
               lw      sp,  PT_R29(sp);                 /
 
#define RESTORE_ALL                                      /
               RESTORE_SOME;                            /
               RESTORE_AT;                              /
               RESTORE_TEMP;                            /
               RESTORE_STATIC;                          /
               RESTORE_SP
 
#define RESTORE_ALL_AND_RET                              /
               RESTORE_SOME;                            /
               RESTORE_AT;                              /
               RESTORE_TEMP;                            /
               RESTORE_STATIC;                          /
               RESTORE_SP_AND_RET
 
 
/*
 * Move to kernel mode and disable interrupts.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
#define CLI                                             /
               mfc0    t0,CP0_STATUS;                  /
               li      t1,ST0_CU0|0x1f;                /
               or      t0,t1;                          /
               xori    t0,0x1f;                        /
               mtc0    t0,CP0_STATUS
 
/*
 * Move to kernel mode and enable interrupts.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
#define STI                                             /
               mfc0    t0,CP0_STATUS;                  /
               li      t1,ST0_CU0|0x1f;                /
               or      t0,t1;                          /
               xori    t0,0x1e;                        /
               mtc0    t0,CP0_STATUS
 
/*
 * Just move to kernel mode and leave interrupts as they are.
 * Set cp0 enable bit as sign that we're running on the kernel stack
 */
#define KMODE                                           /
               mfc0    t0,CP0_STATUS;                  /
               li      t1,ST0_CU0|0x1e;                /
               or      t0,t1;                          /
               xori    t0,0x1e;                        /
               mtc0    t0,CP0_STATUS
 
#endif /* __ASM_STACKFRAME_H */
计算机体系结构基础——1 从 CPU 架构说起 引言 CPU 是整个计算机体系结构的核心,体系结构研究 CPU 内部的结构,CPU 如何与内存,外设交互,如何支撑并配合操作系统。 资料主要来源: 《Linux 内核完全剖析–基于0.12内核》/ 赵炯 1 著. ——机械工业出版社,2010.1 《计算机体系结构》/ 胡伟武等著. ——北京:清华大学出版社,2011.6 其他资料参见篇后附录链接 三种 CPU 架构的介... 阅读详情

相关推荐

深入解析MIPS指令集:从RISC设计哲学到汇编编程实践

指令集是处理器能理解的底层语言,它定义了硬件与软件交互的基本规则。精简指令集计算机(RISC)设计哲学强调指令格式规整、执行周期固定,以简化硬件设计并提升流水线效率。MIPS作为RISC的经典代表,其加载-存储架构、规整的指令格式和固定的32位长度,为深入理解计算机体系结构提供了绝佳范例。掌握MIPS指令集,不仅能提升底层编程能力,更是理解现代处理器流水线、缓存机制和异常处理等核心概念的基础。本文聚焦MIPS指令集的四大核心部件——运算指令、访存指令、分支跳转指令和协处理器0指令,通过剖析其设计原理和实际编

weixin_30394669的博客 432

研读 <<mips体系结构透视 >>

>

keep moving 1022

深入解析MIPS指令集:从RISC设计哲学到汇编编程实战

在计算机体系结构中,指令集是CPU执行操作的命令集合,是硬件与软件交互的核心接口。其设计哲学深刻影响着处理器的性能、功耗与复杂度。RISC(精简指令集计算机)作为一种主流设计理念,强调指令格式规整、功能单一,通过简化硬件逻辑来提升执行效率与流水线吞吐率。这一理念在嵌入式系统、网络设备等领域具有极高的技术价值,为实现高性能、低功耗的计算提供了基础。MIPS架构是RISC理念的经典实践与先驱,其清晰规整的指令格式,特别是固定的32位长度与载入-存储架构,为理解CPU工作原理和进行底层系统编程提供了绝佳范本。本文

weixin_34050519的博客 390

mips汇编之利用syscall输出结果

彻底搞懂:mips汇编之利用syscall输出结果

你的问题在于,读书太少而想得太多。 8602

MIPS体系结构透视(see MIPS run)(英文版PDF+中文版PDF)

MIPS体系结构透视(see MIPS run)(英文版PDF+中文版PDF)

矿卡CMP 170HX的AI推理性能优化实战

GPU计算在现代AI推理中扮演着核心角色,其并行计算架构特别适合处理神经网络的大规模矩阵运算。通过CUDA指令集优化和计算管线重构,可以显著提升硬件利用率,这在边缘计算和带宽敏感型任务中尤为重要。以NVIDIA CMP 170HX矿卡为例,通过禁用FMA指令和框架适配优化,其FP32性能可提升15.9倍,在Qwen2.5-1.5B模型的4-bit量化推理中达到A100同架构78%的解码速度。这种优化技术不仅让淘汰矿卡重获新生,更为边缘AI部署提供了高性价比解决方案,特别适合7B以下量化模型部署和多路视频分析

weixin_30432579的博客 634

MIPS初见

最近的MIPS感觉都是照猫画虎,写一篇做个笔记没准还能想明白点新东西,不知道咋用一定要经常打开指令集,这里MIPS指令集。 输入输出 重要的是这个syscall指令的用法,详见MIPS汇编语言syscall指令的用法。 因此在输入输出相应的类型时,要发出对应的指令,将常用的输入输出写在这备忘: 字符串 输出 .data str: .asciiz"Hello Wolrd" .text la $a0,str li $v0,4 syscall 参照上面的样例,我们就大致清楚了怎么对字符串进

zhousiyuan0515的博客 2688

altium room 布局_ALtium 16相同重复模块PCB布局,复制布局走线

自己做了实际工程以后发现PCB器件名字后缀太长了,所以文章最后写了一下后缀的调整方法。第一种方法:1、建立子原理图如下,文件名CANM 2、之后新建一个顶层文件,文件名TOP,之后design—create sheet symbol form sheet or hdl。选择CANM,并放置到TOP中,如下 3、由于我们要多次调用CANM所以使用repeat命令修改如下: 4、之后根据自己的定义,连...

weixin_39609573的博客 5752

存储管理结构 mips 代码分析 linux,MIPS体系结构剖析,编程与实践【6】

第6章MIPS-Linux Kernel分析(2)上次说道SAVE_ALL里有些玄机,这里把include/asm-mips/stackframe.h对着注解一下,希望能说清楚一些.(因为时间关系,我写的文档将主要以这种文件注解为主,加上我认为有用的背景知识或者分析.)/*一些背景知识一.mips汇编有个约定(后来也有些变化,我们不管,o32,n32),32个通用寄存器不是一视同仁的,而是分成下列...

weixin_36280540的博客 452

使用KITTI数据集测试不同算法的性能

该文章将使用同一个kitti数据集来测试不同算法的性能,目前已经测试的算法包括:LIO-SAM,FAST-LIO2,Point-LIO,Faster-LIO。

wwtx的博客 2586

安卓设备安全相关技术

当前安卓设备使用的加密方案是基于Soc中一块可写入的rom实现,称为熔丝,其结果不可逆。 1、secureboot 2、AVB(Android Verify Boot) 3、dm-verity(device mapper) 4、keymaster 5、crypto 6、rpmb(replay private memory block) 7、TEE(Trust execute environment) 8、SELinux .........

weixin_43797328的博客 4839

MIPS体系结构剖析,编程与实践[1]

http://blogold.chinaunix.net/u1/40363/showart_434186.html第一章 MIPS CPU 体系结构概述<br /><br />陈怀临<br /><br />1。序言<br /><br />本文介绍MIPS体系结构,着重于其寄存器约定,MMU及存储管理,异常和中断处理等等。<br /><br />通过本文,希望能提供一个基本的轮廓概念给对MIPS CPU及之上OS有兴趣的读者。<br /><br />并能开始阅读更详细的归约(SPECIFICATION)资料。

ivan240的专栏 1652

数字电路实验避坑指南:如何正确搭建主从JK触发器测试电路(附Proteus仿真)

本文详细解析了主从JK触发器的工作原理及实验搭建指南,重点解决了常见的Catching Problem现象,并提供了Proteus仿真优化方案。通过元器件选型、电路连接步骤和常见错误排查,帮助读者正确搭建测试电路,确保数字电路实验的稳定性和可靠性。

weixin_30790841的博客 470

MIPS体系结构剖析,编程与实践[2]

http://blogold.chinaunix.net/u1/40363/showart_434187.html第二章 寄存器约定<br /><br />对于在一个CPU上进行开发,掌握其工作的CPU的寄存器约定是非常重要的。<br /><br />MIPS体系结构提供了32个GPR(GENERAL PURPOSE REGISTER)。这32个寄存器的用法大致如下:<br /><br />REGISTER NAME USAGE <br />$0 $zero 常量0(constant value 0) <b

ivan240的专栏 1077

【unity实战】Unity手搓脚本工具实现合并网格功能

本文介绍了在Unity中优化网格性能的方法,通过合并重复网格减少绘制调用。主要使用Mesh.CombineMeshes方法实现网格合并,支持统一材质和多材质处理。核心内容包括:1)基础合并脚本实现,将子网格合并到父对象并禁用原网格;2)统一材质设置,支持自定义或默认材质;3)多材质合并方案,通过设置mergeSubMeshes=false保留子网格材质索引。文章还提供了完整代码示例和操作演示,适用于实际项目中的网格优化需求。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 560

【AN7581】AN7581 SDK编译环境搭建操作说明

安装编译需要的工具包。

wgl307293845的博客 338

MIPS体系结构剖析,编程与实践[5]

http://blogold.chinaunix.net/u1/40363/showart_434191.html第五章 Mips kernel Introduction<!--[if !supportEmptyParas]--> <!--[endif]-->1.硬件知识 * CPU 手册: http://www.mips.com等. * 主板资料,找你的卖家. * 背景知识:如PCI协议,中断概念等.<!--[if !supportEmptyParas]--> <!--[endif]-->2.软件资源<!

ivan240的专栏 1884

华为OD新系统机试真题 - 失灵的键盘(C/C++/Py/Java/Js/Go)

华为OD新系统机试真题 【失灵的键盘】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD4月15号机试真题【失灵的键盘】

qq_45776114的博客 1071

MIPS体系结构剖析,编程与实践[4]

http://blogold.chinaunix.net/u1/40363/showart_434190.html第四章 MIPS 异常和中断处理(Exception and Interrupt handling) <br /><br />任何一个CPU都要提供一个详细的异常和中断处理机制。一个软件系统,如操作系统,就是一个时序逻辑系统,通过时钟,外部事件来驱动整个预先定义好的逻辑行为。这也是为什么当写一个操作系统时如何定义时间的计算是非常重要的原因。<br /><br />大家都非常清楚UNIX提供了一整

ivan240的专栏 1614

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

MIPS体系结构剖析,编程与实践 [7]

http://blogold.chinaunix.net/u1/40363/showart_434193.html第七章 MIPS-Linux Kernel 分析(3)<br />下面是我在为godson CPU的页面可执行保护功能增加内核支持时分析linux-mipsmmu实现的一些笔记,没有时间整理,有兴趣就看看吧.也许第5节对整个工作过程的分析会有些用,其它语焉不详的东西多数只是对我本人有点用.   首先的,关键的,要明白MIPS CPU的tlb是软件管理的,cache也不是透明的,具体的   参见它

ivan240的专栏 1610

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

MIPS体系结构剖析,编程与实践

第一章 MIPS CPU 体系结构概述 陈怀临先生 1。序言 本文介绍MIPS体系结构,着重于其寄存器约定,MMU及存储管理,异常和中断处理等等。 通过本文,希望能提供一个基本的轮廓概念给对MIPS CPU及之上OS有兴趣的读者。 并能开始阅读更详细的归约(SPECIFICATION)资料。 MIPS是最早的,最成功的RISC(Reduced Instruction Set Compu

Rain的专栏 4482

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

MIPS体系结构剖析,编程与实践[3]

http://blogold.chinaunix.net/u1/40363/showart_434188.html第三章 MMU和 Memory Management <br /><br />对于MIPS的MMU和Memory Management, the first and yet important one we need <br />always <br />keep in mind is: No real-mode <br /><br />没有实模式。这一点是MIPS CPU 的一个很重要的特点(

ivan240的专栏 1130

MIPS架构的32个寄存器:设计哲学与工程实践的精妙平衡

MIPS架构的32个通用寄存器设计体现了RISC精简指令集的精髓。其核心特性包括5位编码寻址、寄存器0硬约束只读($zero)及双命名体系。寄存器按功能分为临时寄存器($t0-$t9)、保存寄存器($s0-$s7)、参数/返回值寄存器($a0-$a3/$v0-$v1)及控制流专用寄存器(如$ra、$sp)。设计上平衡性能与复杂度,32个寄存器通过5位编码优化指令密度,配合ABI规范实现软硬件协同。扩展单元(如HI/LO乘除寄存器)和协处理器(CP0)进一步强化功能。该设计影响深远,RISC-V等现代

小李独爱秋的博客 2064

看明白了一段mips汇编

今天总算看明白了网上一段mips汇编代码,感觉很爽阿,呵呵,只是让大虾见笑了。原文章(包含该代码)在如下网址:http://www.xtrj.org/mips/, 题目是MIPS体系结构剖析,编程与实践(作者:张福新,陈怀临, 2002) C代码如下: ~/ vi Hello.c  "Hello.c" [New file]  /* Example to illustrate mips re

乖乖的专栏 2749

c语言中mips jal指令,看明白了一段mips汇编

正 文看明白了一段mips汇编(2006/4/2915:34)今天总算看明白了网上一段mips汇编代码,感觉很爽阿,呵呵,只是让大虾见笑了。原文章(包含该代码)在如下网址:http://www.xtrj.org/mips/, 题目是MIPS体系结构剖析,编程与实践(作者:张福新,陈怀临, 2002)C代码如下:~/ vi Hello.c"Hello.c" [New file]/* Example...

weixin_42524824的博客 1978
上一篇: MIPS体系结构剖析,编程与实践[5]
下一篇: MIPS体系结构剖析,编程与实践 [7]
ivan240
博客等级 码龄21年 39粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值