iret错误:一般保护错误fffc

时间:2012-08-02 08:33:24

标签: linux assembly linux-kernel

我有一个在内核(2.6.30 x86_64)模式下运行的示例代码(r0),试图在intel手册的指导下模拟iret.I推送变量。但是在iret指令的位置发现运行时错误:

  

一般保护错误:fffc [#] SMP

asm volatile(
    "mov %%ss,%%ax \n\t"
    "push %%rax \n\t"/*ss*/
    "push %%rsp \n\t"/*rsp*/
    "pushfq \n\t"/*rflags*/
    "mov %%cs,%%ax \n\t"
    "push %%rax \n\t"/*cs*/
    "mov $._restart_code,%%rax \n\t"
    "push %%rax \n\t"/*rip*/
    "iret \n\t"/*here is the fault rip!!!!!!*/
    "._restart_code:"
    "nop" :);

2 个答案:

答案 0 :(得分:0)

我不确定它是否会解决您的问题,但这里有一些注意事项:

"mov %%cs,%%ax \n\t"
"push %%rax \n\t"/*cs*/

您正在更新EAX的低位字节,因此RAX的高位字节可能与0不同(不应该)。

"mov $._restart_code,%%rax \n\t"

同样,你应该断言$._restart_code是规范形式的。

"mov %%ss,%%ax \n\t"
"push %%rax \n\t"/*ss*/
"push %%rsp \n\t"/*rsp*/

无用,因为你返回相同的权限级别。

答案 1 :(得分:0)

错误是推送后rsp发生了变化。

asm volatile(
    "mov %%ss,%%ax \n\t"
    "push %%rax \n\t"/*ss*/
    "push %%rsp \n\t"/*rsp ##########error here!!!!!!! */ 
    "pushfq \n\t"/*rflags*/
    "mov %%cs,%%ax \n\t"
    "push %%rax \n\t"/*cs*/
    "mov $._restart_code,%%rax \n\t"
    "push %%rax \n\t"/*rip*/
    "iret \n\t"/*###iretq should be used under 64bit mode*/
    "._restart_code:"
    "nop" :);

所以,在所有推送指令之前保存rsp。并且正确的代码是:

asm volatile(
        "mov %%rsp,%%rbx \n\t"
        "mov %%ss,%%ax \n\t"
        "push %%rax \n\t"/*ss*/
        "push %%rbx \n\t"/*rsp*/ 
        "pushfq \n\t"/*rflags*/
        "mov %%cs,%%ax \n\t"
        "push %%rax \n\t"/*cs*/
        "mov $._restart_code,%%rax \n\t"
        "push %%rax \n\t"/*rip*/
        "iretq \n\t"
        "._restart_code:"
        "nop" :);

感谢!!!