汇编程序从堆栈中写入字符

Posted

技术标签:

【中文标题】汇编程序从堆栈中写入字符【英文标题】:Assembly program to write character from stack 【发布时间】: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、换行符、字符串结尾)。将eaxebx 设置为写入标准输出的值,并将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 二进制文件:请检查此答案,为什么它不起作用:***.com/q/46087730/4271923 【参考方案1】:

每条push 指令将 4 个字节压入堆栈。所以,这就是int 0x80 之前堆栈的样子:

   ....
----------  (highest address)
|  0x00  |
---------- 
|  0x00  |
---------- 
|  0x00  |
---------- 
|  0x00  |
---------- <-- push $0
|  0x00  |
---------- 
|  0x00  |
---------- 
|  0x00  |
---------- 
|  0x0A  | 
---------- <-- push $10
|  0x00  |
---------- 
|  0x00  |
---------- 
|  0x00  |
---------- 
|  0x41  |
---------- <-- push $65 <-- ESP

但是,此时您希望堆栈看起来像:

   ....
---------- 
|  0x00  |
---------- 
|  0x0A  |
---------- 
|  0x41  |
---------- <-- ESP

这可以通过将您的 push 指令替换为以下内容来实现:

push $0x0a41

即:

.text
.global main
main:
    push $0x0a41

    mov $4,%eax    ;system call write()
    mov $1,%ebx    ;file descriptor (stdout)
    mov %esp,%ecx  ;string
    mov $3,%edx    ;length of the string
    int $0x80

    mov $1,%eax
    int $0x80

edx 寄存器中你已经指定了字符串的长度(即:3),NUL 字符是没有意义的(你实际上是把它发送到stdout)。

【讨论】:

使用该 push 语句并将 edx 设置为 3 也不会打印任何内容。 如果您使用的是 64 位系统,则需要汇编和链接为 32 位代码才能正常工作。 正确:使用gcc -m32

以上是关于汇编程序从堆栈中写入字符的主要内容,如果未能解决你的问题,请参考以下文章

yongc语言编写单片机程序,出现了堆栈溢出情况,怎么解决?堆栈指针怎么初始化?

我可以从堆栈中间弹出吗?

为啥我不能从字符堆栈中弹出元素?

程序一 用记事本建立文件src.dat,其中存放若干字符。编写程序,从文件src.dat中读取数据,统计其中的大写字母小写字母数字其它字符的个数,并将这些数据写入到文件test.dat中。

试编写一个算法从检查一个Java语言中的大括号方括号小括号是不是配对,若能够全?

堆栈练习3—行编辑程序