Bootstrap

汇编语言的基本指令及基本使用操作

一、立即数

        立即数判断规则:
  1. 如果某个数的数值范围是0~255之间,那么这个数一定是立即数;

  2. 把某个数展开成2进制,这个数的最高位1至最低位1之间的二进制数序列的位数不能超过8位;

  3. 这个数的二进制序列的右边必须为偶数个连续的 0

例:①0x3f4 = 0000 0000 0000 0000 0000 0011 1111 0100

最高位1至最低位1之间的二进制数序列:1111 1101 从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有2个0,所以0x3f4是立即数

②0x132 = 0000 0000 0000 0000 0000 0001 0011 0010

最高位1至最低位1之间的二进制数序列:1001 1001 从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有1个0,不满足第二条,所以0x132不是立即数

为什么最高位1至最低位1之间的二进制数序列的位数不能超过8位?

  • 因为在ARM中将这 12bits 分为 8bit 常数(0~255)和 4bit 循环右移位值(0~15),只有8bit常数位,只能存下8位。

为什么立即数的二进制序列的右边必须为偶数个连续的 0

  • 因为在ARM中将这 12bits 分为 8bit 常数(0~255)和 4bit 循环右移位值(0~15),循环右移位值步进是2,如果是奇数个连续的0,在提取其中的最高位1至最低位1之间的二进制数序列后,移动偶数次无法得到右边奇数个连续0的二进制序列,和立即数的二进制序列不相同。

二、基础汇编指令

1、mov指令

加载立即数到寄存器或转移一个寄存器的值到另外一个寄存器,数字压缩到代码里面

MOV{S}<c> <Rd>, #<const>

eg:mov r0, #2 ;加载立即数2到寄存器r0。

MOV{S}<c> <Rd>, <Rm>

eg:mov r1, r0 ;将r0寄存器的值加载到r1

2、add指令

ADD{S}<c> <Rd>, <Rn>, #<const>

ADDS}<c> <Rd>, <Rn>, <Rm>{, <shift>}

3、sub指令

SUB{S}<c> <Rd>, <Rn>, #<const>

 SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}

4、ldr寄存器加载指令

用于将数据从内存加载到寄存器中,是一条伪指令,将数字放入代码区

LDR{<c>}{<q>} <Rt>, <label> ;

如:ldr r0, =0x2FAB4

ldr指令多用于从ram中将一个32位的字数据传送到目的寄存器中

LDR<c> <Rt>, [<Rn>{, #+/-<imm12>}] 

如:LDR   R0,[R1,#8];将内存地址为R1+8的字数据读入寄存器R0,这里的#8作为12位立即数是可以省略的。

通过r0指向的数将数保存到r1中,此时r0是一个指针

LDR<c> <Rt>, [<Rn>], #+/-<imm12> 

如:ldr r0, [r1], #8 ;将内存地址R1的字数据读入r0,之后r1+8

LDR<c> <Rt>, [<Rn>, #+/-<imm12>]! 

如:LDR   R0,[R1,#8] !;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。

5、bic指定位清零指令

BIC{S}<c> <Rd>, <Rn>, #<const>;

将rn中的字数据const为1的比特清零,把结果放入rd。<const>的反码与<Rn>按位逻辑与

6、orr指定位置位指令:

        ORR{S}<c> <Rd>, <Rn>, #<const>   按位逻辑或

三、指令b,bx,bl的主要区别

b  无条件跳转到指定的标签

bl无条件跳转到指定的标签,并将返回地址保存到链接寄存器(LR,通常是R14)

bx跳转到指定寄存器的地址,并根据地址的最低有效位选择ARM或Thumb状态。

在 ARM 汇编中,SWI(Software Interrupt)指令用于生成软件中断,通常用于请求操作系统服务或调用特定的系统功能。SWI #7 表示生成一个软件中断,传递的参数是 #7。

当执行 SWI #7 时,处理器会跳转到一个预定义的中断处理程序,该程序会根据 #7 的值来执行特定的操作。具体的操作取决于操作系统的实现。例如,在某些系统中,SWI #7 可能被用来请求特定的系统调用,如获取系统时间或处理文件操作。

四、程序状态寄存器

(1)条件码标志

N、Z、C、V,最高4位称为条件码标志。ARM的大多数指令可以条件执行的,即通过检测这些条件码标志来决定程序指令如何执行。

各个条件码的含义如下:

N:在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0。

Z:如果结果为0,则Z=1;如果结果为非零,则Z=0。

C:其设置分一下几种情况:

               对于加法指令(包含比较指令CMN),如果产生进位,则C=1;否则C=0。

               对于减法指令(包括比较指令CMP),如果产生借位,则C=0;否则C=1。

               对于有移位操作的非法指令,C为移位操作中最后移出位的值。

               对于其他指令,C通常不变。

V:对于加减法指令,在操作数和结果是有符号的整数时,如果发生溢出,则V=1;如果无溢出发生,则V=0;对于其他指令,V通常不发生变化。

五、C语言和汇编语言的调用

调用函数时所传递的参数是:r0 r1 r2 r3作为前四个参数;第五个参数以后通过栈来传递。返回值通过r0传递。pop push,

谁调函数,谁保护现场恢复现场

六、三种模式切换及异常处理

	preserve8
	area reset, code, readonly
	code32
	entry

	b start
	ldr pc, =do_undifined
	ldr pc, =do_swi
	ldr pc, =do_p_abort
	ldr pc, =do_d_abort
    nop
	ldr pc, do_irq
	ldr pc, do_fiq
	

do_fiq
	b do_fiq	

do_irq
	import irq_handler
	sub lr, lr, #4
	stmfd sp!, {r0-r12, lr}
	bl  irq_handler
	ldmfd sp!, {r0-r12, pc}^

do_d_abort
	b do_d_abort

do_p_abort
	b do_p_abort

do_swi
	import swi_handler
	stmfd sp!, {r0-r12, lr}	   ;入栈,保护现场
	bl  swi_handler
	ldmfd sp!, {r0-r12, pc}^   ;出栈,恢复现场,并切换回原来的工作模式

do_undifined
	b  do_undifined

start
	ldr sp, =0x40001000 ;svc_sp

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr	r0, r0, #0x12
	bic r0, #(1 << 7)		   ;中断禁止位,禁止irq
	msr cpsr_c, r0

	ldr r0, =0x40001000
	sub r0, r0, #1024
	mov sp, r0

	mrs r0, cpsr               ;读
	bic r0, r0, #0x1F		   ;irq到user模式
	orr r0, r0, #0x10
	msr cpsr_c, r0             ;写

	ldr r0, =0x40001000
	sub r0, r0, #2048
	mov sp, r0
	
	import main
	b main

asm_fn
	export asm_fn
	swi #7
	bx lr

finished
	b finished

	end
extern void asm_fn(void);

void swi_handler(void)
{
	
}

void irq_handler(void)
{
	
}

int main(void)
{
	while(1)
	{
		
	}
	return 0;
}

;