1

I am trying to return the number after some operations, but compiler returns push esp, push num, pop esp, pop num invalid instruction operands, although MASM allows push {register}. It's runing on x64, MASM, with Visual Studio (Debug mode x64). What's wrong?

PUBLIC from_asm
EXTERN puts:PROC
EXTERN exit:PROC

.data
   num dd ?

.code

from_asm PROC

mov EAX, not -30
or EAX,21
mov EBX, not 21
and EAX, EBX
or EAX, 23

mov num, eax
mov esp, dword ptr [num]
push esp
push num
call puts
pop num 
pop esp

ret

from_asm ENDP

END

P.S. I checked, that after all operations EAX and num contains number 31.

old_timer
  • 69,149
  • 8
  • 89
  • 168
Handsome Jack
  • 23
  • 1
  • 7
  • 4
    In 64 bit mode you can't push 32 bit registers. So if you are **really** using x64 that's your problem. Also, the calling convention is totally different in 64 bit mode so your `puts` wouldn't work anyway. – Jester Nov 20 '17 at 21:51
  • Usually there's no good reason to `push` or `pop` the stack pointer, why did you add `push esp`? And you definitely don't want to set it up to some bogus value like `mov esp, dword ptr [num]` ... Describe what you are trying to do? If you are trying to return value from function, most of the calling conventions use value in `eax` for that (not stack). And it's not clear, what kind of string pointer you want to give to `puts`. I mean, except the arithmetic instructions, everything else is "gibberish", just delete it, and start again (reread your book/tutorial, and experiment with smaller steps) – Ped7g Nov 20 '17 at 22:12
  • @Ped7g, thx, you guessed right, but i've already tryed to use `eax`, the resul is the same.. This is how I changed: `mov eax, dword ptr [num]; push eax; call puts; pop eax` – Handsome Jack Nov 20 '17 at 22:21
  • what result.. the "invalid instruction operand"? On which line? `push eax` is perfectly legal in 32b code... BUT NOT in 64b code (edited). It's still not clear why you push integer value ahead of `puts` call, that makes no sense. ... You can do `push rax`... it will still make no sense, but it will compile (in 64b). – Ped7g Nov 20 '17 at 22:29
  • 1
    If you want to return the value, then return the value... (i.e. just `ret`, when it is in `eax`). Why do you put there some `puts` and stack operations is not clear. Actually the reasonable guess is, that you are following some 32b tutorial, with wrong calling convention, and that you want to output the value to console (not just to return it), but that's not how `puts` works (can't display integer value, only string), so ... did I write already to delete it all and start again? And get 64b book, or switch to 32b mode and binaries. – Ped7g Nov 20 '17 at 22:36
  • @Ped7g oops, sorry, got it,thanks, i've changed `puts` on `printf`, and changed all registers on `rx`, but there is one new problem: i wrote `mov rax, num` and compiler says that **instruction operands must be the same size**, (now `num dw`) i know that bigger type than _double word_ can be _quadro word_ (qw), but when I change `num dw` on `num qw`compiler return syntax error on `qw`. – Handsome Jack Nov 20 '17 at 22:53
  • 1
    it helps a lot to check documentation of compiler. [Directives Reference Visual Studio 2015](https://msdn.microsoft.com/en-us/library/8t163bt0.aspx) ... the `db/dw/dd/dq` are actually deprecated, you can use `byte/word/dword/qword` directives with modern MASM. And it's `dq` as "define qword", and `dw` is "define word" = 16 bits, not short of "dword" = 32 bits. ... besides that you can still make the function to return just `int` (32bit value), so keep `num` and `eax` usage as it was, only if you would want to store it to stack, then you must `push rax` (but format only 32b). – Ped7g Nov 20 '17 at 23:10
  • Related: [How many bytes does the push instruction pushes onto the stack when I don't specify the operand size?](https://stackoverflow.com/questions/45127993/how-many-bytes-does-the-push-instruction-pushes-onto-the-stack-when-i-dont-spec). But not a duplicate exactly, even though it does make it clear that 32-bit operand-size for `push` is not encodeable in x86-64 code. – Peter Cordes Nov 21 '17 at 01:49
  • You can't port 32-bit code to 64-bit *just* by changing the register names to `rxx`. The calling conventions are different, too. – Peter Cordes Nov 21 '17 at 01:50

0 Answers0