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. |
|