0

我有一个在内核(2.6.30 x86_64)模式(r0)下运行的示例代码,试图模拟 iret。我在英特尔手册的指南下推送变量。但它在 iret 指令的 pos 中出现运行时错误:

一般保护故障: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" :);
4

2 回答 2

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" :);

谢谢!!!

于 2012-08-02T11:52:11.673 回答
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*/

没用,因为您返回到相同的特权级别。

于 2012-08-02T10:20:40.827 回答