Author Topic: Linking against kernel32.dll with win32 format  (Read 10910 times)

Offline edwardcarlfox

  • Jr. Member
  • *
  • Posts: 7
Linking against kernel32.dll with win32 format
« on: August 12, 2012, 02:33:24 PM »
Hello, I am new to NASM, and I just started programming with it a bit. So far, I did some samples, using the obj format and the alink to link against kernel32.dll. In the codes I use the import and extern keywords. So they are all fine.

But then now I want to do the same but using the win32 format. In this format I cannot use import in the code, so I just state extern. Then I use the link program coming along with VS2010 to link it directly against kernel32.dll, but no matter how I did, the external symbols in the code cannot be resolved. I tried to change the names (i.e. ReadConsole to _ReadConsole@20), but no luck.

So does anyone know how to do this? So again the point is, I want to output the win32 format and use the link program from VS2010 to link against a dll directly.

Thanks in advanced!

Offline Mathi

  • Jr. Member
  • *
  • Posts: 82
  • Country: in
    • Win32NASM
Re: Linking against kernel32.dll with win32 format
« Reply #1 on: August 12, 2012, 06:50:48 PM »
Taking help from the below thread,
http://forum.nasm.us/index.php?topic=778.0

I have written a program to read a line and output that to the screen(console) using nasm and link.exe
Hope this helps.

Code: [Select]
;;linkdemo.asm
;;
;;Assemble with :   nasm -f win32 -Ox -o linkdemo.obj linkdemo.asm
;;link with     :   link /ENTRY:main /SUBSYSTEM:console /MACHINE:X86 kernel32.lib linkdemo.obj


%include "win32n.inc"
extern _GetStdHandle@4
extern _ReadConsoleA@20
extern _ExitProcess@4
extern _WriteConsoleA@20
extern _FlushConsoleInputBuffer@4

global main

segment .bss USE32

Buffer resb 8192
numIn resd 1
numWritten resd 1
segment .data USE32

hConsIn dd 0
hConsOut dd 0
nNumberOfCharsToRead dd 8192

segment .code USE32 class=code

main:

push dword STD_INPUT_HANDLE   ;;Get Input handle
call _GetStdHandle@4
mov [hConsIn],eax

push dword STD_OUTPUT_HANDLE    ;;Get Output handle
call _GetStdHandle@4
mov [hConsOut],eax


push dword [hConsIn]            ;; Flush the Input Buffer
call _FlushConsoleInputBuffer@4

push dword NULL                 ;; Read line
push dword numIn
push dword [nNumberOfCharsToRead]
push dword Buffer
push dword [hConsIn]
call _ReadConsoleA@20


push dword NULL                 ;; Write Line
push dword numWritten
push dword [numIn]
push dword Buffer
push dword [hConsOut]
call _WriteConsoleA@20

push dword 0                    ;; Exit Program
call _ExitProcess@4


Offline edwardcarlfox

  • Jr. Member
  • *
  • Posts: 7
Re: Linking against kernel32.dll with win32 format
« Reply #2 on: August 12, 2012, 07:19:37 PM »
Taking help from the below thread,
http://forum.nasm.us/index.php?topic=778.0

I have written a program to read a line and output that to the screen(console) using nasm and link.exe
Hope this helps.

Code: [Select]
;;linkdemo.asm
;;
;;Assemble with :   nasm -f win32 -Ox -o linkdemo.obj linkdemo.asm
;;link with     :   link /ENTRY:main /SUBSYSTEM:console /MACHINE:X86 kernel32.lib linkdemo.obj


%include "win32n.inc"
extern _GetStdHandle@4
extern _ReadConsoleA@20
extern _ExitProcess@4
extern _WriteConsoleA@20
extern _FlushConsoleInputBuffer@4

global main

segment .bss USE32

Buffer resb 8192
numIn resd 1
numWritten resd 1
segment .data USE32

hConsIn dd 0
hConsOut dd 0
nNumberOfCharsToRead dd 8192

segment .code USE32 class=code

main:

push dword STD_INPUT_HANDLE   ;;Get Input handle
call _GetStdHandle@4
mov [hConsIn],eax

push dword STD_OUTPUT_HANDLE    ;;Get Output handle
call _GetStdHandle@4
mov [hConsOut],eax


push dword [hConsIn]            ;; Flush the Input Buffer
call _FlushConsoleInputBuffer@4

