X86 PUSH指令详解

  1. SDM指令功能描述(PUSH)
    总体描述:
    先递减栈指针,然后把指令中的SRC操作数的内容放在栈顶(也就是ss:(r/e)sp),关于地址和操作数等的宽度规则如下:
    地址宽度:取决于当前cs指向的代码段的D flag,可以被prefix 0x67重载。
    操作数宽度:取决于当前cs指向的代码段的D flag,可以被prefix 0x66或REX.W重载。操作数的宽度同时决定了栈指针的递减值。
    栈地址宽度:除了64bit-mode,B flag决定了栈地址宽度;64bit-mode的地址宽度永远是64。
    补充:
    如果要把立即数压到栈中,则默认使用符号填充的方式,如果要把段选择符压到栈中比如cs,则会用0填充宽度的不足。
    如果操作数宽度小于栈地址宽度,PUSH指令会造成栈的不对齐,会引发异常。
    如果要压入(R/E)SP,那么压入的值是执行PUSH之前的值。
    如果(R/E)SP的值为1,在实地址模式下执行PUSH会引发#SS异常。而进入异常服务函数的时候明显又会引发一次异常,就会引发#DF,然后又进入异常的过程中再次引发了第三次#SS,然后基本就进入shutdown了。

注:D/B flag在代码段中表示指令引用有效地址和操作数的长度

伪代码:
栈地址宽度==64if(操作数宽度==64)       //push qword
{
RSP = RSP - 8;
*(SS:RSP) = SRC;
}
else if(操作数宽度==32)  //push dword
{
RSP=RSP - 4;
*(SS:RSP) = SRC;
}
else if(操作数宽度==16)      //push word
{
RSP=RSP - 2;
*(SS:RSP) = SRC;
}
栈地址宽度==32if(操作数宽度==64)       //push qword
{
ESP = ESP - 8;
*(SS:ESP) = SRC;
}
else if(操作数宽度==32)  //push dword
{
ESP=ESP - 4;
*(SS:ESP) = SRC;
}
else if(操作数宽度==16)      //push word
{
ESP=ESP - 2;
*(SS:ESP) = SRC;
}

栈地址宽度==16else if(操作数宽度==32)  //push dword
{
SP=SP - 4;
*(SS:SP) = SRC;
}
else if(操作数宽度==16)      //push word
{
SP=SP - 2;
*(SS:SP) = SRC;
}
  1. 示例代码
__asm__ volatile
    (
        "pushw %0\t\n"
        "pushl %1\t\n"
        "movl $0, %%eax\t\n"
        "pushw (%%eax)\t\n"
        "pushl (0x30)\t\n"
        "pushw %%ax\t\n"
        "pushl %%eax\t\n"
        "pushw $1\t\n"
        "pushl $1\t\n"
        "pushw %%cs\t\n"
        "pushl %%cs\t\n"
        "pushw %%fs\t\n"
        "pushw %%gs\t\n"
        "addl $38, %%esp\t\n"
        ::"m"(i16), "m"(i32), "m"(i64)
    );

反汇编结果
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值