[TakeLionOS汇编与C语言自学笔记-第四课]
版权所有 2021年 江志剑
按照《21天学通C语言》(第七版),有如下二个例子。其中一个改为输出黑桃符号,是练习题3修改一下的:
//1、files:helloxy.c helloxy.i helloxyno.s helloxy.exe
#include
int x,y;
int main(void)
{
for (x = 0; x < 10;x++, printf("\n"))
for ( y = 0; y < 10; y++)
printf("X");
return 0;
}
//2、files:helloxyq.c helloxyq.i helloxyqno.s helloxyq.exe
#include
int x,y;
int main(void)
{
for (x = 0; x < 10;x++, printf("\n"))
for ( y = 0; y < 10; y++)
printf("%c",6);
return 0;
}
我是用GCC 8.1.0在命令行窗口运行的。
GCC编译时候,其实有四个步骤:
1、预处理:gcc -E hello.c -o hello.i
2、编译生成汇编语言:gcc -S hello.i -o hello.s
3、汇编:gcc -c hello.s -o hello.o
4、链接生成可执行文件:gcc hello.o -o hello
这时候,我想看一下第二步生成的汇编语言代码。
因为本身就是研究操作系统的一部分,所以要研究底层的汇编语言。
结果发现是AT&T格式的汇编语言风格,而且大量使用汇编宏。
所以启用了GCC的编译选项-fno-asynchronous-unwind-tables,直接预处理为cfi宏的汇编指令。
这里就是包含*no.s形式的文件。
比较发现,第一个文件和第二个文件,其余基本一样,但是第20行不一样了:
helloxy.s:movl $88, (%esp) //大写X
helloxyq.s:movl $6, (%esp) //黑桃
也没有出现.ascii宏,因为不是输出字符串了,而是输出字符X和黑桃符号。
最后的LEAVE指令,等效于“MOV ESP,EBP”和“POP EBP”两条指令。
这个指令调整了数据栈指针ESP,并将EBP的数值恢复到调用这个函数之前的初始状态。
毕竟函数要在退出之前恢复这些寄存器的值。