我是汇编编程的新手,在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的操作数是有效的。这不是一个调试问题 - 所以我的代码出了什么问题?或者是我的汇编程序?
答案 0 :(得分:31)
在64位模式下,您无法推送和弹出32位值;您需要pushq
和popq
。
此外,你不会以这种方式得到正确的退出。在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)
我最近也开始关注这些示例,我发现以下工作:
.code32
添加到汇编代码顶部--32
标志-m elf_i386
标志您可以看到我的示例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。现在是允许的。