push dword NULL                 ;; Read line
push dword numIn
push dword [nNumberOfCharsToRead]
push dword Buffer
push dword [hConsIn]
call _ReadConsoleA@20


push dword NULL                 ;; Write Line
push dword numWritten
push dword [numIn]
push dword Buffer
push dword [hConsOut]
call _WriteConsoleA@20

push dword 0                    ;; Exit Program
call _ExitProcess@4


Thanks a lot! Now I can make it work! But pathetically I don't remember where I did wrong before, I mean really wrong so that I could not even link successfully. So now I changed the plain function names to the mangled ones, and also took good care of the ASCII version of the two functions I used (ReadConsoleA and WriteConsoleA).

But originally I called a function using the square brackets, at least when generating the obj format, so I needed to call like this
Code: [Select]
call [ExitProcess] but now if I put the function names in square brackets, the program will crash. But without the square brackets, it works finally! So I am really very confused by the square brackets. In some examples I saw in the internet, some people use the square brackets, and some do not. And now according to my experience, I do not really know when to use and when not to, and what is actually the difference. So to my knowledge (coming from C), a symbol in NASM is just an address, when using it directly, I get the address of the that symbol. But when I put the symbol in square brackets, I can access the content of that symbol. Is this correct? And what is the case for function calls?

Another thing I do not understand, when linking we specify the library is kernel32.lib, but I searched the whole system and I just got kernel32.dll, no .lib. So where does this .lib come from?
« Last Edit: August 12, 2012, 07:46:00 PM by edwardcarlfox »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Linking against kernel32.dll with win32 format
« Reply #3 on: August 12, 2012, 10:27:28 PM »
I don't have a good answer to any of this. A long time ago, I did a small amount of programming for Win (Win98!). I mostly used "-f obj" and Alink. As you observe, if we use "extern" and "import", we do:
Code: [Select]
call [ExitProcess]
As I recall, there's another way to do it, still using "-f obj" and Alink, and using "extern" but not "import" which involves linking against a .lib (with Alink?) and we use the more usual:
Code: [Select]
call ExitProcess
Unless I'm mistaken there's another variable called "__inp_ExitProcess" (possibly decorated). I suspect that Alink is swapping names around for us (to us?).
Code: [Select]
call [__imp_ExitProcess]
; equ
call ExitProcess
A guess, mind you!

