汇编简单代码不会打印输出

时间:2011-12-16 04:34:08

标签: assembly

给出以下代码:

    .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

此致 罗恩

2 个答案:

答案 0 :(得分:3)

您对scanf的参数不正确,您需要同时推送扫描格式和缓冲区来保存您要查找的类型,然后,如果它们不是字符串,则需要推送新的格式字符串printf,在本例中为"%d"

它看起来有点像这样(对不起它的Intel / MASM格式):

SUB ESP,4 ;make stack space for an int
LEA EAX,[ESP]
PUSH EAX
PUSH offset NumberString ;"%d"
CALL scanf
PUSH [ESP+8] ;our scanned number
PUSH offset NumberString ;"%d"
CALL printf
ADD ESP,14 ;clean up for the cdecl funcs and the alloc'ed stack space

答案 1 :(得分:3)

我不确定你使用的是什么类型的汇编程序,但是我可以使用gcc编译你的代码,所以我坚持你的格式化风格(不是谈论AT& T语法)。

无论如何,您应该检查scanf printf,并意识到它需要格式字符串指针到内存中的位置存储读入的值。它还返回成功读取的项目数,而不是读取的内容。

现在执行相同操作并检查"%d\n" .section .rodata input_format: .string "%d" output_format: .string "%d\n" .section .bss input: .long .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 from printf: movl $0, %eax movl %ebp,%esp popl %ebp ret 。您将看到需要格式字符串才能以可读的形式打印您的号码。一个合适的格式字符串是db/dw/dd来打印数字和换行符。

您的代码现在看起来像这样(使用gcc为我编译和工作正常):

.(ro)data

请注意,我通常会使用.bss来分配.string.long部分中的内存而不是inputscanf,所以如果该部分是做得有点不对,你可以解决它。

您也可以使用堆栈空间来存储数字,但是您已经声明了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 或{{1}}段中声明变量:

{{1}}