Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 495 Vote(s) - 3.45 Average
  • 1
  • 2
  • 3
  • 4
  • 5
64-bit mode does not support 32-bit PUSH and POP instructions

#1
NASM returns an error like: "instruction not supported in 64-bit mode"
(Or with YASM, `invalid size for operand 1`)

The subject instructions are `pop ecx` and `push ecx`.
What can I use instead of them or is there an other way to fix this issue?
Reply

#2
*The general idea* is that you normally push and pop full registers, i.e. 64-bit registers in 64-bit mode. `push`'s default operand-size is 64-bit, and 32-bit operand-size is not available.

[To see links please register here]

(yes, unless you specifically use a 16-bit push, but 32-bit isn't available).

You cannot push a 32 bit register in 64 bit mode; instead, you can push and pop the whole 64 bit register that contains a 32-bit value you want, so that's `push rax` instead of `push eax`. The same holds for memory references - you can `push qword ptr[rax]`, but not `push dword ptr[rax]`.

*But*: even in 64 bit mode you can still push:

- 8 or 32 bit immediates sign extended to 64; this is generally handled automatically by your assembler as an optimization (if you do `push 1` it will encode it with the most compact encoding, which will be `6A01`, i.e. with an *imm8* operand). It's [always a 64-bit push unless you explicitly specify `push word 1`][1], regardless of what width of immediate the assembler picks.

- the `fs` and `gs` segment registers *but not* the `cs`, `ds`, `es`, `ss` registers (which aren't important in 64-bit mode, and can only be read with [`mov`][2], not `push`, freeing up those push/pop opcode for potential future use).

As an exception, segment registers are either *zero*-extended or pushed on the stack with a 16-bit move (i.e. the other 48 bit on the stack are left unmodified); this isn't really much of a problem, since `pop fs` and `pop gs` just discard these extra bits.

You can emulate a `push imm64` with `push low32` / `mov dword [rsp+4], high32`. Or with `mov r64, imm64` / `push r64`; `mov` to register (not memory) is the only x86-64 instruction that can take a 64-bit immediate.

----

With 16-bit operand-size (a `66h` prefix), you can do a 16-bit push which adjusts RSP by 2 instead of 8. But normally don't do this because it will misalign the stack until you do a 16-bit pop or otherwise correct it.

- 16 bit registers (`push ax`) and memory references (`push word ptr[rax]`);
- 8-bit sign-extended or 16 bit immediates. `push word 123`

----

8-bit registers can't be pushed in any mode (except as part of a wider register), and 32-bit push/pop aren't available in 64-bit mode, [even with a `REX.W=0` prefix][1].


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through