0

I am trying to write a 64-bit NASM assembly program in Windows to simply print some output to the console. I would like to do this with the most pure assembly possible, so that excludes any standard C libraries. I'm also trying to automate the assembly and linking process, so opening Visual Studio and doing it manually is not an option.

I know that I have to use the Windows APIs like _GetStdHandle and _WriteFile, but I can't figure out how to link those libraries, or how to use them in a 64-bit program.

This is the "Hello World" assembly code I am trying to run:

    global _main
    extern  _GetStdHandle@4
    extern  _WriteFile@20
    extern  _ExitProcess@4

    section .text
_main:
    ; DWORD  bytes;    
    mov     ebp, esp
    sub     esp, 4

    ; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
    push    -11
    call    _GetStdHandle@4
    mov     ebx, eax    

    ; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push    0
    lea     eax, [ebp-4]
    push    eax
    push    (message_end - message)
    push    message
    push    ebx
    call    _WriteFile@20

    ; ExitProcess(0)
    push    0
    call    _ExitProcess@4

    ; never here
    hlt
message:
    db      'Hello, World', 10
message_end:

But I'm not sure how to link the Windows 64-bit APIs to the program. I have also been getting this error: "instruction not supported in 64-bit mode" for the instruction "push eax". I'm just not sure how to re-write this code for 64-bit.

This is the batch program I am using to assemble and link the program:

nasm -f win64 HelloWorld.asm -o HelloWorld.obj &&^
 "C:\Program Files\GoLink\GoLink.exe" /console /entry _main HelloWorld.obj /fo HelloWorld.exe &&^
 HelloWorld.exe

Can anyone walk me through the steps required to get this program to run with the given constraints?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Daniel Williams
  • 635
  • 7
  • 14
  • 1
    That's 32-bit code. 64-bit code uses a different calling convention entirely. (`push rax` would assemble but it's not useful.) Everything about your code is obviously 32-bit, e.g. `sub esp, 4` treats the stack pointer as 32-bit, and in 64-bit mode would truncate it to 32 bits. Are you sure you want to make a 64-bit executable instead of just building this source as 32-bit? – Peter Cordes May 31 '20 at 04:29
  • @PeterCordes I was hoping to re-write this code as 64-bit, and assemble in 64-bit, but I'm not sure how to do either. Could I just replace all of the eax's with rax's, etc.? – Daniel Williams May 31 '20 at 04:33
  • I literally just said you *can't* simply do that, because 64-bit code uses a different calling convention. An answer on [Hello world in NASM with LINK.EXE and WinAPI](https://stackoverflow.com/q/59474618) links to MS's docs. – Peter Cordes May 31 '20 at 04:43
  • I found 3 good duplicates on the first page of a google search for `site:stackoverflow.com windows x64 hello world GetStdHandle`. Hope that covers it. Note the differences in function naming (no leading `_`, and it's not callee-pops so no `@4` decorators.) – Peter Cordes May 31 '20 at 04:49
  • [Translated to 64-bit code](https://godbolt.org/z/TwQg6y). This is following the [x64 calling convention](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention). – IInspectable May 31 '20 at 06:17

0 Answers0