Linux内核完全注释(基于Linux0.11)_笔记_/linux/kernel/asm.s

本文详细介绍了汇编程序中处理CPU异常及故障的底层代码,包括不同类型的中断处理流程及堆栈变化。通过具体示例代码,展示了如何针对特定错误进行处理并返回正常执行路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作用

asm.s汇编程序中包括大部分CPU探测到的异常故障处理的底层代码,也包括数学系处理器的异常处理
该程序的主要处理方式是在中断处理程序中调用traps.c中的C函数程序,显示出错位置和出错号,然后退出中断

说明

不带出错号的中断过程堆栈变化

带出错号的中断过程堆栈变化

补充

若对代码有疑惑,可结合上面展示的两幅图对代码进行解读

代码解析

# 全局符号定义,此处定义的是外部可调用的汇编函数
.globl divide_error,debug,nmi,int3,overflow,bounds,invalid_op
.globl double_fault,coprocessor_segment_overrun
.globl invalid_TSS,segment_not_present,stack_segment
.globl general_protection,coprocessor_error,irq13,reserved

# 除数为0引起的中断如下
divide_error:
	# 压入函数入口点
	pushl $do_divide_error

# 无出错号的通用处理过程
no_error_code:
	# 交换ax与堆栈顶部的值
	# 等价于将ax压入栈中,同时弹出顶部的值给ax
	# 上述操作需要一个中间变量,所以使用xchgl直接交换
	xchgl %eax,(%esp)
	pushl %ebx
	pushl %ecx
	pushl %edx
	pushl %edi
	pushl %esi
	pushl %ebp
	push %ds
	push %es
	push %fs

	# 寄存器保存完毕,调用ax所指向的函数
	pushl $0		# "error code"
	lea 44(%esp),%edx
	pushl %edx
	movl $0x10,%edx
	mov %dx,%ds
	mov %dx,%es
	mov %dx,%fs
	call *%eax

	# 恢复堆栈指针
	addl $8,%esp

	# 恢复压入的寄存器值
	pop %fs
	pop %es
	pop %ds
	popl %ebp
	popl %esi
	popl %edi
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax

	# 中断返回
	iret

# 调试中断入口
debug:
	pushl $do_int3		# _do_debug
	jmp no_error_code

# 非屏蔽中断调用入口点
nmi:
	pushl $do_nmi
	jmp no_error_code

# 断点指令引起中断的入口点
int3:
	pushl $do_int3
	jmp no_error_code

# 溢出出错处理中断的入口点
overflow:
	pushl $do_overflow
	jmp no_error_code

# 边界检查出错中断的入口点
bounds:
	pushl $do_bounds
	jmp no_error_code

# 无效操作指令出错中断的入口点
invalid_op:
	pushl $do_invalid_op
	jmp no_error_code

# 协处理器段超出出错中断的入口点
coprocessor_segment_overrun:
	pushl $do_coprocessor_segment_overrun
	jmp no_error_code

# Intel保留中断的入口点
reserved:
	pushl $do_reserved
	jmp no_error_code

# Linux设置的数学协处理器硬件中断
irq13:
	pushl %eax
	xorb %al,%al
	outb %al,$0xF0
	movb $0x20,%al
	outb %al,$0x20
	jmp 1f
1:	jmp 1f
1:	outb %al,$0xA0
	popl %eax
	jmp coprocessor_error

# 两处错出故障
double_fault:
	# 压入函数入口地址
	pushl $do_double_fault

# 有出错号的通用处理过程
error_code:
	# 交换eax与esp+4
	xchgl %eax,4(%esp)		# error code <-> %eax

	# 交换ebx与esp
	xchgl %ebx,(%esp)		# &function <-> %ebx

	# 保存其余寄存器
	pushl %ecx
	pushl %edx
	pushl %edi
	pushl %esi
	pushl %ebp
	push %ds
	push %es
	push %fs

	# 寄存器保存完毕,调用bx指向的函数
	pushl %eax			# error code
	lea 44(%esp),%eax		# offset
	pushl %eax
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	call *%ebx

	# 恢复堆栈指针
	addl $8,%esp

	# 恢复所有的寄存器
	pop %fs
	pop %es
	pop %ds
	popl %ebp
	popl %esi
	popl %edi
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax

	# 中断返回
	iret

# 无效任务状态段
invalid_TSS:
	pushl $do_invalid_TSS
	jmp error_code

# 段不存在
segment_not_present:
	pushl $do_segment_not_present
	jmp error_code

# 堆栈段出错
stack_segment:
	pushl $do_stack_segment
	jmp error_code

# 一般性保护出错
general_protection:
	pushl $do_general_protection
	jmp error_code
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值