Vol2.4.2.push指令

来源:互联网 发布:尤因和奥拉朱旺的数据 编辑:程序博客网 时间:2024/06/06 11:04
想想刚开始学汇编时候,就是轻飘飘的、蜻蜓点水式的,感觉什么都会了,但是好多东西都说不清楚,你是不是也者样纸?
---->就问你几个问题:
1. PUSH指令可以分解成多少个小步骤?
2. PUSH栈顶指针压进栈的是什么时候的值?
3. 极端情况下会产生哪些处理机异常?
4. 尺寸/位数 的注意问题有哪些?
5. .......
————傻眼了吧?跟我一起恶补吧~!


本文译自Intel 64 And IA-32 Architectures Software Developer’s Manual  Volume 2 Instruction Set Reference

文档最初写在我的WORD文档,存在网盘里,发表到CSDN博客时有改动

http://pan.baidu.com/s/1bnm4g6z

 

PUSH—Push Word, Doubleword or Quadword Onto the Stack

PUSH指令,把字,双字或四字压入堆栈

(译者注: 毫不客气地透漏下,我根本看不懂这是什么意思,待日后看懂后修改本篇文档)

 

指令描述Description

Decrements the stack pointer and then stores the source operand on the top of the stack. Address and operand sizes are determined and used as follows:

递减栈顶指针,然后将源操作数存到栈顶。地址和操作数位数的确定和使用规则如下:

 

• Address size. The D flag in the current code-segment descriptor determines the default address size; it may be overridden by an instruction prefix (67H).

地址位数。在当前代码段描述符中的D标志决定了默认的地址位数;地址位数也能由指令前缀67H翻转。

 The address size is used only when referencing a source operand in memory.

地址位数只在引用在内存中的源操作数时才会使用。

 

• Operand size. The D flag in the current code-segment descriptor determines the default operand size; it may be overridden by instruction prefixes (66H or REX.W).

操作数位数。在当前代码段描述符中的D标志决定了默认的操作数位数;操作数位数也能被指令前缀翻转(66H 或 REX.W )

The operand size (16, 32, or 64 bits) determines the amount by which the stack pointer is decremented (2, 4 or 8).

操作数位数(16, 32 或64位)决定了栈顶指针的减量(2, 4, 或 8 )。

If the source operand is an immediate of size less than the operand size, a sign-extended value is pushed on the stack. If the source operand is a segment register (16 bits) and the operand size is 64-bits, a zero extended value is pushed on the stack; if the operand size is 32-bits, either a zero-extended value is pushed on the stack or the segment selector is written on the stack using a 16-bit move. For the last case, all recent Core and Atom processors perform a 16-bit move, leaving the upper portion of the stack location unmodified.

如果源操作数是小于操作数位数的立即数,压入堆栈的是带符号拓展补位的立即数。如果源操作数是段寄存器(16位大小)而操作数位数是64位的,压入堆栈的是用零拓展补位的段寄存器值; 若操作数位数是32位的,或者用0补位压栈,或者将段选择子使用16位的传送指令写到栈顶。对于后一种情况,所有最近推出的酷睿和安腾处理器使用其余位不动地16位传送.

 

• Stack-address size. Outside of 64-bit mode, the B flag in the current stack-segment descriptor determines the size of the stack pointer (16 or 32 bits); in 64-bit mode, the size of the stack pointer is always 64 bits.

栈地址位数。除64位模式外,当前堆栈段描述符的B标志决定了栈顶指针(16或32位);在64位模式里,栈顶指针永远是64位。

The stack-address size determines the width of the stack pointer when writing to the stack in memory and

when decrementing the stack pointer. (As stated above, the amount by which the stack pointer is decremented is determined by the operand size.)

栈地址位数在向内存中的栈写数据和递减栈顶指针时候决定了栈顶指针的宽度。(如上所述,栈顶指针减少了量由操作数位数决定。)

If the operand size is less than the stack-address size, the PUSH instruction may result in a misaligned stack pointer (a stack pointer that is not aligned on a doubleword or quadword boundary).

若操作数位数少于栈地址位数,PUSH指令会导致栈顶指针不对齐(栈顶指针在双字或四字边界不对齐)。

 

The PUSH ESP instruction pushes the value of the ESP register as it existed before the instruction was executed. If a PUSH instruction uses a memory operand in which the ESP register is used for computing the operand address, the address of the operand is computed before the ESP register is decremented.

PUSH ESP把指令执行前的ESP寄存器压栈。若PUSH指令使用ESP寄存器用来计算操作数地址的内存操作数,操作数的地址在ESP寄存器递减前被计算。

 

