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

max*_*axm 27 x86 assembly 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'
Run Code Online (Sandbox Code Playgroud)

使用"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'
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*nin 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
Run Code Online (Sandbox Code Playgroud)

(当然,每个push/ pop序列都可以用简单的mov(类似mov $60, %eax)替换;我想你正在尝试显式测试pushpop优化代码大小,或者避免0机器代码中的字节(对于漏洞有效载荷))


有关:

  • 您可能需要查看英特尔的手册:http://www.intel.com/products/processor/manuals/index.htm(这完整且可读性很强,但很大). (4认同)
  • 哪里可以找到关于32/64之间差异的好参考?即我可以将哪些资源与本书结合使用以在64位上编程? (2认同)

aga*_*gam 14

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

  1. 添加.code32到汇编代码的顶部
  2. --32国旗组装
  3. 链接-m elf_i386国旗

你可以在这里看到我的例子


Gun*_*iez 7

您需要替换push/pop序列

pushq $1       # push the value 1 onto the stack
popq %rax      # pop 1 off the stack and into the %eax register
Run Code Online (Sandbox Code Playgroud)

请注意错误消息是" 后缀或操作数无效",您只检查了OR错误消息中逻辑的第二部分,可能是因为您不确定后缀的含义:它是"l".

编辑:请参阅托马斯的答案,以解释为什么你的代码无论如何都无法运行,即使它汇编了.