开发者

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

开发者 https://www.devze.com 2023-02-20 14:17 出处:网络
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'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 execute my code, up until I get to using pushl/popl instructions for manipulating the stack. The following code fails to assemble:

 .section .data  # empty

 .section .text
.globl _start
_start:
 pushl $1       # push the value 1 onto the stack
 popl %eax      # pop 1 off the stack and into the %eax register
 int $0x80      # exit the program with exit code '1'

Using "as test.s -o test.o", these errors appear on the termi开发者_高级运维nal and test.o is not created:

test.s: Assembler messages: 
test.s:9: Error: suffix or operands invalid for 'push'
test.s:10:  Error: suffix or operands invalid for 'popl'

I've checked the documentation, and the operands I'm using for pushl and popl are valid. This isn't exactly a debugging question--so what's wrong with my code? Or is it my assembler?


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?


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


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.


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


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

精彩评论

暂无评论...
验证码 换一张
取 消