上面,我们主要以C程序调用汇编子程序的情况介绍了两者进行混合编程的问题。虽然,汇编语言程序调用C语言函数的情况不经常使用,但这是可以实现的。本节简单说明这种混合编程的方法。
EXTERN 被调用函数名∶函数属性 EXTERN 变量名∶变量属性 |
例7.11:汇编语言程序调用C函数计算正弦值,并显示
/* C语言程序:lt711.c */
#include #define PI 3.1415926 /* 定义常量 */ extern void asub(void); main() { asub(); } void sincall(int angle) /* 显示给定度数的正弦值的函数 */ { double radian; radian=PI*angle/180.0; /* 度转换成弧度 */ printf("%f\n",sin(radian)); /* 计算,并显示结果 */ } ; 汇编语言程序:lt711L.asm .model large,c extern sincall:far ;外部函数sincall public asub .data sinangle dw 35 .code asub proc mov ax,@data mov es,ax push es:sinangle call sincall ;调用显示正弦值的C函数 add sp,2 ret asub endp end
例7.12:80x86微处理器识别程序
/* C语言程序:lt712.c */
#include
extern void get_cpu_type(void); extern char cpu_type; main() { get_cpu_type(); printf(“Your Personel Computer Has a“); switch(cpu_type){
case 0: printf(“n 8086/8088 Processor !\n”);break;
case 2: printf(“n 80286 Processor !\n”);break; case 3: printf(“n 80386 Processor !\n”);break; case 4: printf(“n 80486 Processor !\n”);break; case 5: printf(“ Pentium Processor !\n”);break; case 6: printf(“ Pentium Pro Processor !\n”);break; default: printf(“n unknown Processor !\n”); } } ; 汇编语言程序:lt610.asm .model small,c .386P public cpu_type, get_cpu_type CPU_ID MACRO ;处理器识别指令 DB 0FH,0A2H ;CPUID指令的机器代码:0F A2 ENDM .data cpu_type db 0 intel_id db "GenuineIntel" .code get_cpu_type proc ;8086判定:8086标志寄存器的最高4位总是1,根据此特性判断是否为8086 get8086:pushf pop ax and ax,0fffh push ax ;替换当前标志寄存器(欲使D 15~D 12复位) popf pushf pop ax ;得到新标志寄存器内容 and ax,0f000h cmp ax,0f000h ;如果D 15~D 12仍置位,则为8086/8088 mov cpu_type,0 ;设置CPU类型变量为0 jnz get286 ;不是8086,则转向判定80286 ret ;80286判定:实方式下,80286标志寄存器的最高4位总是0,根据此特性判断是否为80286 get286:pushf pop ax or ax,0f000h push ax popf pushf pop ax and ax,0f000h mov cpu_type,2 ;设置CPU类型变量为2 jnz get386 ret
;80386判定:EFLAFS的AC标志(D
18)是在80486才引入的,在80386中该位不能改变
;现在可以使用80386的指令 get386: pushfd pop eax mov ecx,eax ;保存原来EFLAGS xor eax,40000h ;求反D 18 push eax popfd pushfd pop eax xor eax,ecx ;不能改变AC标志,为80386 mov cpu_type,3 jz end_type push ecx popfd ;恢复EFLAGS ;CPUID指令判定:能否改变EFLAGS中的ID标志(D 21),说明是否可以使用CPUID指令 get486: mov cpu_type,4 ;现在至少是80486 mov eax,ecx ;取得原来EFLAGS xor eax,200000h ;求反D 21 push eax popfd pushfd pop eax xor eax,ecx jz end_type ;不能改变ID标志,是80486 ;下面用CPUID指令判定处理器类型 get586: mov eax,0 ;设置EAX=0 CPU_ID ;执行CPUID指令,得到厂商标识串 cmp dword ptr intel_id,ebx jne end_type cmp dword ptr intel_id[+4],edx jne end_type cmp dword ptr intel_id[+8],ecx jne end_type ;判断是否为Intel的产品 cmp eax,1 ;判断EAX是否可以取值为1时执行CPUID指令 jl end_type mov eax,1 ;设置EAX=1 CPU_ID ;执行CPUID指令,得到CPU说明信息 and eax,0f00h ;取得处理器类型 mov cpu_type,ah ;设置CPU类型 end_type: ret get_cpu_type endp end |