1

I'm trying to make a simple x86 program that reverses a string, in this case: "ciao".

section .data
        msg db "ciao"
        len equ $ - msg

section .text
global _start
_start:
        lea eax, [msg]
        mov ebx, len
        add eax, ebx-1
reverseloop:
        push [eax]
        sub eax, 1
        cmp eax, [msg]
        jl reverseloop

When I try to assemble it, I get the error:

main.asm:14: error: operation size not specified

So, I tried to specify the size, by modifying line 14 to:

push byte [eax]

And now I get the error:

main.asm:14: error: invalid combination of opcode and operands

I don't really understand what is the problem here.
The command I use to compile is:

nasm -f elf32 main.asm -o main.o

1
  • 2
    In 32-bit modes push with a memory operand only supports pushing a word or a dword. You can't push a byte. So you could only do push word [eax] or push dword [eax] but you can't do push byte [eax] . See an Instruction Set Architecture document like: felixcloutier.com/x86/push Commented Jan 5, 2023 at 22:23

1 Answer 1

4
push [eax]

NASM does not know the size of the memory operand that you would like to push. You need to specify it as push dword [eax].
It is not an option to use push byte [eax] because the stack operations don't do single bytes.

add eax, ebx-1

This is your next error! The source operand ebx-1 is invalid.
You could first decrement EBX and then add that to EAX, but as I will show below you don't need this decrement.

cmp eax, [msg]
jl reverseloop

This is not doing what you want either. The cmp compares EAX to a dword from memory, but you want this to be a comparison between addresses. Use cmp eax, msg.
And in order to continu the loop for all characters of the string, you need to conditionally jump for as long as the address in EAX is GreaterOrEqual msg.

  mov   eax, msg
  add   eax, len
reverseloop:
  dec   eax
  movzx ebx, byte [eax]
  push  ebx
  cmp   eax, msg
  ja    reverseloop

Now I don't see how this code will reverse anything. The characters land on the stack in the same order as they were in the memory (interspersed with some zero bytes of course).

  mov   eax, msg
  mov   ecx, len
reverseloop1:
  movzx ebx, byte [eax]
  push  ebx
  inc   eax
  dec   ecx
  jnz   reverseloop1

  mov   eax, msg
  mov   ecx, len
reverseloop2:
  pop   ebx
  mov   [eax], bl
  inc   eax
  dec   ecx
  jnz   reverseloop2

Solutions that don't use the stack exist and generally would be better.

Sign up to request clarification or add additional context in comments.

2 Comments

lea eax, [eax+ebx-1] is a valid instruction that can do what they were trying to. Oh, but ebx was set with mov ebx, len so that's silly, just mov eax, msg+len-1 or transform like you did.
For push, it's interesting that NASM will default to DWORD operand-size for immediates like push 123, but requires disambiguation of word vs dword for memory operands like push [eax]. It's probably just as rare that you'd ever want push word [mem] as push word immediate, but that's the design choice NASM made. But probably even more important to be explicit about memory operand sizes for push and pop; bugs with that might be less obvious.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.