MIPS内联汇编

0X0

近几天使用内联汇编来完成部分功能,下面总结下基础知识点,以便以后查询

语法基本结构

	__asm__ __volatile__(
    "汇编语句\n\t"
	"汇编语句\n\t"
	:输出寄存器
	:输入寄存器
    :寄存器破坏表
	);

‘:’把内联汇编分割为了4个部分

  • 第一部分

    如上的第二、第三行,这里可以填写若干条汇编指令

  • 第二部分

    如上的第四行,在这里对输出寄存器进行描述

  • 第三部分

    如上的第五行,在这里对输入寄存器进行描述

  • 第四部分

    如上的第六行,

如果有输入没有输出第五行的‘:’是必不可少的,是格式的一部分,第六行的‘:’可以省略
如果没有输出和输入的话’:'可以省略

寄存器修饰

修饰说明
=该寄存器只写的
+该寄存器是读写的
&该寄存器不能被再用作输入寄存器
r通用寄存器
f浮点寄存器
moffset为有符号12bit内存地址
ZCoffset为有符号16bit,4字节对齐地址
ZBoffset为0的地址

实例

  • 例1

    	int a=2,b=1,c=0;
    	__asm__ __volatile__(
    	"addu %0, %1, %2\n\t"
    	:"=r"(c)
    	:"r"(a),"r"(b)
    	);
    	printf("%d \n", c);
    

    MIPS 无符号32位加法指令的格式为ADDU rd, rs, rt,计算rs+rt=rd,所以rd是输出寄存器,rs、rt为输出寄存器

    • 第三行使用%+数字来进行占位,然后在第二、第三部分对寄存器进行描述,并与C语言变量关联起来

    • 第四行"=r"( c ) 是对%0的修饰,表示%0 操作数是一个通用寄存器,只写,“写的值放到变量c”

    • 第五行"r"(a),“r”(b),表示%1、%2操作数是通用寄存器,寄存器的值使用变量a、b的值

    对这段代码反汇编:

     ;-- main:
                ;-- section..text:
                ;-- .text:
                ;-- _ftext:
                0x1200008d0      f0ffbd67       daddiu sp, sp, -0x10       ; [11] -r-x section size 608 named .text
                0x1200008d4      0000bcff       sd gp, (sp)
                0x1200008d8      02001c3c       lui gp, 2
                0x1200008dc      c0839c67       daddiu gp, gp, -0x7c40
                0x1200008e0      0800bfff       sd ra, 8(sp)
                0x1200008e4      2de09903       daddu gp, gp, t9
                0x1200008e8      02000524       addiu a1, zero, 2
                0x1200008ec      01000224       addiu v0, zero, 1
                0x1200008f0      2128a200       addu a1, a1, v0
                0x1200008f4      488084df       ld a0, -segment.LOAD0(gp)  ; [0x120010cd8:8]=0x120000000 segment.ehdr
                0x1200008f8      988099df       ld t9, -sym._MIPS_STUBS(gp) ; [0x120010d28:8]=0x120000b30 sym.imp.printf
                0x1200008fc      09f82003       jalr t9
                0x120000900      900b8464       daddiu a0, a0, 0xb90
                0x120000904      0800bfdf       ld ra, 8(sp)
                0x120000908      0000bcdf       ld gp, (sp)
                0x12000090c      25100000       move v0, zero
                0x120000910      0800e003       jr ra
                0x120000914      1000bd67       daddiu sp, sp, 0x10
                0x120000918      00000000       nop
                0x12000091c      00000000       nop
    
    

    可以看到在第11~13行

    addiu a1, zero, 2 把2装到a1寄存器

    addiu v0, zero, 1把1装到v0寄存器

    addu a1, a1, v0把1+2结果放到a1寄存器

  • 例2

    在汇编语句比较多时,再使用%+数字的方式来表示就容易混乱

        int ret = 0;
    	int arg;
        __asm__ __volatile__ (
                "cpucfg %[var], %[index]"
                :[var]"=r"(ret)
                :[index]"r"(arg)
                :
        );
    

    使用%[]来占位,中括号中可以填一个字符串

    这样在汇编语句多时要方便些

  • 例3

    在遇到某些汇编指令编译器不支持时可以使用二进制编码

    	int a=0;
    	__asm__ __volatile__(
    	".insn \n\t"
    	".word (0b1011100100000110010010000100) \n\t"
    	:"+r"(a)
    	:
    	);	
    

在C语言定义变量时也可以指定变量放在那个寄存器,如下

register int a asm("$4") = 2;

定义了一个int类型的变量,值为2,并使用的是$4寄存器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值