From: beppu AT rigel DOT oac DOT uci DOT edu (John Beppu) Newsgroups: comp.os.msdos.djgpp Subject: Re: Help with NASM Date: 22 Jan 1997 22:02:40 GMT Organization: University of California, Irvine Lines: 221 Message-ID: <5c62q0$6o9@news.service.uci.edu> References: <32E6660A DOT 387C AT vesatec DOT com> NNTP-Posting-Host: rigel.oac.uci.edu To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp In article <32E6660A DOT 387C AT vesatec DOT com>, Vicente A.S. Werner wrote: >Hello all! > >I've been a total assembler programmer for years , without using c or >other lenguages , now I've switched to DJGPP C system totally. But >I don't have any idea on how to interface rutines on c with assembly >ones . I'm using NASM because its sintaxis is similar to the old >intel one . Any one can help me on how to export and import variables >and such? > >Thanks in Advance > >Vicent A.S. Werner aka [Mcleod] Here's a little overview of things to keep in mind when writing functions in straight assembly for use w/ DJGPP. [Registers] ebx,ebp,edi,esi : these must be preserved eax : return value goes here edx:eax : return (64bit) integer ST0 : return float (note) : look at the assembly output of one of your C programs : (by doing gcc -S ...) to see how DJGPP returns things. [Parameter Passing] suppose one had a function defined like: void phunction ( long* address long c ) { // blah...... } The stack will look like this while execution inside phunction is in process. (This applies to C--I don't know how C++ deals with parameters. Maybe someone else could help.) [esp+08] c [esp+04] address [esp+00] return address (note) : The parameter passing convention can be changed through : command line switches to make djgpp use registers to : pass in parameters. The default, however, is to strictly : use the stack to pass parameters. Again, look at the : assembly output of a C program to see how DJGPP wants : parameters to be dealt with. [NASM hints] I use CPP in conjunction with NASM to make my life a little easier. Here's an example of what I do. #define b byte #define w word #define d dword /* This will draw the region defined by the edge list "edge" in accordance to the distortion map "dist". Drawing will be done in the buffer starting at (*adr0). void distortion_fill ( long* adr0, // address of buffer to fill to long* adr1, // address of buffer to be distorted long* edge, // ofs edge list long* dist // ofs distortion map ); ;; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°*/ #define frame 28 #define S0 esp+04 // limit(lineCounter) (must not be 0) #define S1 esp+08 // lineCounter (aka n) #define S2 esp+12 // distortion_index (aka nn) #define _ebx esp+16 #define _edi esp+20 #define _esi esp+24 #define _ebp esp+28 #define adr0 esp+frame+04 #define adr1 esp+frame+08 #define edge esp+frame+12 #define dist esp+frame+16 _distortion_fill: // enlarge stackframe // prepare edge & dist ptrs mov ecx,[d esp] sub esp,b frame mov ebx,[d edge] mov edx,[d dist] mov [d esp],ecx ; return address // save registers for djgpp nop mov [_ebx],ebx mov [_edi],edi nop mov [_esi],esi mov [_ebp],ebp // prepare variables for loop mov edi,[d adr0] xor ecx,ecx mov esi,[d adr1] mov eax,[d ebx] mov d [S1],ecx ; S1 = Ini(lineCounter) nop mov edx,[d edx] ; edx = dist[nn] mov d [S0],eax ; S0 = Lim(lineCounter) nop mov ecx,[d ebx+4] ; ecx = edge[n].elements mov eax,[d ebx+8] ; eax = edge[n].start mov ebp,esi add edx,eax add esi,edx ; esi mov edx,[d dist] ; edx = &distortion_map[0] xor ecx,b -1 add edi,eax ; edi inc ecx ; ecx add ebp,eax ; ebp ;ÚÄÄÄÄÄÄú .lineFiller: ; al = pixelHolder ; ebx = temp ; ecx = neg(limit(pixelCounter)) ; edx = &distortion_map[nn] ; edi = adr0+edge[n].start ; incremental progression ; esi = adr1+edge[n].start+dist[nn] ; unpredictable ; ebp = adr1+edge[n].start mov al,b [esi] mov esi,ebp ; esi = adr1+edge[n].start = ebp mov ebx,[edx] add edx,b 4 add esi,ebx ; esi = (ebx = dist[nn]) + esi mov b [edi],al inc edi inc ecx jnz short .lineFiller ;ÀÄÄÄÄÄÄú // no more work? mov eax,d [S1] mov ebx,d [S0] inc eax mov d [S2],edx cmp ebx,eax mov ebx,d [edge] mov d [S1],eax je short .bye // prepare registers for another iteration mov edx,d [S2] mov eax,d [ebx+eax*8+4] mov esi,d [adr1] add esi,eax mov ebx,d [edx] mov edi,d [adr0] add esi,ebx ; esi add edi,eax ; edi mov ebp,esi ; ebp jmp short .lineFiller ;ÀÄÄÄÄÄÄú // restore registers for djgpp .bye: mov ebp,[_ebp] mov esi,[_esi] mov ebx,[_ebx] mov edi,[_edi] retn frame #undef frame #undef S0 #undef S1 #undef S2 #undef _ebx #undef _edi #undef _esi #undef _ebp #undef adr0 #undef adr1 #undef edge #undef dist Read up on how CPP is invoked. I think you'll find it to be helpful in dealing with NASM's lack of macro facilities. -- beppu AT uci DOT edu .............................................................