什么是C语言中汇编成汇编语言的puts和printf之间的区别

时间:2016-04-30 22:05:20

标签: c gcc assembly

这是我的C程序使用puts()

#include <stdio.h>
int main(void){
puts("testing");
}

使用gcc -S -o sample.s sample.c将其编译成Assembly后,这就是我得到的:

        .file   "sample.c"
        .section        .rodata
.LC0:
        .string "testing"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        movl    $.LC0, (%esp)
        call    puts
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.5 20110214 (Red Hat 4.4.5-6)"
        .section        .note.GNU-stack,"",@progbits

我也这样做,这次我使用的是printf()而不是看跌期权,这就是我得到的:

    .file   "sample.c"
        .section        .rodata
.LC0:
        .string "testing"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        movl    $.LC0, %eax        //this is the difference
        movl    %eax, (%esp)
        call    printf
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.5 20110214 (Red Hat 4.4.5-6)"
        .section        .note.GNU-stack,"",@progbits

以下是我不明白的内容,printf()函数mov $.LC0%eax,然后是mov %eax(%esp) {{1}函数puts()直接传递给mov %.LC0。 我不知道为什么会这样。

1 个答案:

答案 0 :(得分:4)

在汇编级别,两个函数之间的最大区别在于puts()函数只接受一个参数(指向要显示的字符串的指针),而printf()函数将采用一个参数(指向格式字符串的指针),然后,堆栈中的任意数量的参数(printf()是一个可变参数函数)。

请注意,绝对不会检查参数的数量,它只取决于格式字符串中遇到字符%的时间。例如,这种特殊性用于格式化字符串格式的bug开发方法,以交互方式探索进程堆栈的内容。

所以,基本上,区别在于puts()只有一个参数,printf()是一个可变函数。

如果您想更好地理解这种差异,请尝试编译:

#include <stdio.h>

int main(void) {
    printf("testing %d", 10);
}