今天研究出了一个小问题,在C语言里引用汇编的变量,会是什么结果,,汇编中的变量没有像C语言中int类型那样的类型约束,可以把数据当作任何类型处理,那么传到C语言中我们应该当作什么类型处理呢。
换句话说,在汇编里定义变量var,在C语言里引用,我们肯定要用extern声明var外部变量,那么extern后面接什么类型?难道是extern int var么?还是extern short var
实例:
注意:混合编译的方法,gcc test.s main.c 这样直接用gcc处理汇编和C语言文件就可以自动搞定。
一、
汇编程序:(是的,就这么短小)
.globalvar#注意现在的汇编器不再要求被C语言引用的变量名前加下划线.datavar:.fill10,4,9#填充10个单元,每个单元4字节,每个单元的值为9
C语言:
#include<stdio.h>externintvar;//现在的C语言编译器引用汇编变量可以使用和汇编变量同样的名字,写成_var反而会错误voidmain(){printf(“sizeof(var)=%d\n”,sizeof(var));printf(“%d\n”,var);}
程序的输出为
sizeof(int)=49
解释很简单,
没错吧,这就是说我们在汇编里定义的变量,来到C语言里可以任意声明为任意类型,从sizeof的输出也能看出,我们把var声明成多大,它就是多大。
三、
我们再试试别的,汇编语句保持和上一个一样,依然是
.fill10,2,9#10个单元,每个单元填入9,每单元大小为2B
我们改变C语言语句,把var声明成
externlonglongvar;//8字节整型
当然,输出语句稍微变下,因为是long long型整数,所以要这么输出printf(“%lld\n”, var);
#include<stdio.h>externlonglongvar;voidmain(){printf(“sizeof(var)=%d\n”,sizeof(var));printf(“%lld\n”,var);}
我们还是事先猜测结果,字节太多我不画图了,按照上面的的思路,这次取出8字节当作long long变量var的值,那么应该是0x0009000900090009,化为十进制是2533313445691401。
看看程序运行结果:
预测正确。
四、
再来,把var声明为char变量。
#include<stdio.h>externcharvar;#声明为charvoidmain(){printf(“sizeof(var)=%d\n”,sizeof(var));printf(“%c\n”,var);}
输出语句相应的改变成%c
汇编里面稍微改改填充的数值,因为9是制表符的ASCII码,输出了你也看不到。我们改成填充43
.fill10,2,43#10个单元,每个单元填入43(内存实际存储按照二进制来的),每单元大小为2B
注意43的十六进制表示为0x2b,这是加号“+”的ASCII码,
内存里面长成这样
五、
好吧,再这么整下去也没完了,下面用一个数组定义来终结此文吧。
汇编语言代码和上一个一样,
.fill10,2,43
C语言修改成:
#include<stdio.h>typedefcharCHARARR[20];//CHARARR是一个类型别名,用它定义的每一个变量都是包含20个字符的数组externCHARARRvar;//var被定义为CHARARR类型,是一个包含20个元素的char型数组。voidmain(){printf(“sizeof(var)=%d\n”,sizeof(var));inti=0;while(i<=19){printf(“[%c]”,var[i]);//用[]括起来更容易看出输出现象i++;}printf(“\n”);}
我们让var成为数组,含有20个元素,正好把汇编里面的 10单元x2字节 共计20个字节包括了。
然后用循环逐个输出,为什么要这么做而不用%s呢,因为数组里有很多字节是0x00,这是字符串终止标志。%s会被打断的。
结果如下:
可以看到和预计的一样,20个元素以ASCII码 0x2b 0x00 0x2b 0x00。。。。这样的数组顺序挨个输出。
讲完了,C语言和汇编语言结合起来是不是强大到了难以想象的地步,随心所欲操纵内存数据。
本文出自 “mirage1993” 博客,请务必保留此出处
最好的节约是珍惜时间,最大的浪费是虚度年华。