Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4567090
  • 博文数量: 385
  • 博客积分: 21208
  • 博客等级: 上将
  • 技术积分: 4393
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-30 13:40
文章分类

全部博文(385)

文章存档

2015年(1)

2014年(3)

2012年(16)

2011年(42)

2010年(1)

2009年(2)

2008年(34)

2007年(188)

2006年(110)

分类: LINUX

2007-11-11 20:21:09

SW 软中断详解
[ 2006-5-15 10:15:00 | By: 电子门 ]
 

SWI 软中断详解

http://www.mcublog.com/blog/user1/7610/archives/2006/12125.html

软中断:
编程异常通常叫做软中断

软中断是通讯进程之间用来模拟硬中断的 一种信号通讯方式。
中断源发中断请求或软中断信号后,CPU或接收进程在适当的时机自动进行中断处理或完成软中断信号对应的功能
软中断是软件实现的中断,也就是程序运行时其他程序对它的中断;而硬中断是硬件实现的中断,是程序运行时设备对它的中断。
 
1.软中断发生的时间是由程序控制的,而硬中断发生的时间是随机的
2.软中断是由程序调用发生的,而硬中断是由外设引发的
3.硬件中断处理程序要确保它能快速地完成它的任务,这样程序执行时才不会等待较长时间


阅读全文(219) | 回复(2) | 引用(0)
 


回复:软中断
goodguy发表评论于2005-6-15 20:06:00

SWI 指令


 

SWI : 软件中断

(Software Interrupt)
  SWI{条件}  <24 位编号>
这是一个简单的设施,但可能是最常用的。多数操作系统设施是用 SWI 提供的。没有 SWI 的 RISC OS 是不可想象的。

Nava Whiteford 解释了 SWI 是如何工作的(最初在 Frobnicate issue 12½)...

 


我将试图在本文中解释 SWI 是如何工作的。

SWI 是什么?

SWI 表示 Software Interrupt。在 RISC OS  中使用 SWI 来访问操作系统例程或第三方生产的模块。许多应用使用模块来给其他应用提供低层外部访问。

SWI 的例子有:

  • 文件器 SWI,它辅助读写磁盘、设置属性等。
  • 打印机驱动器 SWI,用来辅助使用打印并行端口。
  • FreeNet/Acorn TCP/IP 协议栈 SWI,用 TCP/IP 协议在 Internet 上发送和接收数据。

在以这种方式使用的时候,SWI 允许操作系统拥有一个模块结构,这意味着用来建立完整的操作系统的所需的代码可以被分割成许多小的部分(模块)和一个模块处理程序(handler)。

当 SWI 处理程序得到对特定的例程编号的一个请求的时候,它找到这个例程的位置并执行它,并传递(有关的)任何数据。

它是如何工作的?

首先查看一下如何使用它。一个 SWI 指令(汇编语言)看起来如下:
   SWI &02
   SWI "OS_Write0"
这些指令实际上是相同的,将被汇编成相同的指令。唯一的不同是第二个指令使用一个字符串来表示 SWI 编号 &02。在使用采用了字符串编号的程序的时候,在执行之前首先查找这个字符串。

在这里我们不想处理字符串,因为它不能给出它要进行什么的一个真实表示。它们通常用于增进一个程序的清晰程度,但不是实际执行的指令。

让我们再次看一下第一个指令:

   SWI &02
这是什么意思? 字面的意思是进入 SWI 处理程序并传递值 &02。在 RISC OS 中这意味着执行编号是 &02 的例程。

它是如何这么作的? 它如何传递 SWI 编号和进入 SWI 处理程序?

如果你查看内存的开始 32 字节(位于 0-&1C)并反汇编它们(查开实际的 ARM 指令)你将见到如下:

 

