如何通过idt找到中断处理应用程序无法找到入口入口地址

linux中断--中断原理分析
有一种朋友不在生活里,却在生命力;有一种陪伴不在身边,却在心间。图老师即在大家的生活中又在身边。这么贴心的服务你感受到了吗?话不多说下面就和大家分享linux中断--中断原理分析吧。
linux中断--中断原理分析&  中断之原理篇  前言:  中断是计算机发展中一个重要的技术,它的出现很大程度上解放了CPU,提高了CPU的执行效率。  在中断出现之前,CPU对IO采用的是轮询的方式进行服务,这使的CPU纠结在某一个IO上,一直在等待它的响应,如果它不响应,CPU就在原地一直的等下去。这样就导致了其他IO口也在等待CPU的服务,如果某个IO出现了important
or emergency affairs,CPU也抽不出身去响应这个IO。  为了解决这个纠结的问题就------出现了中断  中断控制的主要优点是只有在IO接口需要服务时才去响应它,使得CPU很淡定的做它自己的事情,只有IO口有需求的时候才去响应它。同时中断中也设计了中断优先级,来处理一些很紧急的事件。  一.中断的基本知识  1.中断的概念:  所谓中断,是指CPU在正常运行程序时,由于程序的预先安排或内外部事件,引起CPU中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源。  其实从物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如
8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,处理器会通知
OS 已经产生中断。这样,OS
就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。  2.那么当产生一个中断时,CPU是如何识别的呢?  在Intel X86中可以支持256中向量中断,为了使处理器能使别每种中断源,给它们进行了编号-----叫做中断向量  3.这些中断向量在Linux中是如何分配的:  编号0~31的向量对应于异常和非屏蔽中断(这类也属于向量中断或者内部中断,向量中断的特性就是一一映射,一个中断向量对应一个中断处理例程)  编号32~47的向量(即由IO设备引起的中断)分配给屏蔽中断。(这类也属于非向量中断或者外部中断,在Intel手册中常说的就是这类中断。非向量中断的特性在下文就可以体现出来。)  编号48~255的向量用来标示软中断。Linux用其中的128或0x80来实现系统调用(所以通过系统调用来进入内核空间都需要通过128中断操作)  非屏蔽中断的向量和异常的向量是固定的。  4.异常和中断的区别:  1异常:是指CPU内部出现的中断,即在CPU执行特定指令时出现的非法情况。同时异常也称为同步中断,因此只有在一条指令执行后才会发出中断
,不可能在指令执行期间发生异常。  a.产生的原因:  程序的错误产生的(eg:除数为0)  内核必须处理的异常条件产生的(eg:缺页)  b.异常又分为故障和陷阱,它们都不使用中断控制器,也不能被屏蔽  C.X86处理处理器中大约有20中异常。Linux内核必须为每种异常提供一个专门的异常处理程序。  2中断:也称为异步中断。因此它是由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能在指令之间发生。  a.中断又分为外部可屏蔽中断(INTR)和外部非屏蔽中断(NMI)  所用I0设备产生的中断请求均引起可屏蔽中断  硬件故障引起的故障则产生非屏蔽中断。  John说明:  在CPU执行一个异常处理程序时,就不再响应其他异常和中断请求服务.那么如果此时发生了一个异常,CPU不能去响应它,又不能把它的信息丢失该怎么办呢?  这是就用到了堆栈,把所有的信息压入栈。等当前异常处理后,才从堆栈中取出信息再响应刚才的异常。(当产生多个非屏蔽中断时,CPU的处理方法同上)  二APIC和8259A  中断的实现也需要硬件上的支持的,那么硬件上是如何支持中断的?  1.在X86计算机的 CPU 为中断只提供了两条外接引脚:NMI 和 INTR。  NMI 是不可屏蔽中断,它通常用于电源掉电和物理存储器奇偶校验;  INTR是可屏蔽中断,可以通过设置中断屏蔽位来进行中断屏蔽,它主要用于接受外部硬件的中断信号,这些信号由中断控制器传递给 CPU。  2.中断控制器  目前常见的中断控制器有可编程中断控制器8259A和高级可编程中断控制器(APIC)  18259A  PIC(Programmable Interrupt Controller)是由两片 8259A
的外部芯片以级联的方式连接在一起。每个芯片可处理多达 8 个不同的 IRQ(中断请求线)。因为从 PIC 的 INT 输出线连接到主 PIC 的 IRQ2
引脚,所以可用 IRQ 线的个数达到 15 个。  我们来看一个图:(进行看图说明)  a.第一级8259A是主中断控制器,它的第二个中断请求输入端与第二级8259A的中断输出端INT相连。  b.与中断控制器相连的每条线叫做中断线。要使用中断线,就要进行中断线的申请,即IRQ。  那么这条线的名字是啥勒----》中断号。  IRQ线是从0开始顺序编号的,所以第一条IRQ线就是IRQ0。  C.那么该中断号于我们上面所说的中断向量有什么关系呢  中断向量=中断号+32。  从此等式可以看出,第一个中断线(IR0)所对应的中中断向量是32.  由此可以得出:  (1)异常和非屏蔽向量是CPU 内部引起的中断  (2)向量32-47对应的是外部中断。  d.并不是每个设备都可以向中断线上发中断信号,只有对某一条确定的中断线拥有了控制权后,才可以向这条中断线上发送信号。  e.8259A中还有一个很重要的寄存器-8位的中断屏蔽寄存器-这个寄存器的作用是屏蔽中断。  8位的中断屏蔽寄存每一位对应8259A中的一条中断线,如果要禁用某条中断线,则把中断屏蔽寄存器的相应位置1,要启用则置0。  (PS:看到这里就可以明白,需要用到中断控制器的中断都是外部中断,也就是可屏蔽中断。每个IRQ对应一个中断向量。但是并不是每一个中断向量都可以对应一个IRQ)  John哥说明:  屏蔽中断也可以从CPU的角度考虑,即清除eflag的中断标志位(IF),当IF位为0时禁止任何外部IO的中断请求,即关中断;  f.共享中断(一个很重要的概念,后面程序中会涉及到它)  由于计算机的外部设备越来越多,所以15条中断线已经不够用了。中断线是很宝贵的资源,为了更好的利用它,只有当设备需要中断的时候才申请占用一个IRQ,并且为了让更多的设备使用中断采取了在申请IRQ时采用共享中断的方式。  (PS:由于外部设备多,多个设备可以对应同一个IRQ,也就是对应同一个中断向量,一个中断向量对应一个中断处理程序,但是一个中断处理程序可能对应很多中断服务例程)  2高级可编程中断控制器(APIC)  先看图再说:  1.8259A 只适合单 CPU 的情况,为了充分挖掘 SMP 体系结构的并行性,能够把中断传递给系统中的每个 CPU
至关重要。基于此理由,Intel 引入了一种名为 I/O 高级可编程控制器的新组件,来替代老式的 8259A
可编程中断控制器。该组件包含两大组成部分:一是本地
APIC,主要负责传递中断信号到指定的处理器;举例来说,一台具有三个处理器的机器,则它必须相对的要有三个本地 APIC。另外一个重要的部分是 I/O
APIC,主要是收集来自 I/O 装置的 Interrupt 信号且在当那些装置需要中断时发送信号到本地 APIC(相当于一个路由的功能),系统中最多可拥有 8
个 I/O APIC。  2.每个本地 APIC 都有 32 位的寄存器,一个内部时钟,一个本地定时设备以及为本地中断保留的两条额外的 IRQ 线 LINT0 和
LINT1。所有本地 APIC 都连接到 I/O APIC,形成一个多级 APIC 系统。  那么我们如何知道我们机子上使用的是那种中断控制器呢?  我们可以通过在终端出入命令:cat /proc/interrupts来查看  a.若看到列表中有IO-APIC,说明您的系统正在使用 APIC。  若看到 XT-PIC,意味着您的系统正在使用 8259A 芯片。  16位实地址模式的中断机制和32位保护模式的中断机制的最本质差别就是在保护模式下引入了中断描述表  在单处理器的系统中,第一列是中断号,第二列是CPU产生该中断的次数。最后一列是于这个中断相关的俄设备名字。这个名字是通过参数devname提供给函数request_irq()(下篇文章会对它讲解)  三.中断描述表  1.为什么引入  在实地址模式中,CPU把内存中从0开始的1kb空间作为一个中断向量表。表中的每个表项占四个字节,由两个字节的段地址和两个字节的偏移量组成,这样构成的地址就是相应中断处理程序的入口地址。  但是在保护模式下,由4个字节的表项构成的中断向量表已经不能满足要求了。在保护模式下,中断向量表中的表项由8个字节组成。此时他也有了新的名字----中断描述表(Interrupt
Descriptor
Table,IDT)(PS:总共有256个描述符,每个描述符8字节,256*8就是中断描述符占用的字节空间),其中的每个表项叫做一个门描述符(great
descriptor)(在中断系列的其他文章中有很详细的介绍各种门描述符,系统所有的中断都需要经过这些门)  先来看图在说明:  1DPL:段描述符的特权级  2偏移量:入口函数地址的偏移量  3P:表示段是否在内存中的标志  4段选择符:入口函数所处代码段的选择符  5D:标志位,1表示32位,0标示16位  6xxx:3位门类型码  门类型符主要分为  a.中断门(interrupt gate):其类型码为110,中断门包含了一个中断或异常处理程序所在段的选择符和段内偏移量。  当控制权通过中断门进入中断处理程序时,处理器清IF标志即关中断这样就避免了中断嵌套的发生。  中断门中的DPL(请求特权级)为0,因此用户态中的进程不能访问中断门。所用的中断处理程序都由中断门激活,并全部限制在内核态。(进入中断就需要进入中断门)  b..陷阱门(tap gate)其类型码为111。它与中断门类似,唯一的区别是控制权通过陷阱门进入处理程序时保持IF标志位不变,即不关中断。  c.系统门(system gate):Linux内核特别设置的,用来让用户态的进程访问Intel的陷阱门。  系统门的DPL为3。系统调用就是通过系统门进入内核的。  2.在保护模式下,中断描述符表在内存的位置不再局限于从地址0开始的位置,而是可以放在内存的任何位置。  1为了实现这个功能---CPU中设计了一个中断描述符表寄存器IDTR,用来存放中断描述符表在内存的起始位置。  2中断描述表寄存器(IDTR)是一个48位的寄存器。它的低16为保存中断描述符表的大小,高32位保存中断描述表的基址。  3看下图:  中断向量是中断向量表(IDT)的索引,而中断向量表存在于内存的某个位置,由Intel的寄存器IDTR负责记录其基址(线性地址)和大小。IDT表中包含了操作系统中注册的外部IO中断的处理程序的入口地址,以及其他操作系统实现的架构相关的中断和异常的处理函数入口地址(这些地址又存放在所谓的gate
destribtor中)。INTR和IDT的关系如下图所示:  我们知道了中断描述表的功能和基本设置后,那么系统是是在何时给它初始化以及是如何给它初始化的呢?  首先Linux内核在系统的初始化阶段对中断进行初始化,其中包括有:初始化可编程控制器8259A;将中断描述符表的起始地址装入IDTR中,并初始化表中的每一项。  (PS:首先通过IDTR找到中断描述符表,然后通过IDT再找中断处理程序的入口地址)  3.中断的初始化  1用户进程可以通过INT指令发出一个中断请求,其中断请求向量在0~255之间。  那么如何防止用户使用INT指令模拟非法的中断和异常?  此时DPL就起作用了-将DPL置为0就可以了。  2但是,有时候必须让用户进程能够使用内核所提供的功能(比如系统调用)也就是从用户态进入内核态,此时就可以通过把中断门或陷阱门的DPL置为3来实现。  3当计算机在实模式时,中断描述符表被初始化,并由BIOS使用。  but,在进入了Linux内核时,中断描述符表就被移到内存的另一个区域,并为进入保护模式进行预初始化:  用汇编指令LIDT对中断描述符表寄存器IDTR进行初始化,即把IDTR置为0,然后把中断描述符表IDT的起始地址装入IDTR。  4中断描述表的初始化  a.第一次初始化:用setup_idt()函数填充中断描述符表中的256个表项,填充时使用一个空的中断处理程序。因为现在还是在初始化阶段,还没有任何中断处理程序,因此,用这个空的中断处理程序来填充每个表项。  b.第二此初始化:内核在启用分页功能后对IDT进行第二次初始化。  此时,使用实际的陷阱和中断处理程序替换这个空的处理程序。一旦这个过程完成后,对于每个异常,IDT都包含一个专门的陷阱门或系统门,而对每个外部中断,IDT都包含专门的中断门。  上面提到了对IDT的初始化,那么我们就递归深入下来看看系统是如何对IDT表项进行设置的  4.IDT表项的设置  IDT表项的设置是通过_set_gate()函数来实现的。  1插入一个中断门  调用 set_intr_gate(n,addr)函数来实现  此函数的功能是在IDT的第n个表项插入一个中断门。门中的段选择符设置成内核代码的段选择符,偏移量设置为中断处理程序的地址addr,DPL字段设置为0.  分析下的形参:  n:表示在第几个表项中插入一个中断门。  addr:表示偏移量,此处偏移量设置为中断处理程序的地址addr.  现在我们迭代深入,看下它的内部是如何实现的  [cpp] view plaincopy  330static inline void set_intr_gate(unsigned int n, void *addr) 331{  332 BUG_ON((unsigned)n
0xFF); 333 _set_gate(n, GATE_INTERRUPT, addr,
0, 0, __KERNEL_CS);  334}[c-sharp] view plaincopy  19#if (_MIPS_ISA
_MIPS_ISA_MIPS1) 20  21static inline void __BUG_ON(unsigned long condition) 22{  23 if (__builtin_constant_p(condition)) { 24 if (condition)  25 BUG(); 26 else  27 28 }  29 __asm__ __volatile__(&tne $0, %0, %1& 30 : : &r& (condition), &i&
(BRK_BUG));  31} 32  33#define BUG_ON(C) __BUG_ON((unsigned long)(C)) 34  (1)我们可以看到BUG_ON()函数是一函数宏,系统最终调用的是__BUG_ON((unsigned long)(C))
第五个形参表示IST(Interrupt Stack Table)共 3 位,表达 IST1 - IST7 共 7 个 Stack
pointer[c-sharp] view plaincopy  371static inline void set_trap_gate(unsigned int n, void *addr) 372{  373 BUG_ON((unsigned)n
0xFF); 374 _set_gate(n, GATE_TRAP, addr, 0, 0,
__KERNEL_CS);  375} [c-sharp] view plaincopy  365static inline void set_system_trap_gate(unsigned int n, void *addr)
366{  367 BUG_ON((unsigned)n
0xFF); 368 _set_gate(n, GATE_TRAP, addr, 0x3,
0, __KERNEL_CS);  369} 370& 搜索“图老师”或者“tulaoshi_com”加关注,每天最新的美食、健康、育儿、美妆、、手工DIY等生活小技巧,30天变身小巧妇!【微信扫描下图可直接关注】
来源:/n/1626.html
与Linux设备驱动中中断处理相关的首先是申请与释放IRQ的API: request_irq()和free_irq()。 request_irq()的原型为: int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags,const char * devname, void *dev_id); irq是要申请的硬件...
目前对早泄的治疗 早泄治疗的主要目的是提高对射精的控制能力。射精控制能力的提高与夫妻性生活的满意度有关,而且射精时间过短也能造成个人压力和夫妻间交流的障碍。许多男性可以通过自我帮助的方法来延缓射精。但是另一些人可能需要专业人士的帮助。首先要和自己的伴侣探讨这个问题,知道她们的需要和愿望。一个简单有效的自助疗法是...
下面的程序段可以模拟及中的,就是出现的问话框,让使用者根据自己电脑的情形,来决定要连接的网络磁盘要映射到自己的那一个磁盘?要中断的又是那一个对应的磁盘? 请在声明区中加入以下声明及模组: Private Declare Function WNetConnectionDialog Lib &mpr.dll& _ (ByVal hwnd As Long, ByVal dwType As Long) As ...
解析安装MindManager安装中断问题 & MindManager是一款功能强大,实用性强的思维导图软件,随着用户的不断增加,安装MindManager中出现的问题也难免随着用户范围的增长而显现。其中常见的一项就是安装中断问题,本文就详细的讲解了安装MindManager过程中出现的安装中断问题。 问题描述: The wizard was interrupted bef...
中断性爱或致男性阳痿 不少男士们为了更长时间享受性爱,于是都会选择中断性交的方式。这个方式看上去挺有用,但是男士们你们知道吗,若是长时间如此,将会影响到男性健康,严重的还会导致男性阳痿。具体以下就让我们一起来看看吧! &中断性交&让男士们容易阳痿 从心理上来看,性的欲望不能得到满足。此外,...相关文章推荐
Linux内核---44.关于中断号与中断引脚
8Ox86微处理器发布了大约20种不同的异常,内核必须为每一种异常提供一个异常处理程序。对于某些异常,CPU控制单元在开始执行异常处理程序前会产生一个硬件出错码(hardwar
eerror ...
调度器的一般原理是,根据所能分配的计算能力,向系统中的每个进程提供最大的公平性。调度器分配的资源就是CPU的时间,尽量保证每个进程都获得相同的CPU时间。Linux的CFS调度系统不同于O(1)调度器...
Linux使用CFS调度算法。
CFS算法允许每个进程运行一段时间、循环轮转、选择运行最少的进程作为下一个运行进程。而不再使用分配时间片的做法。
nice值在CFS中作为进程获得处理器运行比的权重...
set_trap_gate(0,&divide_error);
set_intr_gate(1,&debug);
set_intr_gate(2,&nmi);
set_system_int...
1.中断的概念
所谓中断是指CPU对系统发生的某个事件作出的一种反应:CPU暂停正在执行的程序,保留现场后自动地转去执行相应的处理程序,处理完该事件后再返回断点继续执行被“打断”的程序。...
文章出处:http://www./viewthread.php?tid=14&extra=page%3D1
在进入正题之前,我想先把ARM920T的异常向量表(E...
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Linux.中断处理.入口x86平台entry_32.S&在保护模式下处理器是通过中断号和IDTR找到中断处理程序的入口地址的。IDTR存的是一个32位的IDT起始地址和一个16位的IDT长度,理论上IDTR和GDTR一样都能支持8192个中断门(65536字节),但x86只能支持256个中断,所以实际上IDTR的最大有效限长只是2048字节。&在这256个中断中,前0×20个中断号被处理器保留用作陷阱(Trap)、故障(Fault)和终止(Abort)。而第0×80号中断号则被Linux用来提供作为用户层程序陷入内核的系统调用之用。所以实际可用的中断号为0×20~0x7F、0×81~0xFF。Linux内核初始化中断是从init/main.c中的start_kernel调用trap_init和init_IRQ开始的。trap_init&是在arch/x86/kernel/traps.c中定义而init_IRQ是在arch/x86/kernel/irqinit.c中定义的。先来看trap_init很简单,就是初始化前0×20个保留的中断号。&接下来看init_IRQ很简单就是简单地调用了intr_init。而intr_init这个函数是在arch/x86/kernel/x86_init.c中设定的。&我们可以看到intr_init其实就是native_init_IRQ,它是在irqinit.c中定义的。该程序主要做了两件事:一是调用pre_vector_init实际上就是init_ISA_irqs;二是将所有的中断门设为interrupt数组里的函数。&interrupt是在entry_32.S中定义的这里实际是上是生成NR_VECTORS-FIRST_EXTERNAL_VECTOR个函数入口,每个函数都在入口处压入一个中断号,然后jmpcommon_interrupt。init_ISA_irqs是在irqinit.c中定义的,它主要初始化8259芯片为非AEOI模式,并将中断起始向量设为0×20。接着将中断描述符的硬件芯片设为i8259A_chip.其实这里8259的中断号与中断描述符的数组是一一对应的,只不过是0×20号对应irq_desc中的0,依此类推。&现在可以大致总结一下,凡是小于0×20的中断号都由traps.c中的init_trap所初始化的函数接管。而这之后内核将IDT中0×20以后的项的入口都初始化为不同的函数,这些函数都做相同的一件事情就是压入中断号,注意这个中断号是实际的中断号减去0×20得到的逻辑中断号,然后再跳转到common_interrupt中执行真正的中断处理程序。&&详解entry_32.Sinterrupt被定义在arch/x86/kernel/entry_32.S中;下面,我们来详细理解一下entry_32.S中定义interrupt的这段代码:.section&.init.rodata,&a&&&//定义一个段,.init.rodata表示该段可以被读写操作,&a&表示需要为该段分配内存ENTRY(interrupt)&&&&&&&&&&&//定义数据段的入口为interrupt.text&&&&&//是告诉连接器,这部分数据是程序代码&&&&.p2align&5&&&&&//advances&the&locationcounter&until&it&a&multiple&of&32.&If&the&location&counter&is&already&amultiple&of&32,&no&change&is&needed.&//按32字节对齐&&&&&&&&&&&&&&&&&&&&&&///.p2align指定下一行代码的对齐方式,第1参数表示按2的多少次幂字节对齐,第2参数表示对齐是跨越的位置用什么数据来填充,第3字节表示最多允许跨越多少字节。&&&&.p2alignCONFIG_X86_L1_CACHE_SHIFT&&&&&&&&&//如果上一行.p2align&5没有执行,那么执行这一条:按2的CONFIG_X86_L1_CACHE_SHIFT次幂的字节对齐,其中CONFIG_X86_L1_CACHE_SHIFT是在内核配置中设定的ENTRY(irq_entries_start)&&&//代码段的入口定义为irq_entries_start&&&&RING0_INT_FRAME&&&&&&&//宏展开:.macro&RING0_INT_FRAME&&&&&&&&//#can't&unwind&into&user&space&anyway&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFI_STARTPROC&simple&&&#define&CFI_STARTPROC&.cfi_startproc&//用在每个函数的开始,用于初始化一些内部数据结构&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFI_SIGNAL_FRAME&&&&&&//#defineCFI_SIGNAL_FRAME&&&&.cfi_signal_frame;作用和上面一句类似&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFI_DEF_CFA&esp,&3*4&&#define&CFI_DEF_CFA&.cfi_def_cfa&//定义计算CFA的规则&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&/*CFI_OFFSET&cs,&-2*4;*/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFI_OFFSET&eip,&-3*4&&//#define&CFI_OFFSET&.cfi_offset&//xx&reg&,offsetreg中的值保存在offset中,offset是CFA的&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.endmNOTE:通用Flash存储器接口(CFI)是一种由Intel、AMD、Sharp和Fujutsu共同制订的规格,是为了提高由不同的供应商现在或者将来所提&供的Flash器件的互换性的工业行业广大成果之一。CFI使得用户只需要一套驱动程序就可以识别并使用各种类型的Flash产品,因为器件的所有识别信息,诸如存储器大小、字节/字配置、块配置、必须的供电电压和时序信息等,都直接保存在芯片上。vector=FIRST_EXTERNAL_VECTOR&&&//#defineFIRST_EXTERNAL_VECTOR&&&&&&&&0x20&&在irq_verctors.h中,定义了0~31号内部中断.rept(NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7&&&&&&&&&&&&&//.rept表示循环,#define&NR_VECTORS&&&&&&&&&&&&256,为256-32+6=230;230/7=32&&&&.balign32&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//按32字节对齐NOTE:.balign[wl]&abs-expr,&abs-expr,&abs-expr增加位置计数器(在当前子段)使它指向规定的存储边界。第一个表达式参数(结果必须是纯粹的数字)是必需参数:边界基准,单位为字节。例如,'.balign8'向后移动位置计数器直至计数器的值等于8的倍数。如果位置计数器已经是8的倍数,则无需移动。第2个表达式参数(结果必须是纯粹的数字)给出填充字节的值,用这个值填充位置计数器越过的地方。第2个参数(和逗点)可以省略。如果省略它,填充字节的值通常是0。但在某些系统上,如果本段标识为包含代码,而填充值被省略,则使用no-op指令填充空白区。第3个参数的结果也必须是纯粹的数字,这个参数是可选的。如果存在第3个参数,它代表本对齐命令允许跳过字节数的最大值。如果完成这个对齐需要跳过的字节数比规定的最大值还多,则根本无法完成对齐。您可以在边界基准参数后简单地使用两个逗号,以省略填充值参数(第二参数);如果您在想在适当的时候,对齐操作自动使用no-op指令填充,本方法将非常奏效。.balignw和.balignl是.balign命令的变化形式。.balignw使用2个字节来填充空白区。.balignl使用4字节来填充。例如,.balignw4,0x368d将地址对齐到4的倍数,如果它跳过2个字节,GAS将使用0x368d填充这2个字节(字节的确切存放位置视处理器的存储方式而定)。如果它跳过1或3个字节,则填充值不明确。&&.rept&&&7&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//加上前面的那个rept,则需要循环32*7=224次,这有点类似于两个for循环,在每次进行内循环时都要进行32字节的对齐操作&&&&.if&vector&&NR_VECTORS&&&&&&&&&&&&&&//vector=0x20;NR_VECCTORS=256;&&&&&&&&&&&&&&.if&vector&&&&FIRST_EXTERNAL_VECTOR&&&&CFI_ADJUST_CFA_OFFSET&-4&&&&&//#defineCFI_ADJUST_CFA_OFFSET&.cfi_adjust_cfa_offset&//xx&offset&修改计算CFA的规则,修改前面一个offset。达到按4字节对齐&&&&&&.endif1:&&&&pushl&$(~vector+0x80)&&&&/*&Note:&always&insigned&byte&range&*/&&&????&&&&CFI_ADJUST_CFA_OFFSET&4&&&&&//4字节对齐&&&&&&.if&((vector-FIRST_EXTERNAL_VECTOR)%7)&&&6&&&&//当vector=41,48&等等时,if为假,则不jmp到标号2执行,而这样的情况总共有32次:我不知道为什么??&&&&jmp2f&&&&&&&&&&&&&&&&&&//数字定义的标号为临时标号,可以任意重复定义,例如:&2f&代表正向第一次出现的标号&2:&,3b代表反向第一次出现的标号&3:&&&&&&&.endif&&&&&&.previous&&&&&//.previous使汇编器返回到该自定义段之前的段进行汇编,则回到上面的数据段&&&&.long&1b&&&&&//在数据段中执行标号1的操作&&&&&.text&&&&&&&&&&//回到代码段vector=vector+1&&&&&&//vector增加1&&&&.endif&&.endr&&&&&&2:&&&&jmp&common_interrupt.endr&&&//结束224次循环END(irq_entries_start)&&//结束代码段.previous&&//返回数据段,结束数据段的interruptEND(interrupt).previous&&//返回定义数据段之前定义的那个段common_interrupt:&&&&addl&$-0x80,(%esp)&&&&/*&Adjust&vector&intothe&[-256,-1]&range&*/&&&SAVE_ALL&&&&&&&&&&&////保存系统寄存器信息&&&&TRACE_IRQS_OFF&&&&&&//在irqflags.h&#&define&TRACE_IRQS_OFF&&&&&&&&&&&&&&&&&&&&&&&&&&/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&jal&&&&trace_hardirqs_off&&&&movl&%esp,%eax&&&&call&do_IRQ&&&&jmp&ret_from_intr&&&&&//返回&&&附:.p2align指定下一行代码的对齐方式,第1参数表示按2的多少次幂字节对齐,第2参数表示对齐是跨越的位置用什么数据来填充,第3字节表示最多允许跨越多少字节。previous表示恢复到当前.section定义之前的那个段作为当前段&&&&
阅读(...) 评论()}

我要回帖

更多关于 安装程序无法找到入口 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信