分享

C语言调用汇编

 共同成长888 2014-07-03

1.子程序是怎么调用的?

2.参数怎么传递的?

3.怎样返回值?

像C一样的高级语言是通过栈来传递参数的.

每种高级语言使用内存的方式不同.共同点是需要使用子程序接口.

被接受的标准是通过堆栈.

如果参数是短整型,那么他的数值直接通过堆栈传递.

如果参数是字符串型,那么把指向他的一个指针入栈.

如果是一个浮点型格式数据,那么既可以通过直接传值,又可以通过传递指针.

堆栈上的变量可以通过 基址寄存器BP 很容易被访问.

很重要的一点就是在C程序里面通过"extern"来调用的汇编子程序不能影响到C程序.

C程序很依赖BP寄存器.

返回值可以通过以下方式传递:

1.堆栈

2.寄存器

3.内存

Turbo C遵从下表返回值:

Type of result Returned in

Ordinal AL (8-bit Values)

AX (16-Bit Values)

DX:AX (32-bit values)

8087 ST(0) on the 8087's register stack

Pointer DX:AX

此表通过寄存器返回数据。

1.如果用Microsoft C,Turbo C编译器,则必须声明以_TEXT名称的代码段

2.如果用以上两者编译器,则要声明以_DATA名称的数据段

3.理解C语言的参数传递规则

例子:

function_name (arg1,arg2,arg3,......,argn);

参数反向入栈,argn首先入栈,arg1最后入栈,参数要么通过直接值传递,要么通过指针传递,

large和huge内存模式,数据指针必须是32位大小。

记得保存汇编语言可能影响的寄存器。

老式接口:

PUBLIC _MYFUNCT

_TEXT SEGMENT WORD PUBLIC ‘CODE’

ASSUME CS:_TEXT

_MYFUNCT PROC NEAR ; For small memory model.

新式接口:

PUBLIC MYFUNCT

.MODEL small, C

.CODE

MYFUNCT PROC

没有参数传递:

Assembly code with directives Assembly code without directives

PUBLIC CUR_ON PUBLIC _CUR_ON

.MODEL small, C _TEXT SEGMENT WORD PUBLIC ‘CODE’

.CODE ASSUME CS: _TEXT

CUR_ON PROC _CUR_ON PROC NEAR

mov ah, 03h mov ah, 03h

mov bx, 00h mov bx, 00h

int 10h int 10h

and ch, 1fh and ch, 1fh

mov ah, 01h mov ah, 01h

int 10h int 10h

ret ret

CUR_ON ENDP _CUR_ON ENDP

END _TEXT ENDS

END

调用方法:

extern void CUR_ON ( void ) ;

void main ( void )

{

CUR_ON( ) ;

}

有参数:

PUBLIC TRIPLE

.MODEL small, C

.CODE

TRIPLE PROC USES ES DI, NOS: WORD

mov ax, NOS

mov bx, 03h

mul bx

mov ax, bx

ret

TRIPLE ENDP

END

PUBLIC _TRIPLE

_TEXT SEGMENT WORD PUBLIC ‘CODE’

ASSUME CS: _TEXT

_TRIPLE PROC NEAR

push bp

mov bp, sp

push es

push di

mov ax, [bp+4]

mov bx, 03h

mul bx

mov ax, bx

pop di

pop es

pop bp

ret

_TRIPLE ENDP

_TEXT ENDS

END

Stack Frame

Memory

Registers

MSB of NOS

2000Ah

[BP + 4]

LSB of NOS

20009h

MSB of return address

20008h

[BP + 2]

LSB of return address

20007h

MSB of saved BP

20006h

BP

LSB of saved BP

20005h

MSB of saved ES

20004h

LSB of saved ES

20003h

MSB of saved DI

20002h

SP

LSB of saved DI

20001h

因此你可以观察到第一个参数在BP+4位置处。别忘了那是C里面调用的函数的左边的。所有其余的参数(如果有的话)都会先后入栈。他们都可以通过类似BP+6的方式访问。在8086家族CPU中堆栈是向下生长的。

Originally written assembly code subroutines can be called from C programs. Large number of graphics routines available in assembly which can be directly interfaced in C.

Large inline assembly blocks makes C program look clumsy and not everyone understands assembly.

Third is of course, the knowledge.

LSB = Least Significant Byte.

MSB = Most Significant Byte.

调用:

#include

extern int TRIPLE ( int ) ;

void main ( void )

{

int p ;

p = TRIPLE ( 20 ) ;

printf ( "%d", p ) ;

}

Thus you can observe that the first parameter begins at address BP+4. Don’t forget that this is the first parameter from left of the function call in C. All the remaining parameters (if any) should be successively push on stack prior to call. They can be manipulated using based index addressing mode e.g. [BP+6] Also important point is, in 8086 family microprocessor stack grows downwards hence the memory locations are given in decreasing order. If you have observed keenly the location of BP pointer, you must have noticed the it points at it’s original contents. But what about the pushed ES and DI? Those are pushed on stack to restore them later.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多