I'm new to ASM programming, but have been using NASM for a week or two now and have a basic grasp of it.  Linking however, is giving me a huge headache.  I've tried to learn assembly through online tutorials, but each one seems to work only with the linker given.  I now have several different linking programs that only seem to work on their own "style" of program.  I'm trying to figure out how to program using only one linker (ALink) but have since run into problems like with this simple program:

;test1.asm
extern printf
import printf dll\msvcrt.dll

section .data
m1: db 'Hello',0

section .text use32
..start:
push m1
call printf
add esp,4
ret

It's quite similar to a program I successfully linked using gcc (without including the C library of course).  Running the following from cmd:

nasm -fobj myprograms\test1.asm
alink -oPE myprograms\test1.obj

doesn't give any errors and seems to go smoothly.  Upon attempting:

myprograms\test1.exe

however, I get an error box saying that  "The application failed to start correctly (0xc000007b)."  Is there an error in my coding or is ALink just as confused as I am?

BTW yes a copy of msvcrt.dll is in the "dll" folder which is itself in the same folder as "test1."
Posted on 2011-10-22 17:11:08 by metallevel
Hi metallevel,

You can put your code in "code blocks" by putting the word "code" in square brackets ([]) - like a memory reference in Nasm, and "/code" (likewise) at the end. Like so:


;test1.asm
extern printf
import printf dll\msvcrt.dll

section .data
m1: db 'Hello',0

section .text use32
..start:
      push m1
  call printf
  add esp,4
ret


Try this slight variation on your code.


;test1.asm
extern printf
; I'm surprised the '/' worked here - but it did.
; I've replaced it with a space, "by preference".
import printf dll msvcrt.dll
; "use32" here, too.
section .data use32
m1: db 'Hello',0

; I don't know why "class=CODE" helps.
section .text use32 class=CODE
..start:
      push m1

; I don't know why we have to use the square brackets
; when using "-f obj" and "import" (and Alink?)
; and not at other times. But we do.
  call
  add esp,4
ret


That's untested. I don't "do Windows" anymore, but I remember a few things from when I did. I can't run your file, but I can assemble it and link it (I've got Alink running on Linux). I then disassemble it with Agner Fog's "objconv", and when Agner's tool can make sense of it, I figure I'm making progress. I think my minor changes will help. No guarantees!

(you might want to look at the NASMX package, which uses Jeremy Gordon's GoLink as a linker)

Best,
Frank

Posted on 2011-10-23 04:40:16 by fbkotler
Thanks, but I'm still having problems.  I've moved the dll into the same directory as the program because both '\' and 'space' seem to cause problems for some reason.  I'll deal with that later, now while the program runs without a fatal error 'Hello' isn't displayed.  As I mentioned using gcc allows 'printf' to work when coded this way (though it likes the '-fwin32' option which can't handle imports).

There must be a simple solution to being able to make any NASM program using ALink with minor modifications.  My only real question is how?  As I mentioned assembling and linking seems to go perfectly, but the program just won't run as expected.

BTW thanks for the "code" tip, I figured there was something like that ;).
Posted on 2011-10-23 12:11:10 by metallevel
Well... there's a "dirty little secret" to printf. It doesn't actually print anything until the buffer is flushed. Ending with a newline will flush the buffer (13, 10 for Windows, just 10 for Linux). Exiting the program will usually also do it. It might be an issue that you end with "ret" instead of "ExitProcess"(?). (you'd have to "extern" and "import" it, like printf)

There's a relatively "new" feature to Nasm, in which if you surround a string with "back apostrophes" instead of single or double quotes, it'll handle "\n" and other C-like stuff...


m1: db `Hello\n`,0


If that doesn't help, I dunno. We may need help from a Windows guru.

Best,
Frank

Posted on 2011-10-23 13:54:08 by fbkotler
Still no luck.  I've tried a number of variations (including all your suggestions), and this is what I have ATM:


;test1.asm
extern printf
extern ExitProcess

import printf msvcrt.dll
import ExitProcess kernel32.dll

section .data
m1: db 'Hello',13,10

section .text use32
..start:
      push m1
  call
  add esp,4

  push dword 0
call


Yet again it appears to assemble and link fine but upon running... nothing.
Posted on 2011-10-23 15:38:01 by metallevel
Well, I seem to have solved my problem by switching to GoLink, removing the 'import' statements, and just linking all the files in at the command line.  Some of my programs still need minor modifications, but at least they're within reason now :).
Posted on 2011-10-23 21:17:47 by metallevel
I guess that's why GoLink has become more "popular"... Pity it isn't open source! Guess it doesn't matter if you're running it on Windows anyway...

Best,
Frank

Posted on 2011-10-24 02:54:14 by fbkotler
One error is often observed with beginners. They will use the "printf" function and immediately exit the program. Although whatever was "printed" did effectively get displayed, it lasted for so little time that the user never gets a chance to see it and then concludes that the program is not working. Simply adding an instruction to wait for a signal from the keyboard before exiting usually solves the problem.
Posted on 2011-10-24 20:22:15 by Raymond