给出以下代码:
.section .rodata
str: .string "Hello World!\n"
input: .long 2
########
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
pushl $str
call printf
#return from printf:
movl $0, %eax
movl %ebp,%esp
popl %ebp
ret
输出将是“Hello World!”。
<小时 />现在我尝试从用户那里获取一个号码,然后将其打印在屏幕上,但是 它不起作用(代码编译,但我做错了)。 我的错误在哪里?
.section .rodata
input: .long 2
########
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
pushl %ebx
call scanf # call scanf to get number from the user
popl input # store the number entered by user in input (variable)
pushl input # push it back into the stack
call printf # print input
#return from printf:
movl $0, %eax
movl %ebp,%esp
popl %ebp
ret
请您参考如下方法:
我不太确定您使用的是哪种汇编器,但是我可以让您的代码使用 gcc 进行编译,因此我坚持使用您的格式风格(不是谈论 AT&T 语法)。
无论如何,你应该检查 documentation对于 scanf
并意识到它需要一个格式字符串和指针,指向内存中存储读入值的位置。它还>返回成功读取的项目数,而不是读取的内容。
现在做同样的事情并检查 documention对于printf
。您将看到需要格式字符串才能以可读形式打印您的号码。合适的格式字符串是 "%d\n"
来打印数字和换行符。
您的代码现在可能看起来像这样(它可以使用 gcc 编译并正常工作):
.section .rodata
input_format: .string "%d"
output_format: .string "%d\n"
.section .bss
input: .long 0 # reserve 4 bytes of space
.section .text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
pushl $input # push the ADDRESS of input to have the value stored in it
pushl $input_format # give scanf the ADDRESS of the format string
call scanf # call scanf to get number from the user
addl $8, %esp # clean up the stack
# Note the return value of scanf is passed through eax (same for printf)
pushl input # pass the number to printf BY VALUE
pushl $output_format # pass the ADDRESSS of the output format string to printf
call printf # print input
#return 0 from main:
movl $0, %eax
movl %ebp,%esp
popl %ebp
ret
请注意,我通常会使用 db/dw/dd
在 .(ro)data
和 .bss
部分中分配内存,如下所示与 .string
和 .long
相反,因此如果该部分做得稍有错误,您可以修复它。
您还可以使用堆栈空间来存储数字,但是您已经声明了 input
,并且我希望代码尽可能与您的代码相似。对于 scanf
和 printf
之前和之后的所有其他内容也是如此,我只是将其保留为您的代码。
编辑:这是使用堆栈创建局部变量的示例,而不是在 .bss
或 .data< 中声明变量
段:
.section .rodata
input_format: .string "%d"
output_format: .string "%d\n"
.section .text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $4, %esp # allocate 4 bytes on the stack for a local variable
# The local variable will be at -4(%ebp)
leal -4(%ebp), %eax # get the ADDRESS of our local variable
pushl %eax # push the ADDRESS of the variable on the stack
pushl $input_format # give scanf the ADDRESS of the format string
call scanf # call scanf to get number from the user
addl $8, %esp # clean up the stack
# Note the return value of scanf is passed through eax (same for printf)
pushl -4(%ebp) # pass the number to printf BY VALUE
pushl $output_format # pass the ADDRESSS of the output format string to printf
call printf # print the input
#return from printf:
movl $0, %eax
movl %ebp,%esp
popl %ebp
ret