x86 Assembly pushl/popl don't work with “Error: suffix or operands invalid”

后端 未结 5 706
逝去的感伤
逝去的感伤 2020-11-29 01:45

I\'m a newbie to assembly programming, working through Programming Ground Up on an Ubuntu x86_64 desktop with GNU assembler v2.20.1.

I\'ve been able to assemble/link

相关标签:
5条回答
  • 2020-11-29 02:24

    I ran into this error working through the same book. I created the following shell script (att.sh):

    #!/bin/sh
    as --32 $1.s -o $1
    ld -melf_i386 $1.o -o $1
    ./$1
    echo $?
    

    Which I then made executable and ran (assuming an input file myfile.s):

    chmod +x ./att.sh
    ./att.sh myfile
    
    0 讨论(0)
  • 2020-11-29 02:27

    You may push any value without push command like that

    decq %rsp
    movb $0, (%rsp)
    

    push 1 byte on stack and pop after

    movb (%rsp), %al
    incq %rsp
    

    And any other size. As compilator don't generate any error and all will work good! To address may use rbp register instead of rsp. Now is allowed.

    0 讨论(0)
  • 2020-11-29 02:35

    You need to replace the push/pop sequence with

    pushq $1       # push the value 1 onto the stack
    popq %rax      # pop 1 off the stack and into the %eax register
    

    Note the error message is "suffix or operand invalid", you only checked the second part of the logical OR in the error message, maybe because you weren't exactly sure what the suffix means: it's the "l".

    Edit: Please see Thomas answer for an explanation why your code won't work anyway even if it assembles.

    0 讨论(0)
  • 2020-11-29 02:42

    I recently started following these examples too, I found the following worked:

    1. Add .code32 to the top of your assembly code
    2. Assemble with the --32 flag
    3. Link with the -m elf_i386 flag

    You can see my example here

    0 讨论(0)
  • 2020-11-29 02:48

    In 64-bit mode you cannot push and pop 32-bit values; you need pushq and popq.

    Also, you will not get a proper exit this way. On 32-bit x86, you would need to set %eax to 1 to select the exit() system call, and set %ebx to the exit code you actually wish. On 64-bit x86 (that's what you are using), conventions are different: the system call number for exit() is 60, not 1; the first system call parameter goes in %rdi, not %rbx; the system-call invocation opcode is not int $0x80 but the special, x86-64-only opcode syscall.

    Which leads to:

    .section .data
    .section .text
    .globl _start
    _start:
        pushq   $60
        popq    %rax
        pushq   $1
        popq    %rdi
        syscall
    

    (each push/pop sequence can be replaced with a simple mov (like mov $60, %eax) of course; I suppose that you are trying to explicitly test push and pop, optimize for code-size, or avoid 0 bytes in the machine code (for an exploit payload))


    Related:

    • What are the calling conventions for UNIX & Linux system calls on i386 and x86-64
    • What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
    0 讨论(0)
提交回复
热议问题