2

<< Intel 64およびIA-32アーキテクチャソフトウェア開発者マニュアル第2巻B:命令セットリファレンス、ニュージーランド>>は次のように述べています。

| Opcode* | Instruction | Op/En | 64-Bit Mode | Compat/Leg Mode | Description |
|      6A | PUSH imm8   | C     | Valid       | Valid           | Push imm8.  |
|      68 | PUSH imm16  | C     | Valid       | Valid           | Push imm16. |
|      68 | PUSH imm32  | C     | Valid       | Valid           | Push imm32. |

#cat -n test.asm

 1  bits 64
 2
 3  push byte 12
 4  push word 12
 5  push dword 12
 6  push qword 12
 7

#nasm test.asm

 test.asm:5: error: instruction not supported in 64-bit mode
  1. 5行目が違法なのはなぜですか?「PUSHimm32」と一致すると思います。

  2. そして、なぜ6行目が合法なのですか?'PUSH imm8 / PUSH imm16 /PUSHimm32'のいずれとも一致しません。

お願い助けて!

======テスト======

    I think that the Intel manual is right, the 'push imm' 
    instructions do have three encoding form:
    Form 1: 6a XX
    Form 2: 66 68 XX XX 
    Form 3: 68 XX XX XX XX

    What we are arguing is the implemental specific behavior of the NASM.

    In NASM 2.04rc1(the above example I given):
    1. The 'byte' in 'push byte imm' direct the NASM use the Form 1, 
       no matter how long the imm given in the instruction it is, the imm
       was trunked to a byte in final machine code. 
    2. The 'word' in 'push word imm' direct the NASM use the Form 2,
       no matter how long the imm given in the instruction it is, the imm 
       was trucked or zero-extended to a word in final machine code.
    3. The 'qword' in 'push dword imm' direct the NASM use the Form 3,
       no matter how long the imm given in the instruction it is, the imm 
       was trucked or zero-extended to a dword in final machine code.
       Note: the 'qword' in the instruction but 'dword' in final machine
       code, which made us confused.
    4. if none of 'byte', 'word', 'qword' is given, the NASM use the From 3.

次の例を参照してください。

# cat -n push.asm
1  bits 64
2
3  push byte 0x21
4  push byte 0x4321
5
6  push word 0x4321
7  push word 0x654321
8
9  push qword 0x654321
10
11  push 0x21
12  push 0x4321
13  push 0x654321
14  push 0x87654321
15  push 0xa987654321
16
# nasm -v
NASM version 2.04rc1 compiled on Feb 21 2009
# nasm push.asm -o push.bin
push.asm:4: warning: signed byte value exceeds bounds
push.asm:7: warning: word data exceeds bounds
# ndisasm -b 32 push.bin // 'ndisasm -b 64 push.bin' not works right in this version of NASM.
00000000  6A21              push byte +0x21
00000002  6A21              push byte +0x21
00000004  66682143          push word 0x4321
00000008  66682143          push word 0x4321
0000000C  6821436500        push dword 0x654321
00000011  6821000000        push dword 0x21
00000016  6821430000        push dword 0x4321
0000001B  6821436500        push dword 0x654321
00000020  6821436587        push dword 0x87654321
00000025  6821436587        push dword 0x87654321

In newer NASM, the behavior changes:
(1) 'push 0x21' was encoded to '6A21' in NASM 2.10.01,
    while '6821000000' in NASM 2.04rc1; 
(2)'push dword 0x654321' in 64 bit mode was allowed 
    in NASM 2.10.01 and encoded to '6821436500'
4

3 に答える 3

7

マニュアルが間違っています。(ちなみに、これだけがエラーではありません)

64 ビット モードでは、32 ビット プッシュはありません。pushは、REX.W プレフィックスなしで 64 ビットに昇格される数少ない命令の 1 つであり、降格することはできません。

編集:実際、マニュアルの私のバージョンは正しいことを言っています:

Sign-Extended IMM32を押します。

したがって、64ビットモードでは、「qwordをプッシュし、即時から符号を拡張する」と解釈されます。

于 2012-07-02T10:04:10.673 に答える
4

編集:以下の打たれたテキストは、即値に関して間違っています。

これがどのように機能するかです...

オペランドのサイズに関係なく、64 ビット モードではスタック ポインタを 2 または 8 バイトだけ進めることができpush、このように割り当てられたスペースに 16 ビットまたは 64 ビットの値を書き込むことができます。

したがって、8 ビット レジスタまたは 32 ビット レジスタは、ゼロまたは符号拡張されないため、プッシュできません。ただし、16 ビットまたは 64 ビットのレジスタをプッシュできます。

即時の場合は少し異なります。

push imm8(オペコード 6Ah の後に imm8 が続く) は、最初に 8 ビットの即値オペランドを 64 ビットに符号拡張し、次に結果の 8 バイト値をプッシュします。

push imm32(オペコード 68h の後に imm32 が続く) は、最初に 32 ビットの即値オペランドを 64 ビットに符号拡張し、次に結果の 8 バイト値をプッシュします。

