第 7 章教学重点第 7章介绍实际应用当中,
常见的混合编程问题,重点是参数传递方法
混合编程的两种方式
模块连接的约定规则
模块连接的参数传递方法
C++代码优化第 7 章 什么是混合编程
多种程序设计语言间,通过相互调用,
参数传递,共享数据结构和数据信息而形成程序的过程就是混合编程
程序的大部分采用高级语言编写,以提高程序的开发效率;在某些部分,
利用汇编语言编写,以提高程序的运行效率第 7 章 混合编程方法
嵌入式汇编 ——
在 C/C++语言中直接使用汇编语言语句,
简洁直观,功能较弱
模块连接 ——
两种语言分别编写独立的程序模块,分别产生目标代码 OBJ文件,然后进行连接,
形成一个完整的程序
使用灵活,功能强,要解决参数传递问题第 7 章 混合编程的关键问题
建立不同语言之间的接口
在不同格式的两种语言间提供有效的通讯方式,作出符合两种语言调用约定的某种形式说明,实现两种语言间的程序模块互相调用,
变量的相互传送以及参数和返回值的正确使用第 7 章 7.1 Turbo C嵌入式汇编方式
格式
asm 操作码 操作数 <;或换行 >
举例
asm mov ax,ds;
asm pop ax; asm pop ds; asm ret;
asm push ds
第 7 章 若干注意事项
操作码支持 8086/8087指令或若干伪指令:
db/dw/dd和 extern
操作数是操作码可接受的数据:立即数,
寄存器名,还可以是 C语言程序中的常量,
变量和标号等
内嵌的汇编语句可以用分号,;”结束,也可以用换行符结束
使用 C的注释,如 / * … * /
正确运用通用寄存器,标号等
/ * LT702.C */
#include <stdio.h>
void upper(char *dest,char *src)
{ asm mov si,src
/* dest和 src是地址指针 */
asm mov di,dest
asm cld
loop,asm lodsb /* C语言定义的标号 */
asm cmp al,'a'
asm jb copy /* 转移到 C的标号 */
asm cmp al,'z'
asm ja copy
/* 不是 ’ a’到 ’ z’之间的字符原样复制 */
例 7.2- 1/2
asm sub al,20h /*小写字母转换成大写 */
copy,asm stosb
asm and al,al
/* C语言中,字符串用 NULL( 0) 结尾 */
asm jnz loop
}
main()/* 主程序 */
{
char str[]="This Started Out As Lowercase!";
char chr[100];
upper(chr,str);
printf("Origin string:\n%s\n",str);
printf("Uppercase String:\n%s\n",chr);
}
例 7.2- 2/2
第 7 章 7.2 Turbo C模块连接方式
要注意模块连接的约定规则
命名约定:汇编语言过程应采用 C语言类型
声明约定
寄存器使用约定
存储模式约定:采用 相同的存储模式
参数传递是关键
通过堆栈传递入口参数
通过寄存器返回出口参数; 汇编语言子程序,lt703s.asm
.model small,c ;小型存储模式
.data
msg db ’Hello,C and Assembly ! $’
.code
PUBLIC display
display proc
mov ah,9 ;小型模式不必设置 DS
mov dx,offset msg;寄存器 AX和 DX无须保护
int 21h
ret
display endp
end
例 7.3- 1/2
/* C语言程序,lt703.c */
extern void display(void);
/* 说明 display是外部函数 */
main()
{ display();
}
利用汇编程序编译汇编语言程序成目标代码文件:
ML/c lt703s.asm
利用 C编译程序编译 C程序,连接目标代码文件:
TCC -ms -Iinclude -Llib lt703.c lt703s.obj
例 7.3- 2/2; 汇编语言子程序,lt704s.asm
.model small,c
PUBLIC min
.code
min proc ;小型模式,为近过程
push bp
mov bp,sp
mov ax,[bp+4] ;取第 1个参数
cmp ax,[bp+6] ;与第 2个参数比较
jle minexit
mov ax,[bp+6] ;保存返回值
minexit,pop bp
ret
min endp
end
例 7.4- 1/3
图示
large
6
8
8
L; 汇编语言子程序,lt704.asm
.model small,c
PUBLIC min
.code
min proc,var1:word,var2:word
mov ax,var1 ;取第 1个参数
cmp ax,var2 ;与第 2个参数比较
jle minexit
mov ax,var2 ;保存返回值
minexit,pop bp
ret
min endp
end
例 7.4- 2/3
/* C语言程序,lt704.c */
extern int min(int,int);
main()
{ printf(“%d”,min(100,200));
}
小型模式编译程序和连接:
TCC -ms -Iinclude -Llib lt704.c lt704s.obj
大型模式编译程序和连接:
TCC -ml -Iinclude -Llib lt704.c lt704l.obj
例 7.4- 3/3
第 7 章 7.3 汇编语言在 Visual C++中的应用
Visual C++逐渐将 MASM融合进去
嵌入汇编语言指令
调用汇编语言过程
Visual C++集成开发环境
编译汇编语言程序
调试汇编语言程序
应用之一:优化 C++代码第 7 章 7.3.1 嵌入汇编语言指令
格式
_ _asm { 指令 }
举例
int power2(int num,int power)
{
_ _asm
{
mov eax,num
mov ecx,power
shl eax,cl
} // 返回 EAX=EAX× (2^CL)
}
第 7 章 7.3.2 调用汇编语言过程
必须遵循共同的约定规则
命名约定
声明约定
寄存器使用约定
存储模式约定
参数传递约定
采用一致的调用规范
声明共用函数和变量
正确传递入口参数和返回参数第 7 章 32位汇编语言过程
用,386p等处理器伪指令说明采用的指令集
32位逻辑段环境
有些指令在 32位段与 16位段有差别
采用平展模式 ( flat)
汇编时采用选项 /coff;汇编语言子程序,lt714f.asm
.386p
.model flat,c
PUBLIC power2
.code
power2 proc
push ebp
mov ebp,esp
mov eax,[ebp+8] ;取第 1个参数
mov ecx,[bp+12] ;取第 2个参数
shl eax,cl
pop ebp
ret ;返回 EAX
power2 endp
end
例 7.14- 1/3
图示;汇编语言子程序,lt714f.asm
.386p
.model flat,c
PUBLIC power2
.code
power2 PROC,num:dword,power:dword
mov eax,num ;获取参数
mov ecx,power
shl eax,cl ;计算
ret ;EAX存放返回值
power2 ENDP
end
例 7.14- 2/3
// C++语言程序,lt714.cpp
# include <iostream.h>
extern,c”{int power2(int,int);}
void main(void)
{
cout<<“2的 6次方乘 5等于,\t”;
cout<<power2(5,6)<<endl;
}
将汇编语言程序汇编成目标代码文件:
ML/c /coff lt714f.asm
在 Visual C++6.0编译环境下创建项目,
插入汇编成的目标代码文,然后编译连接例 7.14- 3/3
// C++程序,LT715.CPP
#include <iostream.h>
extern "C" {long isum(int,int *);}
int imin(int,int *);
void main(void)
{
const int SIZE=10;
int array[SIZE];
int temp;
cout<<"请输入 10个整数,"<<endl;
for(temp=0;temp<SIZE;temp++)
cin>>array[temp];
cout<<endl;
cout<<"整数数据之和,\t"<<isum(SIZE,array)<<endl;
cout<<"其中最小值为,\t"<<imin(SIZE,array)<<endl;
}
例 7.15- 1/4
//求 itmp个元素的数组 iarray的最小数
int imin(int itmp,int iarray[])
{
__asm {
mov ecx,itmp
jecxz minexit ;个数为 0,返回
dec ecx
mov esi,iarray
mov eax,[esi]
jecxz minexit ;个数为 1,返回
minlp,add esi,4
cmp eax,[esi] ;比较两个数据的大小
jle nochange
mov eax,[esi] ;取得较小值
nochange,loop minlp
minexit:
}}
例 7.15- 2/4;汇编语言子程序,LT715F.ASM
.386p
.model flat,c
.code;32位有符号数据的求和过程
isum proc uses ecx esi,\
count:dword,darray:PTR
mov ecx,count ;个数为 0,和为 0
xor edx,edx
xor eax,eax
jecxz sumexit
mov esi,darray ;个数为 1,和为本身
mov eax,[esi]
dec ecx
jecxz sumexit
例 7.15- 3/4
sumlp,add esi,4
add eax,[esi] ;计算低 32位
adc edx,0 ;计算高 32位
loop sumlp
sumexit,ret
isum endp
end
例 7.15- 4/4
将汇编语言程序汇编成目标代码文件:
ML/c /coff lt715f.asm
在 Visual C++6.0编译环境下创建项目,
插入汇编成的目标代码文件,然后编译连接第 7 章 7.3.3 使用汇编语言优化 C++代码
例 7.16:在整数数组查找一个数值,查找过程需要进行大量循环
C++代码 ( lt716.cpp)
Debug调试版本,81000( 0.046ms)
Release发布版本,31000( 0.018ms)
嵌入汇编语言编写查找函数
使用串操作指令,41000 ( 0.023 ms)
不使用串操作指令,31000( 0.018ms)
在简单情况下,Visual C++的优化技术已经非常有效;但仍然可用汇编代码进行改进第 7 章 7.3.4 使用 Visual C++开发汇编语言程序
新建工程项目,选择 32位控制台或窗口应用程序
输入磁盘目录,工程名称,并选择创建一个空白工程
新建汇编语言源程序文件
输入源程序文件名以及扩展名 ASM,加入工程项目
通过工程菜单的设置命令展开工程设置窗口
在命令文本框中输入进行汇编的命令
在输出文本框输入汇编后目标模块文件名
调用创建命令进行汇编语言程序的汇编和连接
注意在 VisualC++环境确定包含文件的路径第 7 章 汇编语言程序的调试过程
工具菜单的选项命令展开调试标签页进行设置
通用下选中十六进制显示
反汇编窗口下要选中代码字节
存储器窗口下选中固定宽度,后面填入数字 16
在编辑窗口源程序的语句行,按 F9键,设置断点
使用运行,单步执行等命令进行
开各种窗口观察程序当前的运行状态
存储器窗口查看变量
反汇编窗口有反汇编的实际执行代码
寄存器窗口显示处理器的寄存器内容第 7章 教学要求
1,熟悉嵌入式和模块连接两种混合编程方法
2,了解模块连接混合编程的约定规则
3,熟悉模块链接混合编程的参数传递方法
4,了解 32位环境的混合编程方法
常见的混合编程问题,重点是参数传递方法
混合编程的两种方式
模块连接的约定规则
模块连接的参数传递方法
C++代码优化第 7 章 什么是混合编程
多种程序设计语言间,通过相互调用,
参数传递,共享数据结构和数据信息而形成程序的过程就是混合编程
程序的大部分采用高级语言编写,以提高程序的开发效率;在某些部分,
利用汇编语言编写,以提高程序的运行效率第 7 章 混合编程方法
嵌入式汇编 ——
在 C/C++语言中直接使用汇编语言语句,
简洁直观,功能较弱
模块连接 ——
两种语言分别编写独立的程序模块,分别产生目标代码 OBJ文件,然后进行连接,
形成一个完整的程序
使用灵活,功能强,要解决参数传递问题第 7 章 混合编程的关键问题
建立不同语言之间的接口
在不同格式的两种语言间提供有效的通讯方式,作出符合两种语言调用约定的某种形式说明,实现两种语言间的程序模块互相调用,
变量的相互传送以及参数和返回值的正确使用第 7 章 7.1 Turbo C嵌入式汇编方式
格式
asm 操作码 操作数 <;或换行 >
举例
asm mov ax,ds;
asm pop ax; asm pop ds; asm ret;
asm push ds
第 7 章 若干注意事项
操作码支持 8086/8087指令或若干伪指令:
db/dw/dd和 extern
操作数是操作码可接受的数据:立即数,
寄存器名,还可以是 C语言程序中的常量,
变量和标号等
内嵌的汇编语句可以用分号,;”结束,也可以用换行符结束
使用 C的注释,如 / * … * /
正确运用通用寄存器,标号等
/ * LT702.C */
#include <stdio.h>
void upper(char *dest,char *src)
{ asm mov si,src
/* dest和 src是地址指针 */
asm mov di,dest
asm cld
loop,asm lodsb /* C语言定义的标号 */
asm cmp al,'a'
asm jb copy /* 转移到 C的标号 */
asm cmp al,'z'
asm ja copy
/* 不是 ’ a’到 ’ z’之间的字符原样复制 */
例 7.2- 1/2
asm sub al,20h /*小写字母转换成大写 */
copy,asm stosb
asm and al,al
/* C语言中,字符串用 NULL( 0) 结尾 */
asm jnz loop
}
main()/* 主程序 */
{
char str[]="This Started Out As Lowercase!";
char chr[100];
upper(chr,str);
printf("Origin string:\n%s\n",str);
printf("Uppercase String:\n%s\n",chr);
}
例 7.2- 2/2
第 7 章 7.2 Turbo C模块连接方式
要注意模块连接的约定规则
命名约定:汇编语言过程应采用 C语言类型
声明约定
寄存器使用约定
存储模式约定:采用 相同的存储模式
参数传递是关键
通过堆栈传递入口参数
通过寄存器返回出口参数; 汇编语言子程序,lt703s.asm
.model small,c ;小型存储模式
.data
msg db ’Hello,C and Assembly ! $’
.code
PUBLIC display
display proc
mov ah,9 ;小型模式不必设置 DS
mov dx,offset msg;寄存器 AX和 DX无须保护
int 21h
ret
display endp
end
例 7.3- 1/2
/* C语言程序,lt703.c */
extern void display(void);
/* 说明 display是外部函数 */
main()
{ display();
}
利用汇编程序编译汇编语言程序成目标代码文件:
ML/c lt703s.asm
利用 C编译程序编译 C程序,连接目标代码文件:
TCC -ms -Iinclude -Llib lt703.c lt703s.obj
例 7.3- 2/2; 汇编语言子程序,lt704s.asm
.model small,c
PUBLIC min
.code
min proc ;小型模式,为近过程
push bp
mov bp,sp
mov ax,[bp+4] ;取第 1个参数
cmp ax,[bp+6] ;与第 2个参数比较
jle minexit
mov ax,[bp+6] ;保存返回值
minexit,pop bp
ret
min endp
end
例 7.4- 1/3
图示
large
6
8
8
L; 汇编语言子程序,lt704.asm
.model small,c
PUBLIC min
.code
min proc,var1:word,var2:word
mov ax,var1 ;取第 1个参数
cmp ax,var2 ;与第 2个参数比较
jle minexit
mov ax,var2 ;保存返回值
minexit,pop bp
ret
min endp
end
例 7.4- 2/3
/* C语言程序,lt704.c */
extern int min(int,int);
main()
{ printf(“%d”,min(100,200));
}
小型模式编译程序和连接:
TCC -ms -Iinclude -Llib lt704.c lt704s.obj
大型模式编译程序和连接:
TCC -ml -Iinclude -Llib lt704.c lt704l.obj
例 7.4- 3/3
第 7 章 7.3 汇编语言在 Visual C++中的应用
Visual C++逐渐将 MASM融合进去
嵌入汇编语言指令
调用汇编语言过程
Visual C++集成开发环境
编译汇编语言程序
调试汇编语言程序
应用之一:优化 C++代码第 7 章 7.3.1 嵌入汇编语言指令
格式
_ _asm { 指令 }
举例
int power2(int num,int power)
{
_ _asm
{
mov eax,num
mov ecx,power
shl eax,cl
} // 返回 EAX=EAX× (2^CL)
}
第 7 章 7.3.2 调用汇编语言过程
必须遵循共同的约定规则
命名约定
声明约定
寄存器使用约定
存储模式约定
参数传递约定
采用一致的调用规范
声明共用函数和变量
正确传递入口参数和返回参数第 7 章 32位汇编语言过程
用,386p等处理器伪指令说明采用的指令集
32位逻辑段环境
有些指令在 32位段与 16位段有差别
采用平展模式 ( flat)
汇编时采用选项 /coff;汇编语言子程序,lt714f.asm
.386p
.model flat,c
PUBLIC power2
.code
power2 proc
push ebp
mov ebp,esp
mov eax,[ebp+8] ;取第 1个参数
mov ecx,[bp+12] ;取第 2个参数
shl eax,cl
pop ebp
ret ;返回 EAX
power2 endp
end
例 7.14- 1/3
图示;汇编语言子程序,lt714f.asm
.386p
.model flat,c
PUBLIC power2
.code
power2 PROC,num:dword,power:dword
mov eax,num ;获取参数
mov ecx,power
shl eax,cl ;计算
ret ;EAX存放返回值
power2 ENDP
end
例 7.14- 2/3
// C++语言程序,lt714.cpp
# include <iostream.h>
extern,c”{int power2(int,int);}
void main(void)
{
cout<<“2的 6次方乘 5等于,\t”;
cout<<power2(5,6)<<endl;
}
将汇编语言程序汇编成目标代码文件:
ML/c /coff lt714f.asm
在 Visual C++6.0编译环境下创建项目,
插入汇编成的目标代码文,然后编译连接例 7.14- 3/3
// C++程序,LT715.CPP
#include <iostream.h>
extern "C" {long isum(int,int *);}
int imin(int,int *);
void main(void)
{
const int SIZE=10;
int array[SIZE];
int temp;
cout<<"请输入 10个整数,"<<endl;
for(temp=0;temp<SIZE;temp++)
cin>>array[temp];
cout<<endl;
cout<<"整数数据之和,\t"<<isum(SIZE,array)<<endl;
cout<<"其中最小值为,\t"<<imin(SIZE,array)<<endl;
}
例 7.15- 1/4
//求 itmp个元素的数组 iarray的最小数
int imin(int itmp,int iarray[])
{
__asm {
mov ecx,itmp
jecxz minexit ;个数为 0,返回
dec ecx
mov esi,iarray
mov eax,[esi]
jecxz minexit ;个数为 1,返回
minlp,add esi,4
cmp eax,[esi] ;比较两个数据的大小
jle nochange
mov eax,[esi] ;取得较小值
nochange,loop minlp
minexit:
}}
例 7.15- 2/4;汇编语言子程序,LT715F.ASM
.386p
.model flat,c
.code;32位有符号数据的求和过程
isum proc uses ecx esi,\
count:dword,darray:PTR
mov ecx,count ;个数为 0,和为 0
xor edx,edx
xor eax,eax
jecxz sumexit
mov esi,darray ;个数为 1,和为本身
mov eax,[esi]
dec ecx
jecxz sumexit
例 7.15- 3/4
sumlp,add esi,4
add eax,[esi] ;计算低 32位
adc edx,0 ;计算高 32位
loop sumlp
sumexit,ret
isum endp
end
例 7.15- 4/4
将汇编语言程序汇编成目标代码文件:
ML/c /coff lt715f.asm
在 Visual C++6.0编译环境下创建项目,
插入汇编成的目标代码文件,然后编译连接第 7 章 7.3.3 使用汇编语言优化 C++代码
例 7.16:在整数数组查找一个数值,查找过程需要进行大量循环
C++代码 ( lt716.cpp)
Debug调试版本,81000( 0.046ms)
Release发布版本,31000( 0.018ms)
嵌入汇编语言编写查找函数
使用串操作指令,41000 ( 0.023 ms)
不使用串操作指令,31000( 0.018ms)
在简单情况下,Visual C++的优化技术已经非常有效;但仍然可用汇编代码进行改进第 7 章 7.3.4 使用 Visual C++开发汇编语言程序
新建工程项目,选择 32位控制台或窗口应用程序
输入磁盘目录,工程名称,并选择创建一个空白工程
新建汇编语言源程序文件
输入源程序文件名以及扩展名 ASM,加入工程项目
通过工程菜单的设置命令展开工程设置窗口
在命令文本框中输入进行汇编的命令
在输出文本框输入汇编后目标模块文件名
调用创建命令进行汇编语言程序的汇编和连接
注意在 VisualC++环境确定包含文件的路径第 7 章 汇编语言程序的调试过程
工具菜单的选项命令展开调试标签页进行设置
通用下选中十六进制显示
反汇编窗口下要选中代码字节
存储器窗口下选中固定宽度,后面填入数字 16
在编辑窗口源程序的语句行,按 F9键,设置断点
使用运行,单步执行等命令进行
开各种窗口观察程序当前的运行状态
存储器窗口查看变量
反汇编窗口有反汇编的实际执行代码
寄存器窗口显示处理器的寄存器内容第 7章 教学要求
1,熟悉嵌入式和模块连接两种混合编程方法
2,了解模块连接混合编程的约定规则
3,熟悉模块链接混合编程的参数传递方法
4,了解 32位环境的混合编程方法