If the ESP or SP register is 1 when the PUSH instruction is executed in real-address mode, a stack-fault exception (#SS) is generated (because the limit of the stack segment is violated). Its delivery encounters a second stack fault exception (for the same reason), causing generation of a double-fault exception (#DF). Delivery of the double-fault exception encounters a third stack-fault exception, and the logical processor enters shutdown mode. See the discussion of the double-fault exception in Chapter 6 of the Intel® 64 and IA-32 Architectures Software Developers Manual, Volume 3A.

若ESP或SP寄存器在实模式下执行后是1,栈故障异常(#SS)就会产生(因为违背了设置的段界限)。如果巧合的话,产生了第二个栈故障错误(原因相同),会产生双重故障异常(#DF)。若再遇到第三个栈故障错误,逻辑处理器会进入关机模式。关于双重故障异常我们在Intel(R) 64与IA-32架构软件开发者手册,第三卷中讨论。

 

IA-32架构兼容性IA-32 Architecture Compatibility

For IA-32 processors from the Intel 286 on, the PUSH ESP instruction pushes the value of the ESP register as it existed before the instruction was executed. (This is also true for Intel 64 architecture, real-address and virtual-8086 modes of IA-32 architecture.) For the Intel® 8086 processor, the PUSH SP instruction pushes the new value of the SP register (that is the value after it has been decremented by 2).

对于Intel 286以后的IA-32架构处理器,PUSH ESP指令将执行前的ESP压栈。(同样适用于Intel 64架构和IA-32架构上的虚拟8086模式。)对于Intel® 8086处理器,PUSH SP把执行后的SP新值压栈(即SP减2后的值)。

 

Intel官方伪指令描述的操作Operation

(* See Description section for possible sign-extension or zero-extension of source operand and for *)

(* a case in which the size of the memory store may be smaller than the instruction’s operand size *)

IF StackAddrSize = 64

  THEN

    IF OperandSize = 64

      THEN

        RSP ←RSP – 8;

        Memory[SS:RSP] ←SRC; (* push quadword *)

      ELSE IF OperandSize = 32

        THEN

          RSP ←RSP – 4;

          Memory[SS:RSP] ←SRC; (* push dword *)

        ELSE (* OperandSize = 16 *)

          RSP ←RSP – 2;

            Memory[SS:RSP] ←SRC; (* push word *)

      FI;

  ELSE IF StackAddrSize = 32

    THEN

      IF OperandSize = 64

        THEN

          ESP ←ESP – 8;

          Memory[SS:ESP] ←SRC; (* push quadword *)

        ELSE IF OperandSize = 32

          THEN

            ESP ←ESP – 4;

            Memory[SS:ESP] ←SRC; (* push dword *)

          ELSE (* OperandSize = 16 *)

            ESP ←ESP – 2;

            Memory[SS:ESP] ←SRC; (* push word *)

        FI;

  ELSE (* StackAddrSize = 16 *)

    IF OperandSize = 32

      THEN

        SP ←SP – 4;

        Memory[SS:SP] ←SRC; (* push dword *)

      ELSE (* OperandSize = 16 *)

        SP ←SP – 2;

        Memory[SS:SP] ←SRC; (* push word *)

FI;

FI;


标志位影响状况Flags Affected

None.

无影响

 

保护模式下能够产生的异常Protected Mode Exceptions

#GP(0) If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. 

#GP(0)若内存操作数的实际地址超出CS, DS, ES, FS, GS的段界限。

If the DS, ES, FS, or GS register is used to access memory and it contains a NULL segment selector.

在DS, ES, FS, GS寄存器用来访问内存并且寄存器本身包含NULL选择子。

 

#SS(0) If a memory operand effective address is outside the SS segment limit.

#SS(0)若内存操作数的实际地址超过SS段界限。

 

#PF(fault-code) If a page fault occurs.

#PF(故障代码) 如果发生页故障。

 

#AC(0)If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3

#AC(0) 若启用了对齐检查,并且在当前特权级(CPL)是3时引用了一个没有对齐的内存引用。

 

#UD  If the LOCK prefix is used.

#UD 使用了LOCK指令前缀。

 

实模式下可能产生的异常Real-Address Mode Exceptions

#GP If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.

#GP(0)若内存操作数的实际地址超出CS, DS, ES, FS, GS的段界限。

 

#SS If a memory operand effective address is outside the SS segment limit.

#SS(0)若内存操作数的实际地址超过SS段界限。

If the new value of the SP or ESP register is outside the stack segment limit.

若SP或ESP得到新值超出了堆栈段界限

 

#UD  If the LOCK prefix is used.

#UD 使用了LOCK前缀。

 

虚拟8086模式下可能产生的异常Virtual-8086 Mode Exceptions

#GP(0) If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. 

#GP(0)若内存操作数的实际地址超出CS, DS, ES, FS, GS的段界限。

 

#SS(0) If a memory operand effective address is outside the SS segment limit.

#SS(0)若内存操作数的实际地址超过SS段界限。

 

#PF(fault-code) If a page fault occurs.

#PF(故障代码) 如果发生页故障。

 

#AC(0)If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3

#AC(0) 若启用了对齐检查,并且在当前特权级(CPL)是3时引用了一个没有对齐的内存引用。

 

#UD  If the LOCK prefix is used.

#UD 使用了LOCK指令前缀。

 

兼容模式可能产生的异常Compatibility Mode Exceptions

Same exceptions as in protected mode.

与保护模式下情况相同

 

64位模式可能产生的异常64-Bit Mode Exceptions

#GP(0) If the memory address is in a non-canonical form.

#GP(0) 若内存地址使用了不标准的格式

 

#SS(0) If the stack address is in a non-canonical form.

#SS(0) 若内存地址使用了不标准的格式

 

#PF(fault-code) If a page fault occurs.

#PF(故障代码) 如果发生页故障。

 

#AC(0)If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3

#AC(0) 若启用了对齐检查,并且在当前特权级(CPL)是3时引用了一个没有对齐的内存引用。

 

#UD  If the LOCK prefix is used.

#UD  若使用了LOCK指令前缀

If the PUSH is of CS, SS, DS, or ES.

若PUSH了CS, SS, DS 或ES




后记:

英语语法、翻译水平有限,这几句话翻译的很蹩脚,也不知对不对,待日后检验。

1. The PUSH ESP instruction pushes the value of the ESP register as it existed before the instruction was executed. 

2. If a PUSH instruction uses a memory operand in which the ESP register is used for computing the operand address, the address of the operand is computed before the ESP register is decremented.

3. If the ESP or SP register is 1 when the PUSH instruction is executed in real-address mode, a stack-fault exception (#SS) is generated (because the limit of the stack segment is violated). 

4. #SS(0) If the stack address is in a non-canonical form.


0 0
原创粉丝点击