当前位置:首页 » 编程软件 » c汇编混合编程

c汇编混合编程

发布时间: 2022-02-18 00:12:04

❶ C与汇编语言混合编程

在汇编里调用C函数用LCALL 函数名,变量用PUBLIC声明,在C里面调用汇编只要外部声明汇编的函数接口,即extern 函数名.

❷ C与汇编混合编程!

我建议你不要使用TC了,好像TC不允许,换VC++6.0吧,好使的多
在asm前面加“_”变成“_asm”编译器应该就认了
如果你写一大段,可以这么写,用花括号括起的部分,编译器就认为是汇编代码了
_asm
{
MOV AX,1;
MOV BX,2;
}
如果非要写单行 _asm MOV AX,1; 编译器应该也认
以上VC++ 6.0编译通过

❸ C/C++与汇编混合编程有什么好处

当需要C/C++与汇编混合编程时,可以有以下两种处理策略:

  • 若汇编代码较短,则可在C/C++源文件中直接内嵌汇编语言实现混合编程。

  • 若汇编代码较长,可以单独写成汇编文件,最后以汇编文件的形式加入项目中,通过ATPCS规定与C程序相互调用及访问

  • 后缀.S文件中的汇编指令是用armasm汇编器进行汇编的,而c语言程序中的内嵌汇编指令则是用内嵌汇编器进行汇编的。这两种汇编器存在一定的差异,所以在内嵌汇编时要注意以下几点。

  • 2.3.1 小心使用物理寄存器

  • 必须小心使用物理寄存器,如R0~R3、IP(R12)、LR(R14)和CPSR中的N、Z、C、V标志位。因为计算汇编代码中的C表达式时,可能使用这些物理寄存器,并会修改N、Z、C、V标志位。

  • 如计算:

  • y=x+x/y;

  • [cpp] view plain

  • 1. __asm

  • 2. {

  • 3. MOV R0, x //把x的值给R0

  • 4. ADD y, R0, x/y //计算x/y时R0的值会被修改

  • 5. }

  • 2.3.2 内嵌汇编程序中允许使用C变量

  • 在计算x/y时R0会被修改,从而影响R0+x/y的结果。内嵌汇编程序中允许使用C变量,用C变量来代替寄存器R0可以解决上述问题。这时内嵌汇编器将会为变量var分配合适的存储单元,从而避免冲突的发生。如果内嵌汇编器不能分配合适的存储单元,它将会报告错误。

  • [cpp] view plain

  • 1. int var;

  • 2. __asm

  • 3. {

  • 4. MOV var, x //把x的值给R0

  • 5. ADD y, var, x/y //计算x/y时R0的值会被修改

  • 6. }

  • 2.3.3 不需要保存和恢复用到的寄存器

  • 对于在内嵌汇编语言程序中用到的寄存器,编译器在编译时会自动保存和恢复这些寄存器,用户不用保存和恢复这些寄存器。除了CPSR和SPSR寄存器外,其他物理寄存器在读之前必须先赋值,否则编译器会报错。

  • [cpp] view plain

  • 1. int fun (int x)

  • 2. {

  • 3. __asm

  • 4. {

  • 5. STMFD SP!, {R0} //保存R0,先读后写,汇编出错

  • 6. ADD R0, x, #1

  • 7. EOR x, R0, x

  • 8. LDMFD SP!, {R0} //多余的

  • 9. }

  • 10. return x;

  • 11. }

❹ 如何C语言与汇编混编

c语言可以嵌套汇编:
按照TC2.0的帮助系统所以说的,在TC2.0下是可以用汇编的,方法是使用asm关键字:其格式是:
asm opcode <operands> <;newline>,如同别的注释一样,<>之间的表示可选的;例如:

main()
{
char *c="hello,world/n/r$";
asm mov ah,9;asm mov dx,c;asm int 33;
printf("You sucessed!/n");

}
或者是:

main()
{
char *c="hello,world/n/r$";
asm mov ah,9
asm mov dx,c
asm int 33
printf("You sucessed!");
}
两种格式其实是一种.如果你用的是第一种的样式,记住:
每一句汇编语句都要以asm开头,如果一行内有多个句子,
那么千万不要忘记在两个句子之间的这个semicolon(分号),
但是最后一句汇编后面(如果后面没有其它的语句)的分号可有可无,象第一个例子中的
asm int 33;后面的分号就可以不要,因为它的后面没有其它
的语句了.但如果是这样:
asm mov ah,9; asm mov dx,c;asm int 33; printf("You sucessed!");
那么asm int 33;后面的分号便还是留下好,以免出现编译错误!
在这一点上颇象C语言.