push imm16(オペランド サイズ プレフィックス 66h、オペコード 6Ah の後に imm16 が続きます) は、16 ビットの即値オペランドを拡張子なしで 2 バイト値としてプッシュします。

あなたが言うとき、NASMは少し寛容に見えますpush qword 12. push qword 0x80000000ただし、 orpush qword 2147483648などの符号付き 32 ビット整数として表現できない値を使用すると、警告が発行されますpush qword -2147483649

This is the relevant piece of documentation:
ELSE IF SRC is immediate byte
  THEN TEMP ← SignExtend(SRC); (* extend to operand size *)
ELSE IF SRC is immediate word (* operand size is 16 *)
  THEN TEMP ← SRC;
ELSE IF SRC is immediate doubleword (* operand size is 32 or 64 *)
  THEN
    IF operand size = 32
      THEN TEMP ← SRC;
      ELSE TEMP ← SignExtend(SRC); (* extend to operand size of 64 *)
FI;

現在、NASM の私のバージョン (2011 年 7 月 15 日にコンパイルされた 2.09.10) は、push dword 12. あなたのが本当にそうなら、それはバグです。

NASM にバグが見つかったようです。push word 1266h、6Ah、0Chに組み立てます。IOW、それはpush imm8forのオペコードを使用しpush imm16ます。それは正しくありません。バイト オペランドは、オペランド サイズのプレフィックスに関係なく、バイト オペランドのままです。ダブルワードおよびクワッドワードのオペランドに拡張または縮小できるのは、「ワード」オペランドのみです。同じ命令のオペコードのペア、1 つはバイト オペランドを操作し、もう 1 つは (q/d) ワード オペランドを操作し、オペランド サイズ プレフィックスは「ワード」の「ワードネス」に影響します。オペランド。64 ビット モードでの適切なエンコードはpush word 12、66h、68h、0Ch、0h です。

64 ビット モードでは 32 ビット オペランドをプッシュできないため、5 行目は不正です。プッシュできるのは、64 ビット オペランド (push byte 12事実上push byte-sign-extended-to-qword 12) または 16 ビット オペランドのみです。の操作を説明する疑似コードを見てくださいpush

IF in 64-bit mode (* stack-address size = 64 *)
  THEN
    IF operand size = 64
      THEN
        RSP ← RSP − 8;
        Memory[RSP] ← TEMP; (* Push quadword *)
      ELSE (* operand size = 16 *)
        RSP ← RSP − 2;
        Memory[RSP] ← TEMP; (* Push word *)
FI;

はっきりとした理由はわかりませんが、以下の2つです。

  1. このように実装すると便利でした
  2. 設計者は、整列されていないスタック エラーの可能性を低くしようとしました
于 2012-07-02T10:07:21.237 に答える
1
    I think that the Intel manual is right, the 'push imm' 
    instructions do have three encoding form:
    Form 1: 6a XX
    Form 2: 66 68 XX XX 
    Form 3: 68 XX XX XX XX

    What we are arguing is the implemental specific behavior of the NASM.

    In NASM 2.04rc1(the above example I given):
    1. The 'byte' in 'push byte imm' direct the NASM use the Form 1, 
       no matter how long the imm given in the instruction it is, the imm
       was trunked to a byte in final machine code. 
    2. The 'word' in 'push word imm' direct the NASM use the Form 2,
       no matter how long the imm given in the instruction it is, the imm 
       was trucked or zero-extended to a word in final machine code.
    3. The 'qword' in 'push dword imm' direct the NASM use the Form 3,
       no matter how long the imm given in the instruction it is, the imm 
       was trucked or zero-extended to a dword in final machine code.
       Note: the 'qword' in the instruction but 'dword' in final machine
       code, which made us confused.
    4. if none of 'byte', 'word', 'qword' is given, the NASM use the From 3.

次の例を参照してください。

# cat -n push.asm
1  bits 64
2
3  push byte 0x21
4  push byte 0x4321
5
6  push word 0x4321
7  push word 0x654321
8
9  push qword 0x654321
10
11  push 0x21
12  push 0x4321
13  push 0x654321
14  push 0x87654321
15  push 0xa987654321
16
# nasm -v
NASM version 2.04rc1 compiled on Feb 21 2009
# nasm push.asm -o push.bin
push.asm:4: warning: signed byte value exceeds bounds
push.asm:7: warning: word data exceeds bounds
# ndisasm -b 32 push.bin // 'ndisasm -b 64 push.bin' not works right in this version of NASM.
00000000  6A21              push byte +0x21
00000002  6A21              push byte +0x21
00000004  66682143          push word 0x4321
00000008  66682143          push word 0x4321
0000000C  6821436500        push dword 0x654321
00000011  6821000000        push dword 0x21
00000016  6821430000        push dword 0x4321
0000001B  6821436500        push dword 0x654321
00000020  6821436587        push dword 0x87654321
00000025  6821436587        push dword 0x87654321
于 2012-07-03T02:53:24.093 に答える