如果没用到.asp的话,可以禁用
如果你是webform的话,.aspx, .axd, .ashx不能禁用
用到webservice的话,.asmx, .soap不迅答桥能禁用
用到wcf的话,.svc, .soap不能禁用
如果是mvc程序的话,.cshtml不能禁用
StaticFile不能禁用
问题表现: 某个应用在调用wcf服务时,日志提示"405 method not allowed"
开始以为是程序的问题,后来发现在别的服务器上安装使用都没有问题,猜测可能是IIS环境的问题。
百度了一下,得出的结论是:一般IIS默认能处理静态的htm,html文件 ,以埋激雀及动态铅液的脚本 asp,aspx 文件,如果要处理php或其他类型的脚本语言,必须做好ISAPI映射,于是打开IIS,找到提供上述RisWebService.svc服务的站点,点击“处理程序映射”
观察路径这一列,发现没有.svc的路径映射,所以IIS无法识别程序中的一般处理程序(*.svc),因此就报了标题中的错误。可能是在安装IIS过程中安装ASP.net功能安全不全。
解决弯早办法:找到NET4安装目录: %windir%\Microsoft.NET\Framework64\v4.0.30319,
cmd运行命令 aspnet_regiis -i,
安装完之后,再次查看IIS程序映射,发现增加了.svc路径,问题解决。
发生异常时,异常处理程序可能需要确定处理器是在 ARM 状态还是在 Thumb 状返肆态。特别是 SVC 处理程序,更需要读取处理器状态。 通过检查 SPSR 的 T 位可确定处理器状态。 该位在 Thumb 状态时为 1,在 ARM 状态时为 0。
ARM 和 Thumb 指令集均有 SVC 指令。 在 Thumb 状态下调用 SVC 时,必须考虑以下情况:
指令的地址在 lr–2,而不在 lr–4。
该指令本身为 16 位,因而需要半字加载,请参阅Figure 6.3。
在 ARM 状态下,SVC 编号以 8 位存储,而不是 24 位。
Figure 6.3. Thumb SVC 指令
Example 6.8 演示处理 SVC 异常的 ARM 代码。 通过动态调用 SVC,可以增大 Thumb 状态下可访问的 SVC 编号的范围。
Example 6.8. SVC 处理程序
PRESERVE8
AREA SVC_Area, CODE, READONLY
EXPORT SVC_HandlerIMPORT C_SVC_Handler
T_bit EQU0x20Thumb bit (5) of CPSR/SPSR.
SVC_Handler
STMFD sp!, {r0-r3, r12, lr} Store registers
MOV r1, sp Set pointer to parameters
MRS r0, spsr Get spsr
STMFD sp!, {r0, r3} Store spsr onto stack and another
register to maintain 8-byte-aligned stack
TST r0, #T_bit Occurred in Thumb state?
LDRNEH r0, [lr,#-2] Yes: Load halfword and...
BICNE r0, r0, #0xFF00...extract comment field
LDREQ r0, [lr,#-4] No: Load word and...
BICEQ r0, r0, #0xFF000000...extract comment field
BL C_SVC_Handler Call main part of handler
LDMFD sp!, {r0, r3} Get spsr from stack
MSR SPSR_cxsf, r0 Restore spsr
LDMFD sp!, {r0-r3, r12, pc}^ Restore registers and return
END
确定要调用的 SVC
进入 SVC 处理程序后,必须确定要调用哪个 SVC。 此信息可存储在指令本身的 0-23 位,如Figure 6.4 所示,或将其传递给某个漏空轿整数寄存器,通常为 R0-R3 中的一个。
Figure 6.4. ARM SVC 指令
顶层 SVC 处理程序可以相对于 LR 加载 SVC 指令 请用汇编语言、C/C++ 内联或嵌入式汇编器编写。
处理程序必须首先将导致异常的 SVC 指令加载到寄存器中。 此时,SVC LR 保存 SVC 指令的下一个指令的地址,这样 SVC 加载到了寄存器(本例中为 R0)中,代码如下:
LDR R0, [lr,#-4]
然后,处理程序可检查注释字段位,以决定所需的 *** 作。 通过清除 *** 作码的前八位来提取 SVC 编号:
BIC R0, R0, #0xFF000000
Example 6.9 演示如何用这些指令编写顶层亏告 SVC 处理程序。 有关在 ARM 状态和 Thumb 状态下处理 SVC 指令的处理程序示例,请参阅Example 6.8。
Example 6.9. 顶层 SVC 处理程序
PRESERVE8
AREA TopLevelSVC, CODE, READONLY Name this block of code.
EXPORT SVC_Handler
SVC_Handler
PUSH {R0-R12,lr} Store registers.
LDRR0,[lr,#-4] Calculate address of SVC instruction
and load it into R0.
BICR0,R0,#0xFF000000 Mask off top 8 bits of instruction
to give SVC number.
Use value in R0 to determine which SVC routine to execute.
LDM sp!, {R0-R12,pc}^ Restore registers and return.
END
汇编语言编写的 SVC 处理程序
要调用请求的 SVC 编号的处理程序,最简单的方法是使用跳转表。 如果 R0 包含 SVC 编号,则Example 6.10 中的代码可以插入到Example 6.9 提供的顶层处理程序中,插入位置在 BIC 指令之后。
Example 6.10. SVC 跳转表
AREA SVC_Area, CODE, READONLY
PRESERVE8
IMPORT SVCOutOfRange
IMPORT MaxSVC
CMPR0,#MaxSVC Range check
LDRLS pc, [pc,R0,LSL #2]
B SVCOutOfRange
SVCJumpTable
DCDSVCnum0
DCDSVCnum1
DCD for each of other SVC routines
SVCnum0SVC number 0 code
BEndofSVC
SVCnum1SVC number 1 code
BEndofSVC
Rest of SVC handling code
EndofSVC
END
C 语言和汇编语言编写的 SVC 处理程序
尽管顶层处理程序始终必须用 ARM 汇编语言编写,处理每个 SVC 的例程既可用汇编语言编写,也可用 C 语言编写。有关限制的说明,请参阅在超级用户模式下使用 SVC。
顶层处理程序使用 BL 指令可跳转到相应的 C 函数。 因为 SVC 编号是由汇编例程加载到 R0 中的,所以作为第一个参数传递给 C 函数。 举例来说,函数可以将此参数值用在 switch() 语句中,请参阅Example 6.11。
若要调用此 C 函数,可以向Example 6.9 中 SVC_Handler 例程添加下面的代码行:
BLC_SVC_Handler Call C routine to handle the SVC
Example 6.11. C 函数中的 SVC 处理程序
void C_SVC_handler (unsigned number)
{
switch (number)
{
case 0 : /* SVC number 0 code */
...
break
case 1 : /* SVC number 1 code */
...
break
...
default :/* Unknown SVC - report error */
}
}
超级用户模式堆栈空间可能是有限的,因此要避免使用需要大量堆栈空间的函数。
MOV R1, spSecond parameter to C routine...
...is pointer to register values.
BLC_SVC_Handler Call C routine to handle the SVC.
用 C 语言编写的 SVC 处理程序可以传入和传出值,前提是顶层处理程序将堆栈指针值作为第二个参数(在 R1 中)传递给 C 函数,并且更新 C 函数以访问该值:
void C_SVC_handler(unsigned number, unsigned *reg)
现在,C 函数在主应用程序代码中遇到 SVC 指令时就可访问存储在寄存器中的值了,请参阅 Figure 6.5。 它可从其中读取:
value_in_reg_0 = reg [0]
value_in_reg_1 = reg [1]
value_in_reg_2 = reg [2]
value_in_reg_3 = reg [3]
也可向其中回写:
reg [0] = updated_value_0
reg [1] = updated_value_1
reg [2] = updated_value_2
reg [3] = updated_value_3
这使已更新的值写入到堆栈的相应位置,然后通过顶层处理程序恢复到寄存器中。
Figure 6.5. 访问超级用户模式堆栈
在超级用户模式下使用 SVC
执行 SVC 指令时:
处理器进入超级用户模式。
CPSR 存储到 SVC SPSR 中。
返回地址存储在 SVC LR 中,请参阅处理器对异常的响应。
如果处理器已经处在超级用户模式下,则会损坏 SVC LR 和 SPSR。
如果在超级用户模式下调用 SVC,则必须存储 SVC LR 和 SPSR,以确保 LR 和 SPSR 的原始值不会丢失。 例如,如果某个特定 SVC 编号的处理程序例程调用另一个 SVC,则必须确保该处理程序例程将 SVC LR 和 SPSR 都存储在堆栈中。 这可确保处理程序的每一次调用都保存返回到调用它的 SVC 后面的指令所需要的信息。Example 6.12 演示如何实现这一点。
Example 6.12. SVC 处理程序
AREA SVC_Area, CODE, READONLY
PRESERVE8
EXPORT SVC_Handler
IMPORT C_SVC_Handler
T_bit EQU 0x20
SVC_Handler
PUSH {R0-R3,R12,lr} Store registers.
MOV R1, sp Set pointer to parameters.
MRS R0, SPSR Get SPSR.
PUSH {R0,R3} Store SPSR onto stack and another register to maintain
8-byte-aligned stack. Only required for nested SVCs.
TST R0,#0x20 Occurred in Thumb state?
LDRHNE R0,[lr,#-2] Yes: load halfword and...
BICNER0,R0,#0xFF00...extract comment field.
LDREQR0,[lr,#-4] No: load word and...
BICEQR0,R0,#0xFF000000...extract comment field.
R0 now contains SVC number
R1 now contains pointer to stacked registers
BL C_SVC_HandlerCall C routine to handle the SVC.
POP {R0,R3} Get SPSR from stack.
MSR SPSR_cf, R0 Restore SPSR.
LDM sp!, {R0-R3,R12,pc}^ Restore registers and return.
END
用 C 和 C++ 编写的嵌套 SVC
可用 C 或 C++ 语言编写嵌套的 SVC。 由 ARM 编译器生成的代码根据需要存储和重新加载 lr_SVC。
从应用程序调用 SVC
可用汇编语言或 C/C++ 调用 SVC。
用汇编语言设置所有必需的寄存器值并发出相关的 SVC。 例如:
MOVR0, #65load R0 with the value 65
SVC0x0Call SVC 0x0 with parameter value in R0
几乎像所有的 ARM 指令那样,SVC 指令可被有条件地执行。
在 C/C++ 中,将 SVC 声明为一个 __SVC 函数并调用它。 例如:
__svc(0) void my_svc(int)
.
.
.
my_svc(65)
这确保了 SVC 以内联方式进行编译,无需额外的调用开销,其前提是:
所有参数都只传入 R0-R3
所有结果都只返回到 R0-R3 中。
参数被传递给 SVC,如同 SVC 是一个真正的函数调用。 但是,如果有二到四个返回值,则必须告诉编译器返回值在一个结构中,并使用__value_in_regs 命令。 这是因为基于 struct 值的函数通常被视为一个 void 函数,它的第一个参数必须是存放结果结构的地址。
Example 6.13 和 Example 6.14 演示一个 SVC 处理程序,该处理程序提供 SVC 编号 0x0、0x1、0x2 和 0x3。 SVC 0x0 和 SVC 0x1 都采用两个整数参数并返回一个结果。SVC 0x2 采用四个参数并返回一个结果。SVC 0x3 采用四个参数并返回四个结果。 此示例位于示例目录(...\svc\main.c 和 ...\svc\svc.h)中。
Example 6.13. main.c
#include <stdio.h>
#include "svc.h"
unsigned *svc_vec = (unsigned *)0x08
extern void SVC_Handler(void)
int main( void )
{
int result1, result2
struct four_results res_3
Install_Handler( (unsigned) SVC_Handler, svc_vec )
printf("result1 = multiply_two(2,4) = %d\n", result1 = multiply_two(2,4))
printf("result2 = multiply_two(3,6) = %d\n", result2 = multiply_two(3,6))
printf("add_two( result1, result2 ) = %d\n", add_two( result1, result2 ))
printf("add_multiply_two(2,4,3,6) = %d\n", add_multiply_two(2,4,3,6))
res_3 = many_operations( 12, 4, 3, 1 )
printf("res_3.a = %d\n", res_3.a )
printf("res_3.b = %d\n", res_3.b )
printf("res_3.c = %d\n", res_3.c )
printf("res_3.d = %d\n", res_3.d )
return 0
}
Example 6.14. svc.h
__svc(0) int multiply_two(int, int)
__svc(1) int add_two(int, int)
__svc(2) int add_multiply_two(int, int, int, int)
struct four_results
{
int a
int b
int c
int d
}
__svc(3) __value_in_regs struct four_results
many_operations(int, int, int, int)
从应用程序动态调用 SVC
在某些情况下,需要调用直到运行时才会知道其编号的 SVC。 例如,当有很多相关 *** 作可对同一目标执行,并且每个 *** 作都有自己的 SVC 时,就会发生这种情况。 在这种情况下,前几节中介绍的方法不适用。
对此,有几种解决方法,例如:
通过 SVC 编号构建 SVC 指令,将它存储在某处,然后再执行该指令。
使用通用的 SVC(作为一个额外的参数)将一个代码作为对其参数执行的实际 *** 作。 通用 SVC 对该 *** 作进行解码并予以执行。
第二种机制可使用汇编语言将所需的 *** 作数传递到寄存器(通常为 R0 或 R12)中来实现。 然后可重新编写 SVC 处理程序,对相应寄存器中的值进行处理。
因为有些值必须用注释字段传递给 SVC,所以有可能将这两种方法结合起来使用。
例如, *** 作系统可能会只用一条 SVC 指令和一个寄存器来传递所需的 *** 作数。 这使得其他 SVC 空间可用于应用程序特定的 SVC。 在一个特定的应用程序中,如果从指令提取 *** 作数的开销太大,则可使用这个方法。 ARM 和 Thumb 半主机指令就是这样实现的。
Example 6.15 演示如何使用 __svc 将 C 函数调用映射到半主机调用。 该示例是根据示例目录中的 retarget.c 编写的,该文件路径为...\emb_sw_dev\source\retarget.c。
Example 6.15. 将 C 函数映射到半主机调用
#ifdef __thumb
/* Thumb Semihosting */
#define SemiSVC 0xAB
#else
/* ARM Semihosting */
#define SemiSVC 0x123456
#endif
/* Semihosting call to write a character */
__svc(SemiSVC) void Semihosting(unsigned op, char *c)
#define WriteC(c) Semihosting (0x3,c)
void write_a_character(int ch)
{
char tempch = ch
WriteC( &tempch )
}
编译器含有一个机制,支持使用 R12 来传递所需运算的值。 在 AAPCS 下,R12 为 ip 寄存器,并且专用于函数调用。 其他时间内可将其用作暂存寄存器。 通用 SVC 的参数被传递到 R0-R3 寄存器中,如前面所述,还可以选择在 R0-R3 中返回值,请参阅 从应用程序调用 SVC。 在 R12 中传递的 *** 作数可以是通用 SVC 调用的 SVC 的编号。 但这不是必需的。
Example 6.16 演示使用通用或间接 SVC 的 C 程序段。
Example 6.16. 使用间接 SVC
__svc_indirect(0x80)
unsigned SVC_ManipulateObject(unsigned operationNumber,
unsigned object,unsigned parameter)
unsigned DoSelectedManipulation(unsigned object,
unsigned parameter, unsigned operation)
{ return SVC_ManipulateObject(operation, object, parameter)
}
它生成以下代码:
DoSelectedManipulation
PUSH {R4,lr}
MOV R12,R2
SVC #0x80
POP {R4,pc}
END
还可使用 __svc 机制从 C 中传递 R0 中的 SVC 编号。 例如,如果将 SVC 0x0 用作通用 SVC, *** 作 0 为字符读, *** 作 1 为字符写,则可以进行如下设置:
__svc (0) char __ReadCharacter (unsigned op)
__svc (0) void __WriteCharacter (unsigned op, char c)
可通过如下定义使其具有更好的可读性风格:
#define ReadCharacter () __ReadCharacter (0)
#define WriteCharacter (c) __WriteCharacter (1, c)
但是,如果以这种方式使用 R0,则仅有三个寄存器可用于向 SVC 传递参数。 通常,在不得不将除 R0-R3 之外的更多参数传递给子例程时,可通过使用堆栈来完成 但是,SVC 处理程序不容易访问堆栈参数,因为这些参数通常在用户模式堆栈中,而不是在 SVC 处理程序使用的超级用户模式堆栈中。
作为另一种选择,其中一个寄存器(通常是 R1)可用来指向存储其他参数的内存块。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)