【发布时间】:2018-01-18 17:21:41
【问题描述】:
我正在尝试在 AT&T 语法汇编中编写一个测试程序,将某些字符的 ascii 值推送到堆栈,然后打印它们。我的代码如下:
.text
.global main
main:
push $0
push $10
push $65
mov $4,%eax
mov $1,%ebx
mov %esp,%ecx
mov $3,%edx
int $0x80
mov $1,%eax
int $0x80
我希望这个程序做的是将 0、10 和 65 压入堆栈,使堆栈为 65、10、0(大写字母 A、换行符、字符串结尾)。将eax 和ebx 设置为写入标准输出的值,并将ecx 设置为堆栈指针,以便它写入堆栈上的内容,而edx 是堆栈上的长度(即3) .当我运行它时,绝对没有任何反应。你能帮我理解我做错了什么以及这里实际发生了什么吗?
【问题讨论】:
-
push将 4 个字节存储到内存中(在 32 位模式下)。因此,您应该只看到您的信A。单个push $0x0a41也应该为您提供换行符。请注意,write()或您的终端并不特别关心终止零,因此只需打印两个字节就足够了。 -
使用我的初始代码,或者使用您建议的单推版本,控制台不会打印任何内容。
-
两者都按照描述在这里工作。然后通过
strace运行您的代码。 -
在调试器中运行,在每个
push之后检查rsp/esp的值,提出质疑。如果它移动了8,您正在将这个 32b linux API 汇编源编译为 64b 二进制文件,这将不起作用,您需要使用syscall而不是int 0x80,并修复参数(syscall服务是不同的)。如果您没有调试器,只需尝试添加mov rax,rcx,这在 32b 模式下应该会失败,但会在 64b 模式下编译)。你绝对需要调试器,并学会使用它。 -
如果您不小心将其编译为 64b 二进制文件:请检查此答案,为什么它不起作用:stackoverflow.com/q/46087730/4271923
标签: linux assembly x86 gnu-assembler att