[TakeLionOS汇编与C语言自学笔记-第六课]
版权所有 2021年 江志剑
按照《21天学通C语言》(第七版),有如下一个例子P17。
将整个程序的代码,包括行号显示出来:
//1、files:hellolistit.c hellolistitno.s hellolistit.exe
/* hellolistit.c - 该程序将显示整个程序的代码,包括行号! */
#include <stdio.h>
#include <stdlib.h>
#define BUFF_SIZE 256
void display_usage(void);
int line;
int main(int argc, char *argv[])
{
char buffer[BUFF_SIZE];
FILE *fp;
if (argc < 2)
{
display_usage();
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Error opening file, %s!", argv[1]);
return (1);
}
line = (1);
while (fgets(buffer, BUFF_SIZE, fp) != NULL)
fprintf(stdout,"%4d:\t%s", line++, buffer);
fclose(fp);
return 0;
}
void display_usage(void)
{
fprintf(stderr, "\nProper Usage is:");
fprintf(stderr, "\n\nhellolistit filename.ext\n");
}
我是用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形式的文件。
最后的LEAVE指令,等效于“MOV ESP,EBP”和“POP EBP”两条指令。
这个指令调整了数据栈指针ESP,并将EBP的数值恢复到调用这个函数之前的初始状态。
毕竟函数要在退出之前恢复这些寄存器的值。
问题是其中的注释中文字符,输出的时候会出现乱码?这个问题暂时解决不了。
用了-fexec-charset=gbk 和-finput-charset=gbk,也解决不了。
这里面汇编指令也有很多问题。
今天太迟了,就不继续下去了。