As I recall, the only success I had with "-f win32" and using the MicroSoft linker (not quite the same version, I'm sure) was by downloading Hutch's MASM32 package and using kernel32.lib (etc.) from there. If all else fails, you might try that (beware the EULA!).

I've been told that we can "make our own import libraries" by putting just the "extern"/"import" stuff into a file, assembling it with "-f obj",  and linking that .obj against our "main" .obj, assembled with "-f win32". The linker will complain about converting OMF to COFF, but it'll do it. So I'm told - haven't actually tried it, so I can't provide any details.

Another option would be to download the NASMX package. It uses Jeremy Gordon's "GoLink" linker, so isn't an answer to your question. I suspect GoLink does some "name swapping" for us, too. It may be a painless way to get a Windows .exe running, if you aren't too committed to using the linker you want to use. There aren't any .lib files in it AFAIK.

I'm sure MicroSoft has got all this stuff documented if you know where to look for it. I don't. Wish I had a better answer for ya!

Best,
Frank


Offline edwardcarlfox

  • Jr. Member
  • *
  • Posts: 7
Re: Linking against kernel32.dll with win32 format
« Reply #4 on: August 13, 2012, 08:42:53 AM »
I don't have a good answer to any of this. A long time ago, I did a small amount of programming for Win (Win98!). I mostly used "-f obj" and Alink. As you observe, if we use "extern" and "import", we do:
Code: [Select]
call [ExitProcess]
As I recall, there's another way to do it, still using "-f obj" and Alink, and using "extern" but not "import" which involves linking against a .lib (with Alink?) and we use the more usual:
Code: [Select]
call ExitProcess
Unless I'm mistaken there's another variable called "__inp_ExitProcess" (possibly decorated). I suspect that Alink is swapping names around for us (to us?).
Code: [Select]
call [__imp_ExitProcess]
; equ
call ExitProcess
A guess, mind you!

As I recall, the only success I had with "-f win32" and using the MicroSoft linker (not quite the same version, I'm sure) was by downloading Hutch's MASM32 package and using kernel32.lib (etc.) from there. If all else fails, you might try that (beware the EULA!).

I've been told that we can "make our own import libraries" by putting just the "extern"/"import" stuff into a file, assembling it with "-f obj",  and linking that .obj against our "main" .obj, assembled with "-f win32". The linker will complain about converting OMF to COFF, but it'll do it. So I'm told - haven't actually tried it, so I can't provide any details.

Another option would be to download the NASMX package. It uses Jeremy Gordon's "GoLink" linker, so isn't an answer to your question. I suspect GoLink does some "name swapping" for us, too. It may be a painless way to get a Windows .exe running, if you aren't too committed to using the linker you want to use. There aren't any .lib files in it AFAIK.

I'm sure MicroSoft has got all this stuff documented if you know where to look for it. I don't. Wish I had a better answer for ya!

Best,
Frank




Thank you for your answer!
It is weird that depending on if we use import or not in the code, the calling syntax is different. However I think I want to figure this out, I don't want to just use some tools and not understand the basis. I suppose it has something to do with the linking process, and I happened to get a book all about this!

For the "__imp_ExitProcess" thing, I have also tried, but it did not work. As I observed, the "__imp_" prefix may only apply to those GUI related functions like "__imp_MessageBoxA" (I read some article online and got this thing).

And about the OMF and the COFF, I have read in MSDN that the MS linker will convert OMF to COFF, but not all structures in OMF can be converted. So I don't like this, which is not a exact one to one mapping. And I also read that, OMF is very old, and nowadays it seems that only Borland is still using it (as I recall it correctly). That's why I want to use the win32 format.

I heard about GoLink, but since I have already VS2010, hence also the MS linker, I may want to try it first, but not downloading many new tools and finally I don't know which one will work with which one.

About the documentation, I always go for MSDN, and now MS has a new documentation helping program, once you get VS, you will have it installed. But of course if you are talking about those technical detail documentation, I also don't know, well of course, MS will not reveal so much technical detail about their products, right?

Alright, it seems like we are just chatting, but OK, this is how we grow up :-) Wish you all the best!

Offline edwardcarlfox

  • Jr. Member
  • *
  • Posts: 7
Re: Linking against kernel32.dll with win32 format
« Reply #5 on: August 13, 2012, 10:29:32 AM »
Hello everyone, it seems that I somehow figured out the use of square brackets when calling a function. I found out this by using IDA Pro (free version).

When using obj format, and of course linking using alink, the address of the external function is defined in the initialized data section, something like
Code: [Select]
ReadConsoleA dd ?(at least this is what I see in IDA Pro, a question mark following). Without really knowing the exact address, I think the address is actually the address of ReadConsoleA in kernel32.dll. So when calling ReadConsoleA here, we need to put it into the square brackets, to get the content of the symbol, which is in turn the address of the function.

When using win32 format, and linking using MS link, the name ReadConsoleA is not a label, but actually a function call, but it calls a stub, and in the stub the final ReadConsoleA in kernel32.dll is called (actually jumped). So here the name ReadConsoleA is then already the address of a function, and hence no need to put it into the square brackets.

Hope this could clarify some misunderstanding of the square brackets.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Linking against kernel32.dll with win32 format
« Reply #6 on: August 13, 2012, 03:05:59 PM »
That sounds right, thanks! As to where to find those .lib files, this applies to a different VS version, but may help:

http://social.msdn.microsoft.com/Forums/is/Vsexpressvc/thread/426d85b4-db84-4c01-a9d4-d3fd025339c0

Best,
Frank


Offline edwardcarlfox

  • Jr. Member
  • *
  • Posts: 7
Re: Linking against kernel32.dll with win32 format
« Reply #7 on: August 13, 2012, 04:12:59 PM »
That sounds right, thanks! As to where to find those .lib files, this applies to a different VS version, but may help:

http://social.msdn.microsoft.com/Forums/is/Vsexpressvc/thread/426d85b4-db84-4c01-a9d4-d3fd025339c0

Best,
Frank

The only hint I got from the link you provided is the .lib are included in the Windows SDK, and I just checked carefully, the kernel32.lib is actually there! It is weird since before I just searched in the whole C disk, and got no result, well the K in the file name is capitalized, and I search for the small k. But I guess windows does not care about cases of file names, right. Anyway, this also clarifies some problem. Thanks a lot!