x86程序集pushl / popl不能与“错误:后缀或操作数无效”

时间:2011-03-30 11:04:09

标签: assembly x86 x86-64

我是汇编编程的新手,在GNU汇编程序v2.20.1的Ubuntu x86_64桌面上使用Programming Ground Up工作。

我已经能够组装/链接执行我的代码,直到我使用pushl / popl指令来操作堆栈。以下代码无法汇编:

 .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'

使用“as test.s -o test.o”,这些错误出现在终端上并且没有创建test.o:

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

我已经检查了文档,我正在使用的pushl和popl的操作数是有效的。这不是一个调试问题 - 所以我的代码出了什么问题?或者是我的汇编程序?

5 个答案:

答案 0 :(得分:31)

在64位模式下,您无法推送和弹出32位值;您需要pushqpopq

此外,你不会以这种方式得到正确的退出。在32位x86上,您需要将%eax设置为1以选择exit()系统调用,%ebx设置为您实际希望的退出代码。在64位x86(这就是您正在使用的)上,约定是不同的:exit()的系统调用号是60,而不是1;第一个系统调用参数位于%rdi,而不是%rbx;系统调用操作码不是int $0x80,而是特殊的,仅限x86-64的操作码syscall

导致:

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

(每个push / pop序列当然可以用简单的mov替换(如mov $60, %eax};我想您正在尝试显式测试{{ 1}}和push,针对代码大小进行优化,或者避免机器代码中的pop字节(对于漏洞利用负载))


相关:

答案 1 :(得分:14)

我最近也开始关注这些示例,我发现以下工作:

  1. .code32添加到汇编代码顶部
  2. 使用--32标志
  3. 进行汇总
  4. -m elf_i386标志
  5. 的链接

    您可以看到我的示例here

答案 2 :(得分:7)

您需要用

替换推/弹序列
pushq $1       # push the value 1 onto the stack
popq %rax      # pop 1 off the stack and into the %eax register

请注意错误消息是“后缀或操作数无效”,您只检查了错误消息中逻辑OR的第二部分,可能是因为您不确定是什么后缀表示:它是“l”。

编辑:请查看托马斯的答案,了解为什么即使代码汇编,您的代码也无法正常运行。

答案 3 :(得分:2)

我在同一本书中遇到了这个错误。 我创建了以下shell脚本(att.sh):

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

然后我创建了可执行文件并运行(假设输入文件为myfile.s):

chmod +x ./att.sh
./att.sh myfile

答案 4 :(得分:-1)

你可以在不使用push命令的情况下推送任何值

decq %rsp
movb $0, (%rsp)

在堆栈上按1个字节

后弹出
movb (%rsp), %al
incq %rsp

以及任何其他尺寸。编译器不会产生任何错误,一切都会好起来的!要解决可能使用rbp寄存器而不是rsp。现在是允许的。