日常運行程序時,我們經常要用到輸入輸出函數。輸入經常來自於鍵盤,輸出經常用於屏幕。而C語言標準庫提供了相應的函數scanf和printf。
scanf函數和printf函數的函數原型是:
int scanf(const char *format, ...);
int printf(const char *format, ...);
可以看出它們都是參數可變的函數。
舉個例子。
#include <stdio.h>
int main(void)
{
int a;
int b;
int c;
scanf("%d %d",&a,&b);
c=a+b;
printf("sum=%d\n",c);
return 0;
}
鍵盤輸入
12 32
輸出
sum=44
scanf函數接受的是"%d %d",一個整數加空格加一個整數。輸入符合要求,所以得到了需要的輸入。
將以上C代碼轉爲彙編代碼。
.section .rodata
.LC0:.string "%d %d"
.LC1:.string "sum=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
leal -4(%ebp),%eax
pushl %eax
leal -8(%ebp),%eax
pushl %eax
pushl $.LC0
call scanf
addl $12,%esp
movl -4(%ebp),%eax
addl -8(%ebp),%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC1
call printf
addl $8,%esp
movl $0,%eax
leave
ret
當我們要調用一個函數時,需要傳入參數,而這裏scanf接受3個參數,leal -4(%ebp),%eax pushl %eax取a的地址,並傳入棧中。leal -8(%ebp),%eax pushl %eax取b的地址,並傳入棧中。將.LC0的地址傳入棧中。調用scanf完成函數的調用,之後函數進入scanf函數內部執行,直至scanf函數的ret指令執行,函數返回到call scanf下一條執令。addl $12,%esp,清理參數佔用的棧空間。這樣完成了scanf函數的調用。同理,printf也是如此。