Xref: utzoo alt.msdos.programmer:256 comp.sys.ibm.pc:32522 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!hplabs!hp-sdd!megatek!zeta!hollen From: hollen@zeta.megatek.uucp (Dion Hollenbeck) Newsgroups: alt.msdos.programmer,comp.sys.ibm.pc Subject: Re: Calling C functions from assembly Message-ID: <663@megatek.UUCP> Date: 2 Aug 89 14:11:42 GMT References: <12324@s.ms.uky.edu> Sender: news@megatek.UUCP Lines: 84 From article <12324@s.ms.uky.edu>, by simon@ms.uky.edu (G. Simon Gales): > I'm trying to call some C functions from assembly, using MSC 5.0 and either > MASM or TASM. I could write a dummy _main() in C, if this makes things > easier, but I'm still not sure what needs to be setup to call a C subroutine. > > Can anyone clue me in on how to do this? There is a section in the ref. manual dealing specifically with this, but I will summarize. Be aware that I am summarizing from memory and do not have the manual in front of me. I will address both calling C functions from assembly and assembly being called by C. Calling C from Assembly. ======================= Pseudocode the calling interface so you know the order of the arguements. Push the arguements onto the stack from right to left and push multi-word args (floats, far ptrs....) from high to low. Be sure of your memory model so that you can have the segment registers OK. Some memory models ASSUME ES = DS so you must make it so before calling C functions. For instance the tiny memory model assumes that CS = DS = ES = SS. Results are returned in registers. A char in AL, a short int in AX, a long int or float in AX/BX (low order in BX), and a double in AX, BX, CX, DX high order in AX to low order in DX. Calling Assembly from C. ======================== Here is a code fragment for ASM being called by C. ;; FUNCTION ;; read_ee_raw (ee_offset, numbytes, destination) ;; ;; int ee_offset ARG1 ;; int num_bytes ARG2 ;; char far *destination ARG3 - offset ;; ARG4 - segment PUBLIC READ_EE_RAW READ_EE_RAW PROC NEAR PUSH BP ;set up frame pointer MOV BP,SP PUSH AX ;save registers used PUSH DI PUSH SI PUSH DS PUSH ES LDS SI,[EEPROM_BASE] ;get seg:off ptr to EEPROM base MOV AX,[BP+ARG1] ;get byte offset into EEPROM SHL AX,1 ;make word offset ADD SI,AX ;add to base offset MOV DI,[BP+ARG3] ;get offset to destination MOV AX,[BP+ARG4] ;get segment of destination MOV ES,AX ;get in dest segreg MOV CX,[BP+ARG2] ;get count of bytes to read EEPROM_READ_LOOP: LODSW ;read word - high byte is junk STOSB ;write byte LOOP EEPROM_READ_LOOP ;continue until done POP ES ;restore registers used POP DS POP SI POP DI POP AX POP BP ;restore frame pointer RET READ_EE_RAW ENDP No other explanation should be necessary except to say to read the manual to be sure what registers should be saved and restored. You cannot go wrong by saving/restoring all you use. Dion Hollenbeck (619) 455-5590 x2814 Megatek Corporation, 9645 Scranton Road, San Diego, CA 92121 uunet!megatek!hollen or hollen@megatek.uucp