老狐狸和珅在线阅读:怎么把tc 和 汇编 连接到一个程序里啊

来源:百度文库 编辑:中科新闻网 时间:2024/05/05 23:42:06
有没有一个实例啊
两个文件
一个是.c的 一个是.asm的
高手教给我啊
不胜感激

在C程序中使用内联汇编语言

MSPGCC试图在最大程度上和其它MSP430的C工具链兼容,内联汇编语言也要保持兼容是不切实际的。MSPGCC使用通用gcc语法来处理内联汇编语言,用一些扩展来处理MSP430的特殊问题。一开始你会觉得GCC处理内联汇编的方式比其它编译器难使用,然而,这些都是它的有效和强大之处。

内联汇编语法

mspgcc支持GNU标准内联汇编特性‘asm’。在汇编程序里使用‘asm’,你可以用C表达式来指定指令的操作数,这意味着你不用管要使用的数据在寄存器或内存的位置。

你必须指定汇编程序指令模板,如同汇编程序语言一样,操作数用引号括起来。例如:

asm("mov %1, %0": "=r" (result): "m" (source));

也可以这样更清晰的写:

asm("mov %src,%res": [res] "=r" (result): [src] "m" (source));

这里‘source’是输入操作数而‘result’是输出操作数,‘=’意味着输出。m 和 r 指示GCC使用的操作数寻址方式。完整的约束符文档在请参照GNU gcc文档。

每个汇编语句用冒号分成四部分。

1. 汇编指令, 定义为 single string 常量:

"mov %src, %res"

2. 一列输出操作数,用逗号隔开。 例子中只包含一个输出操作数,为它定义标志符"res":

[res] "=r" (result)

3. 用逗号分开的输入操作数列表,同样例子中只有一个操作数,为它定义标志符"src":

[src] "m" (source)

4. The clobbered registers. This is left empty in our example, as nothing is clobbered.

译注:不太懂,理解的兄弟请教教我,好像是gcc用来保护寄存器的(保护寄存器使用push,pop就行了)

因此,完整的模式如下:

asm((string asm statement) : [outputs]:[inputs]:[clobbers]);

msp430-gcc识别下列约束符:

. m - memory operand(操作数).

. I - integer operand.

. r - register operand.

. i - immediate operand (int constants in most cases).

. P - constants, generated by r2 and r3.

gcc支持其它一些处理器通用的约束符。这些约束符促使编译器自动产生前后同步代码、分配寄存器、保存和恢复任何需要的,以确保汇编程序可以被准确高效的处理。例如:

asm("add %[bar],%[foo]"

: [foo] "=r" (foo)

: "[foo]" (foo), [bar] "m" (bar));

等效于:

foo += bar;

生成下面的汇编代码:(假设foo为全局变量)

mov &foo, r12

/* #APP */

add &bar, r12

/* #NOAPP */

mov r12, &foo

如果输出操作数没被使用,有必要为‘asm’构造指定‘volatile’。如果你写的头文件要被包含在ANSI C程序中,用‘__asm__’取代‘asm’,‘__volatile__’ 取代 ‘volatile’。

A‘%’后面跟着数字或者已定义的标记强制gcc去取代相关的操作数。对4和8字节的操作数用A,B,C和D修饰来选择操作数中适当的16位。

例如:

#define LONGVAL 0x12345678l

{

long a,b;

...

asm("mov %A2, %A0 \n\t"

"mov %B2, %B0 \n\t"

"mov %A2, %A1 \n\t"

"mov %B2, %B1 \n\t"

: "=r"((long)a),"=m"((long)b)

: "i"((long)LONGVAL) );

...

}

or

#define LONGVAL 0x12345678l

{

long a,b;

...

asm("mov %A[longval], %A[a] \n\t"

"mov %B[longval], %B[a] \n\t"

"mov %A[longval], %A[b] \n\t"

"mov %B[longval], %B[b] \n\t"

: [a] "=r" ((long) a), [b] "=m" ((long) b)

: [longval] "i"((long) LONGVAL));

...

}

这会产生和下面相类似的汇编语言(假设‘a’在语句块里声明,‘b’为全局的):