还有一种格式是
asm{ assembly language statement},这种格式应该被普遍的欢迎.
它们的例子如下(其中的语句排列格式与上面两种相同):
asm{
mov ax,var1
add ax,var2
......
}
但是要注意这种格式TC2.0是不支持的!
只有后来的TC++3.0及后来的IDE支持!

工具的使用:
一旦你的C源文件里包括了这些好东西,则必须用TCC.EXE的COMMAND-LINE来编译,具体的命令参数TCC.EXE已经提供,这里不复阐述了.最简单的是:TCC C源文件名(使用这个方法,TCC会自动调用TASM.EXE和TLINK.EXE,并且能够使TLINK.EXE正确的找到需要的.obj和.lib文件,如果你单步编译的话,可能会碰到很多的问题,主要是TLINK.EXE它自己并不会去找.obj和.lib文件,你自己可以建一个.bat文件,如果要指定.lib文件的目录的话可以用/L参数,在文章的后面有一个例子).但大家要注意了,看一下你的TC目录下面到底是否有TASM.EXE文件,并在TURBOC.CFG(这个文件包括TCC.EXE运行期参数,这里面所有参数在运很期都将被自动TCC.EXE使用,例如:-IH:/TC/INCLUDE/
-LH:/TC/LIB/)文件中设置好一些参数,并确认TASM.EXE的版本号要2.0以上,以及是否能够向下兼容.但是在大多数的情况下TC的目录是没有TASM.EXE的,或是版本不正常.
如果你有TASM.EXE文件并且TURBOC.CFG文件也已经写好了,但是还要注意一个
问题:运行TCC.EXE时要在独立的DOS SHELL下面(不要害怕,这不是一个新东西,我的意思
是,不在诸如TC下的DOS SHELL下面运行,我曾经败在这个问题下,当我发现时直想揍电脑
一顿,还好没有,不然就没有这篇文件了.)
还有一句重要的话:TC2.0支持大部分8086指令(当然用法有一些约定,不过现在我并不打算
进行详细说明,因为那是一件很繁杂的事,以后有时间或许会写出来----如果大家需要的话).
如果说上面我所说的那些约定很繁杂的话,那么下面的方法该是多么简单啊!
让我们使用Borland为TC2.0内建的变量来进行伪汇编.
或许你还不知道在TC2.0中还有一些内建的pseudo寄存器(可以看作是register 型的变量,但是它们比register型的变量好用的多)
_AX,_AH,_AL,
_BX,_BH,_BL,
_CX,_CH,_CL,
_DX,_DH,_DL,
_DI,_SI,_SP,
_CS,_DS,_ES,_SS
注意这些寄存器的size,_AX,_BX,_CX,_DX,_CS,_DS,_ES,_SS,_SI,_DI,_SP等都是16位的寄存器相当于C语言的unsigned int类型,其余的都是8位的寄存器(相当于unsigned char)(TC怎么可能支持32位的寄存呢,所以EAX等是不能用的,FS,GS和IP寄存器都是无效的),还有就是在传递参数的时候千万不要忘记使用强制类型转换.
中断调用指令是:__int__(interrupt_#)(注意int的前辍和后辍都是两个underscores)
For example:
#include<dos.h>
unsigned int _stklen=0x200;
unsigned int _heaplen=0;

main()
{
_DX=(unsigned int)"Hello,world./r/n$";
_AX=0x900;
__int__(0x21);

}
dos.h它是包含__int__()内建中断调用语句的头文件,因此是不可
缺少的._stklen和_heaplen是定义运行期堆栈和堆大小的两个内部
引用变量(这是个我自己想的名词,意指如果这两个变量在源文件中
显式的声明了,那么编译程序会自会引用来构造编译时期的信息以产生
用户希望的目标文件,如果不显式的声明则编译程序自动确定).
这两个变量也有一些约定,如果_stklen不显式声明,_heaplen赋值为零
都表示栈和堆都是defult的.
最后在TC2.0中还有一个没有说明的标志位寄存器flags,它也是内建
pseudo寄存器是:_FLAGS,是一个16位寄存器.这些内建的寄存器都可以进行
运算,但是要注意它们所代表的类型(必要时进行类型转换);
看起来这是不是一种好的办法啊(而且使用这种方法只要用个一个dos.h头文件就好,
不需要用TCC编译,可以直接在TC20的IDE下编译).
TC2.0中也提供了一些简单好用的函数来实现对DOS功能的调用如:
int86(...),int86x(...)(但是这些方法实际仍然要调用函数,所以不如使用
伪寄存器,又因为要牵涉到union REGS结构的内存分配所以系统的开销是增大了,
而使用伪寄存器是最简洁的),端口通信函数如:inportb(...),inport(...),
outportb(...),outport(...),指针转换函数:FP_OFF,FP_SEG,MK_FP,这些函数在
帮助系统中都有,有用时大家可以查阅.

tlinkbat.bat的例子:
rem The lib environment variable is the directory of the .obj and .lib file
set lib=h:/tc/lib/
rem 这下面的句子中的c0s(C 零S)是一个.OBJ文件,是一个C程序的STARTUP文件
tlink %lib%c0s %1,%1,%1,/L%lib%emu.lib %lib%maths.lib %lib%cs.lib
set lib=
(使用时可将以rem开头的句子删除)

___________________________________________________
一些约定:
我们先说一下在TC20下写汇编(内联汇编--自己起的名字,大家可以想叫什么叫什么)时的编译器的编译原则:
1.所有在main()函数外的的汇编语言的语句都作为数据声明语句处理,也即在编译器编译时会将它放在数据段中,如:
asm string1 db "Hello",,,'world!',0ah,0xd,"$"
main()
{
asm mov dx,offset string1
asm mov ah,9
asm int 33
asm mov dx,offset string2
asm int 33
}
asm string2 db "the string can be declared after the main() function!$"
象这些样子在main()外面的汇编语言的数据定义语句(事实上不管是什么汇编语句,
只要是在main()之外,包括这个句子:asm mov ax,0x4c00),在编译后都放在数据段中,而C语言的数据声明语句仍按C的规则!
2.所有在main()函内的汇编语言的语句在编译后都放在代码段中,包括这个句子:
asm string2 db "the string can be declared after the main() function!$"
3.不要在以asm 开头的语句中使用C语言的关键字,这会导致编译阶段的错误

那么,根据这三条大家会得到什么样的结论呢?(先闭上眼想一想,你可能会由此变的
很赞赏自己,是的你应该这样相信自己是对的!)
让我们一起看一下这个结论:
1.根据编译原则1得到:不可以在main()外面写汇编命令语句(不要笑,正是与C语言相同才值得注意!),在任何地方都不要进行任何的段定义和宏定义(这是因为编译后的形式决定的,也即:在TC20下所有的汇编格式的语句只能是,直接性的数据定义和语句指令)!
2根据编译原则2得到:不可以在main()之内使用汇编的语句进行数据定义(同样不要笑,
大多数人在第一次在TC20下写汇编都会有这样的错误的)
3.如同类强制类型这样的事是不可以在以asm开头的汇编语句中使用的
好了,天即朗,气瞬清!这样一说,一个大体的框架就出来了!只要遵守这个原则写,就可避免很多莫名其妙的错误出现!
通俗的说:
汇编语句的数据定义放在main()外面,指令放在main()里面.
如果你没有更好的文档,那么记住我的这些话!

一些细节的问题:
在以asm开头的内联汇编语句中是不支持C的转义字符的,但是用C语言声明一个字符数组(含有转义字符的),然后用int 33 ah=9这功能时输出这个字符串时,其中的转义字符是有效的(这主要是因为编译后其内部表示形式不同造成的,自己想想会有答案的).
内联汇编支持C的一些如数值表示,字符串声明格式等,
如:一个十六进制的数据可以用两种方式表示:0xa 和0ah,字符串可以是这样:
"Hello,world!$"(如同C)也可以这样'Hello,world!$'(用汇编自己的方式).
象C一样你同样要注意赋值的类型,而且要比C更严格(汇编从来不自己动手做
如同类型转换啊这样事),所以一切的事完全要你自己做好!而且你不要企图以C的形式
做这件事,如这样的格式 asm mov dx,(unsigned)a(a是一个这样的东西,
char a[ ]="hello,world!";),而且这样句子也会导致错误:asm mov dx,word ptr a(逻辑错误),不过这不是在编译时的错误,而是运行期的错误(具体的原因自己想一想,象word label这样的东西的运算作用和会导致的后果),你可以这样用一个句子做"中间人"如int i=(unsigned)a;asm mov dx,i(也千万不要用asm mov dx,(unsigned)a 这样的句子.但是,告诉大家一个好消息,你可以用指针指向一个字符串,然后你会惊讶你竟然可以这样:
char *p="hello,world";asm mov dx,p,然后用int 33 ah=9的功能输出这个字符串而不会有错误(这也表现出指针的特点,它是一个二字节的(TC20下)变量,含有的是一个地址,这与其指向的变量的类型是毫无关系的).
内汇汇编语句不支持->这个运算符.还有标号的问题,在最后的例子中你会年看到一些特别之处!

上面所说的只是很细小并微少的一些事(也是很常遇到的),尚有很多的细节要说,但由于本人时间有限不能一一列举,如C的结构在内联汇编的应用等大家可以按照其运行机理去想想一下用法;另外,由于这只是一件学习的事,所以还是大家自己学(找一下有关文档,当然现在已经没有什么比较完整的了),情况会好的多,我在对内联汇编的学习过程中领会到了不少的东西,例如编译原理方面的知识,以及如何做会使代码更高效,占空间最少等的方法.最后向大家推荐一种方法,在利用TCC的-S开关可以生成C源文件的汇编代码
(或许很多的人都用过)是很好的学习材料!祝大家学有所成!

Cstarter
02-11-17

/* 由于个人的时间和能力有限,难免有错误和不详细的地方,请大家见谅!
My Email:[email protected] [email protected] QQ:170594633 */
一些例子:
下面这个例子是对沈美明 温冬婵的
<<IBM-PC 汇编语言程序设计>>清华版第十一章程序的改写
可直接在命令行上键入 tcc filename 就可以,当然你要有TASM.EXE
/*
asm mus_frep dw 330,294,262,294,3 p(330)
asm dw 3 p(294),330,392,392
asm dw 330,294,262,294,4 p(330)
asm dw 294,294,330,294,262,-1
asm mus_time dw 6 p(25),50
asm dw 2 p (25,25,50)
asm dw 12 p(25),100
*/
asm mus_frep dw 330,392,330,294,330,392,330,294,330
asm dw 330,392,330,294,262,294,330,392,294
asm dw 262,262,220,196,196,220,262,294,330,262
asm dw -1
asm mus_time dw 3 p (50),25,25,50,25,25,100
asm dw 2 p (50,50,25,25),100
asm dw 3 p (50,25,25),100

main()
{
asm jmp start
/*设置发声的频率,这一段在沈美明 温冬婵的
<<IBM-PC 汇编语言程序设计>>清华版第十一章有详细的说明 */

sound:
asm mov al,0b6h
asm out 43h,al
asm mov dx,12h
asm mov ax,533h*896
asm div di
asm out 42h, al
asm mov al,ah
/* 这个延时是用来防止两次IO操作的最后一次操作的错误,
因为CPU比总线的速度快很多,所以 要延时等待第一次操作完成后再进行第二次操作*/

asm mov cx,1000
delay:
asm loop delay

asm out 42h,al
asm in al,61h
asm mov ah,al
asm or al,3
asm out 61h,al

/* 使用中断15H功能86H延时CX:DX=微秒数*/
asm mov ax,2710h
asm mul bx
asm mov cx,dx
asm mov dx,ax
asm mov ah,86h
asm int 15h /*可用__int__(0x15);代替*/

asm mov al,ah
asm out 61h,al
asm jmp add_count
/*------------------*/
start:
asm mov si,offset mus_frep
asm lea bp,mus_time
frep:
asm mov di,[si]
asm cmp di,-1
asm je end_mus
asm mov bx,[bp]
asm jmp sound
add_count: /*标号不能用汇编语言写*/
asm add si,2
asm add bp,2
asm jmp frep
end_mus:;

}

对于上面的程序大家可用伪寄存器的方法写一个,要容易的多!

/*一个发声程序!(引自<<PC技术内幕>>电力版--这个版不好,不如清华版的)*/
#include"dos.h"
main()
{
static union REGS ourregs;
outportb(0x43,0xb6);
outportb(0x42,0xee);
outportb(0x42,0);
outportb(0x61,(inportb(0x61)|0x03));
ourregs.h.ah=0x86;
ourregs.x.cx=0x001e;
ourregs.x.dx=0x8480;
int86(0x15,&ourregs,&ourregs);
outportb(0x61,(inportb(0x61)&0xfc));
}

❺ 为什么要C和汇编混合编程

依我的看法,上面两位说的都不对:
一楼:汇编语言是低级语言直接往硬件的寄存器里写入东西:
其实C语言和汇编语言都一样,都会编译成二进制文件机器语言烧录到单片机中,所以没有一楼所说的区别

二楼:在C中也不会有数据损失的,如果你定义好数据类型的话。

单片机中是将C编译成汇编,然后根据汇编编译成机器语言---可执行文件;
其实单片机中经常在C中嵌入汇编,主要是因为时间的关系,因为一条汇编语言执行的时间都是可以知道的,而C指令执行的时间是不可知的,因为C编译器不一样,编译后的汇编也是不一样的,如果用汇编就不会有这种情况。所以在一些精确延时的场合,要嵌入汇编
另外,C的可移植性较强,不同的单片机里,功能要求相同的可以直接拿去用
总之,汇编是程序员可以自己翻译成机器语言的,所以单片机的运行是可以完全掌握的

❻ c语言和汇编语言的混合编程方法主要有哪些

C语言在实际应用中,为了完成某种特定的功能,或需要缩短程序的运行时间,或需要对硬件进行直接操作,或需要利用操作系统的某些功能模块,这时就会使用到汇编语言程序,即要采用C语言与汇编语言的混合编程技术实现。

C与汇编语言的混合编程方法,为C语言应用开发人员提供方便。汇编语言开发的程序代码短、执行速度快,而C语言是应用广泛的面向过程的开发语言。通过给出混合编程的方法、约定规则以及实现的具体步骤,说明了混合编程需要注意的问题,最后给出了相应的实例。

(6)c汇编混合编程扩展阅读:

汇编语言具有更高的机器相关性,更加便于记忆和书写,但又同时保留了机器语言高速度和高效率的特点。汇编语言仍是面向机器的语言,很难从其代码上理解程序设计意图,设计出来的程序不易被移植,故不像其他大多数的高级计算机语言一样被广泛应用。所以在高级语言高度发展的今天,它通常被用在底层,通常是程序优化或硬件操作的场合。

❼ 汇编语言和c/c++的混合编程通常有哪四种方式

1、在C和C++代码中内联汇编
2、使用C、C++程序调用汇编库
3、反汇编C和C++代码,在汇编码上进行优化,最后编译
4、汇编调用C库

❽ C语言和汇编语言混合编程实现99秒马表

自己写,编你那程序,有优点,也没有优点了,自找麻烦

❾ 单片机C编程和汇编混合编程

需要用汇编的:
1. 时间较短、但精确度要求高的延时子程序
2. 编译器未提供支持的特殊汇编指令,包括某些协处理器指令等
3. 单片机性能有限、但出于种种原因(抠门的老板、产品兼容、生产能力)又不允许变更硬件平台的情况下,需要对关键模块充分优化,有时只能用汇编来写以求达到最高效能
4. 有时候某些特殊功能寄存器(SFR)或存储器映射I/O操作必须用汇编,以规避C/C++编译器的一些天然限制
欢迎继续补充。

❿ 汇编语言和C语言的混合编程

是什么显示啊?是LED点阵显示吗?

热点内容
万网云服务器云虚拟主机 发布:2025-01-15 18:20:58 浏览:945
手动安装交叉编译链 发布:2025-01-15 18:15:30 浏览:563
java调用clinux 发布:2025-01-15 18:13:02 浏览:293
如何给孩子配置一份保险 发布:2025-01-15 18:07:53 浏览:456
思科模拟器ftp配置 发布:2025-01-15 18:01:53 浏览:196
wd软件如何修改密码 发布:2025-01-15 17:59:57 浏览:715
公共代理服务器地址 发布:2025-01-15 17:59:53 浏览:818
android文件图片 发布:2025-01-15 17:39:44 浏览:206
linux的路径怎么写 发布:2025-01-15 17:18:49 浏览:185
php解压程序 发布:2025-01-15 17:06:22 浏览:142