地址       内容               反汇编
00000000 : 0..å : E5000030 : STR R0,[R0,#-48]
00000004 : .óŸå : E59FF31C : LDR PC,&00000328
00000008 : .óŸå : E59FF31C : LDR PC,&0000032C
0000000C : .óŸå : E59FF31C : LDR PC,&00000330
00000010 : .óŸå : E59FF31C : LDR PC,&00000334
00000014 : .óŸå : E59FF31C : LDR PC,&00000338
00000018 : .óŸå : E59FF31C : LDR PC,&0000033C
0000001C : 2?ã : E3A0A632 : MOV R10,#&3200000
让我们仔细看一下。

除了第一个和最后一个指令之外(它们是特殊情况)你见到的都是把一个新值装载到 PC (程序计数器)的指令,它们告诉计算机到哪里去执行下一个指令。还展示了这个值是从内存中的一个地址接受来的。(你可以在 !Zap 主菜单上使用“Read Memory”选项去自己查看一下。)

这看起来好象与 SWI 没多少关系,下面做进一步的说明。

一个 SWI 所做的一切就是把模式改变成超级用户并设置 PC 来执行在地址 &08 处的下一个指令! 把处理器转换到超级用户模式会切换掉两个寄存器 r13 和 r14 并用 r13_svc 和 r14_svc 替换它们。

在进入超级用户模式的时候,还把 r14_svc 设置为在这个 SWI 指令之后的地址。

这个实际上就象一个连接到地址 &08 的分支指令(BL &08),但带有用于一些数据(SWI 编号)的空间。

象我说过的那样,地址 &08 包含跳转到另一个地址的一个指令,就是实际的 SWI 程序的地址!

此时你可能会想“稍等一会! 还有 SWI 编号呢?”。实际上处理器忽略这个值本身。SWI 处理程序使用传递来的 r14_svc 的值来获取它。

下面是完成它的步骤(在存储寄存器 r0-r12 之后):

  1. 它从 r14 中减去 4 来获得 SWI 指令的地址。
  2. 把这个指令装载到一个寄存器。
  3. 清除这个指令的高端 8 位,去掉了 OpCode 而只剩下的 SWI 编号。
  4. 使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。
  5. 恢复寄存器 r0-r12。
  6. 使处理器离开超级用户模式。
  7. 跳转到这个例程的地址。
容易吧! ;)

下面是一个例子,来自 ARM610 datasheet:

0x08 B Supervisor

EntryTable
DCD ZeroRtn
DCD ReadCRtn
DCD WriteIRtn

...

Zero EQU 0
ReadC EQU 256
WriteI EQU 512

; SWI 包含需要的例程在位 8-23 中和数据(如果有的话)在位 0-7 中。
; 假定 R13_svc 指向了一个合适的栈

STMFD R13, {r0-r2 , R14}
; 保存工作寄存器和返回地址。
LDR R0,[R14,#-4]
; 得到 SWI 指令。
BIC R0,R0, #0xFF000000
; 清除高端的 8 位。
MOV R1, R0, LSR #8
; 得到例程偏移量。
ADR R2, EntryTable
; 得到入口表(EntryTable)的开始地址。
LDR R15,[R2,R1,LSL #2]
; 分支到正确的例程

WriteIRtn
; 写 R0 中的位 0 - 7 中的字符。

.............
LDMFD R13, {r0-r2 , R15}^
; 恢复工作空间,并返回、恢复处理器模式和标志。
这就是 SWI 指令的基本处理步骤。

来源:

The ARM610 datasheet by Advanced Risc Machines
The ARM RISC Chip - A programmers guide by van Someren Atack published by Addison Wesley

 



Copyright © 2000 Richard Murray
300)this.width=300" border=0>

个人主页 | 引用 | 返回
 


回复:软中断
goodguy发表评论于2005-6-15 19:47:00
300)this.width=300" align=middle border=0>

SWI
instruction

300)this.width=300" align=middle border=0>

SWI : SoftWare Interrupt

  SWI  
This is a simple facility, but possibly the most used. Many Operating System facilities are provided by SWIs. It is impossible to imagine RISC OS without SWIs.

Nava Whiteford explains how SWIs work (originally in Frobnicate issue 12½)...


In this article I will attempt to delve into the working of SWIs (SoftWare Interrupts).

What is a SWI?

SWI stands for Software Interrupt. In RISC OS SWIs are used to access Operating System routines or modules produced by a 3rd party. Many applications use modules to provide low level external access for other applications.

Examples of SWIs are:

  • The Filer SWIs, which aid reading to and from disc, setting attributes etc.

  • The Printer Driver SWIs, used to well aid the use of the Parallel port for printing.

  • The SWIs FreeNet/Acorn TCP/IP stack SWIs used to transmit and receive data using the TCP/IP protocol usually used for sending data over the Internet.

When used in this way, SWIs allow the Operating System to have a modular structure, meaning that the code required to create a complete operating system can be split up into a number of small parts (modules) and a module handler.

When the SWI handler gets a request for a particular routine number it finds the position of the routine and executes it, passing any data.

So how does it work?

Well first lets look at how you use it. A SWI instruction (in assembly language) looks like this:
   SWI &02