...

/* #APP */

mov #llo(305419896), r12

mov #lhi(305419896), r13

mov #llo(305419896), 4(r1) ; mov #llo(305419896), &b

mov #lhi(305419896), 6(r1) ; mov #lhi(305419896), &b+2

/* #NOAPP*/

mov r12, 0(r1)

mov r13, 2(r1)

...

由此可以看出:

%A[tag]担当%[tag]的寄存器或地址常量操作数,或者与#llo()一样取整型值。#llo()是汇编宏,取低16位值。

%B[tag]寄存器数加1,地址加2,取操作数的16-31位。

%C[tag]寄存器数加2,地址加4,取32-47位。

%D[tag]寄存器数加3,地址加6,取最后16位。

译注:其中[tag]如果是0,1,2……则:

%0 ... %K 是输出变量

%K+1 ... %N 是输入变量

上例中%0代表a,%1代表b,%2代表LONGVAL。

I,J,K和L修饰符和A,B,C,D修饰符的功能相似,寄存器数加1,地址也是加1。

They should only be used in zero_extendMN operations.

还有 %E 修饰符取代 Rn 从 (mem:xx (reg:xx n)) 作为 @Rn.。对栈顶或指针这是一个有用的修饰符。 !!! 除非很清楚自己在干什么,否则不要使用它!!!

寄存器,变量,标号

既然Gcc不能检查汇编语法,你可以在汇编声明asm()中做任何事,但是请不要。gcc不使用r0,r2,r3,因此,如果你在asm()中使用其中之一作为输出或作为寄存器变量的别名,gcc会用其它的寄存器替代。使用它们作为输入参数会导致"’asm’ operand requires impossible reload"的错误。

在asm()声明中变量能以任何普通方式使用(mind name conversion for [Rr][0-15] names)

Gcc以下面的模式定义标号:

“.Lfe%=”

函数结束标号

“.L__Frame_size_%s”

看上面

“.L%=”

局部标号

“%=”修饰符在文件里代替唯一的数字。

下面的标号为一些扩展的操作数定义:

.Lsren%=

.Lsrcl%=

.Lsre%=

.Lae%=

.Lmsn%=

.Lcsn%=

.Lsend%=

.Lsst%=

.Leaq%=

.LcmpSIe%=

因此,不要使用这些模式。你可以使用其它任何标号。请注意,如果标号以.L开头,表示这是一个局部标号在用msp430-objdump反汇编的输出中。

库调用

在代码生成期间gcc使用一些库函数。这些用非标准的参数传递方案,这些不遵守mspgcc ABI,因此,不要在你的汇编代码中使用,除非你绝对肯定在发生什么。也就是:

乘法:

__mul{qi,hi,si}3

__umul{qi,hi,si}3

__umulsi3hw

对没有硬件乘法器的器件,乘法程序被调用处理相乘。如果目标是处于HI模式(16 bit) or QI 模式 (8 bit),第一个参数r10传递,第二个r12传递,返回值在r14中。在Si模式(32 bit),第一个参数r11:r10,第二个r13:r12,结果在r14:r15中。这两种方式函数返回时输入参数被破坏(clobbered)。

除法:

__divmod{qi,hi,si}4

__udivmod{qi,hi,si}4

如果目标处于 HI 模式 (16 bit) 或 QI 模式 (8 bit), 分子由 r12传递, 分母在r10中。 计算结果 r12/r10的商在r12中余数在r14中。Registers,r10, r11 and r13 are clobbered.

在 SI 模式 (32 bit),分子由r13:r12 传递,分母在r11:r10中。 商保存在r13:r12中,a余数在r15:r14.中。Registers r8, r9, r10, and r11 are cloberred。

所有的浮点数库调用可以以通用方式使用,因为它们遵守mspgcc ABI

各模块可以先分别汇编或编译,生成各自的.OBJ文件,然后运行L51将各OBJ文件连接,生成新文件即可.
也可以用WAVE直接将程序打开进行全部编译,即可

tcc编译.c ->.o
tasm 编译.asm ->.o

tlink连接,要带上c的运行库,具体的查帮助吧