Jump to content

C library with NASM

- - - - -

  • Please log in to reply
20 replies to this topic

#1
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
I have been trying to use the C library with NASM, but it isn't working out. I get "Undefined reference to WinMain@16" errors from ld. To link the object file outputted from NASM, I am using gcc -o [filename].exe [filename].o I figure this is a linking error, does anyone know what I should be doing?
Latinamne loqueris?

#2
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
I think I figured this out now.
Latinamne loqueris?

#3
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
What was the problem?

#4
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
I don't really know, there was just some linking error, so I took the easy way out: I made a C file that looked like this:

extern void SomeFuncName(void);


int main()

{

    SomeFuncName();

}

and in the assembly file I made the SomeFuncName function global (using the global keyword), assembled it to an ELF object file, and linked it like this:
gcc [Output from assembler].o [C file].c

Latinamne loqueris?

#5
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Use the extern keyword in your NASM code where you have your global declarations and stuff.
sudo rm -rf /

#6
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
That is the first thing I tried, and it gave me that undefined reference. I haven't tried making an extern statement for WinMain though, maybe I should.
Latinamne loqueris?

#7
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
Try disassembling the code, if possible, maybe the function name (that you access, referenced by the keyword extern) is different from what it needs to be. I don't know if this is the case, but I sometimes got things like:
C code:
int gcd(int a, int b){ 

.....and so on.....

But when I disassembled the code and the function name, instead of being gcd, was ?gcd@@YAHHH@Z.

Another thing is maybe the function name, in global form (from the C code), might actually be _function_name, instead of function_name, (with leading underscore), but NASM assembles it so it references 'function_name', instead of '_function_name'.

So anyway, I think you could try figuring out the actual object code function label name and type 'extern _whatever_the_function_name_is' and then, if you want to, use '%define whatever_the_function_name_is _whatever_the_function_name_is'.

I'm not sure if this is the problem, though, but you could try this.

#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Definitely try to turn name mangling off.
sudo rm -rf /

#9
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
It worked when I defined it as _main! But I didn't clean up the stack after calling _printf, how do I do that?

BTW It appears you were using the Digital Mars compiler for that, RhetoricalRuvim.
Latinamne loqueris?

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Not sure how Microsoft does it, but the way GCC does it is like this:

myfunc:

    ; create the standard stack frame

    push    ebp

    mov     ebp, esp

    

    ; Save enough space on the stack to pass all arguments to all functions and

    ; keep stack variables as well. If you only call functions with 3 arguments

    ; or less, then subtract 12, as in this example.

    sub     esp, 12

    

    ; ... blah ...

    

    mov     DWORD [esp], format_string

    mov     DWORD [esp + 4], 1234

    mov     DWORD [esp + 8], 5678

    call    printf

    

    ; ... blah ...

    

    add     esp, 12     ; MAKE SURE THIS IS THE SAME AS ABOVE

    pop     ebp

    ret


That way you don't have to clean up after every function call.
sudo rm -rf /

#11
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
It works now, thanks! It is possible to just push the arguments and then add the size of all the arguments put together after the call though, isn't it?
Latinamne loqueris?

#12
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
Maybe something like (not sure if it's the best way, though):
function: 

enter 12, 0 


;; .....  


leave 

ret 

About adding the size of the arguments, you mean something like this?:
function: 

enter 12, 0 


push dword 1234 

push word 5678 

call some_function 

add esp, 6 


leave 

ret 


some_function: 

;; some code .....  

ret 


I usually do it like this, though:
function: 

enter 12, 0 


push dword 1234 

push word 5678 

call some_function 


leave 

ret 


some_function: 

enter 4, 0 


;; some code 


leave 

ret 6 
That way the RET instruction takes care of the adding 6 to the stack pointer.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users