or
   SWI "OS_Write0"
Both these instructions are in fact the same, and would therefore assemble to the same instruction. The only difference is that the second instruction uses a string to represent the SWI number which is &02. When a program written using the string is used, the string is first looked up before execution.

We're not going to deal with the strings here as they do not give a true representation of what it going on. They are often used to aid the clarity of a program, but are not the actual instructions that are executed.

Right lets take a look at the first instruction again:

   SWI &02
What does that mean? Well, literally it means enter the SWI handler and pass value &02. In RISC OS this means execute routine number &02.

So how does it do that, how does it passed the SWI number and enter the SWI handler?

If you look at a disassembly of the first 32 bytes of memory (locations 0-&1C) and disassemble them (look at the actual ARM instructions) you should see something like this:

Address  Contents            Disassembly
00000000 : 0..å : E5000030 : STR R0,[R0,#-48]
00000004 : .óŸå : E59FF31C : LDR PC,&00000328
00000008 : .óŸå : E59FF31C : LDR PC,&0000032C
0000000C : .óŸå : E59FF31C : LDR PC,&00000330
00000010 : .óŸå : E59FF31C : LDR PC,&00000334
00000014 : .óŸå : E59FF31C : LDR PC,&00000338
00000018 : .óŸå : E59FF31C : LDR PC,&0000033C
0000001C : 2¦ ã : E3A0A632 : MOV R10,#&3200000
So what? You may think, well take a closer look.

Excluding the first and last instructions (which are special cases) you can see that all the instruction load the PC (Program Counter), which tells the computer where to execute the next instruction from, with a new value. The value is taken from a address in memory which is also shown. (you can take a look at this for yourself using the "Read Memory" option on the !Zap main menu.)

Now, this may seem to bare little relation to SWIs but with the following information it should make more sense.

All a SWI does is change the Mode to Supervisor and set the PC to execute the next instruction at address &08! Putting the processor into Supervisor mode switches out 2 registers r13 and r14 and replaces these with r13_svc and r14_svc.

When entering Supervisor mode, r14_svc will also be set to the address after the SWI instruction.

This is really just like a Branch with Link to address &08 (BL &08) but with space for some data (the SWI number).

As I have said address &08 contains a instruction which jumps to another address, this is the address where the real SWI Handler is!

At this point you maybe thinking "Hang on a minute! What about the SWI number?". Well in fact the value itself is ignored by the processor. The SWI handler obtains it using the value of r14_svc that got passed.

This is how it does it (after storing the registers r0-r12):

  1. It subtracts 4 from r14 to obtain the address of the SWI instruction.
  2. Loads the instruction into a register.
  3. Clears the last 8 bits of the instruction, getting rid of the OpCode and giving just the SWI number.
  4. Uses this value to find to address of the routine of the code to be executing (using lookup tables etc.).
  5. Restore the registers r0-r12.
  6. Takes the processor out of Supervisor mode.
  7. Jumps to the address of the routine.
Easy! ;)

Here is some example code, from the ARM610 datasheet:

0x08 B Supervisor

EntryTable
DCD ZeroRtn
DCD ReadCRtn
DCD WriteIRtn

...

Zero EQU 0
ReadC EQU 256
WriteI EQU 512

; SWI has routine required in bits 8-23 and data
; (if any) in bits 0-7.
; Assumes R13_svc points to a suitable stack

STMFD R13, {r0-r2 , R14}
; Save work registers and return address
LDR R0,[R14,#-4]
; Get SWI instruction.
BIC R0,R0, #0xFF000000
; Clear top 8 bits.
MOV R1, R0, LSR #8
; Get routine offset.
ADR R2, EntryTable
; Get start address of entry
; table.
LDR R15,[R2,R1,LSL #2]
; Branch to appropriate routine.

WriteIRtn
; Wnte with character in R0 bits 0 - 7.

.............
LDMFD R13, {r0-r2 , R15}^
; Restore workspace and return, restoring
; processor mode and flags.
That's it, that's the basics of the SWI instruction.

Sources:

The ARM610 datasheet by Advanced Risc Machines
The ARM RISC Chip - A programmers guide by van Someren Atack published by Addison Wesley

阅读(10002) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

tekkamanninja2011-06-08 11:05:25

谢谢,后面的回复很好~~

chinaunix网友2009-03-21 19:09:38

谢谢!!

chinaunix网友2009-03-21 19:09:38

谢谢!!