我正在尝试编写一个简单的程序,从键盘获取字符串,然后将其打印到屏幕上。到目前为止,我无法让它发挥作用。
代码如下:
.section .rodata
output: .string "you entered %s\n"
input: .string "%s"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $100, %esp
pushl $input
call scanf
movl %ebp, %esp
subl $100, %esp
pushl $output
call printf
xorl %eax, %eax
movl %ebp, %esp
popl %ebp
ret
当我执行它时,对于任何给定的输入,输出都是 you entered (null)
。 当我将 subl $100, %esp
命令(call print
之前的命令)的偏移量设置为 subl $104, %esp
我得到 you entered %s
,当偏移量设置为 108 时,我得到 you entered *gibberish*
。
我觉得这是一个我需要猜测 scanf
将字符串保存在堆栈中的位置的游戏(为什么它不在它应该在的位置?)。
我正在使用 IA32 指令集。
如有任何帮助,我们将不胜感激。
请您参考如下方法:
基本上你的程序有3个问题:
subl $100, %esp
pushl $input
# Error 1:
# As Frank Kotler already wrote at this point
# only $input is stored on the stack; however
# the address of the buffer must also be on
# the stack (see Frank Kotler's comment)
call scanf
movl %ebp, %esp
# Error 2:
# Now the buffer is below ESP.
# Because interrupts use the kernel stack they
# will not overwrite the memory below ESP.
# However signals will destroy the memory below
# ESP!!
#
# Instead of the lines:
# movl %ebp, %esp
# subl $100, %esp
#
# You should use something like this:
# add $8, %esp
# or:
# lea -100(%ebp), %esp
#
subl $100, %esp
# Error 3:
# As for "scanf" the second argument
# is missing on the stack
pushl $output
call printf