0

Assuming I hate myself and want to avoid external libraries as much as possible, I am trying to write hello world assembly. From what little I understand, in Windows we should link with the kernel32.dll and output from that. Any ideas why my code is not outputting?

code:

extern ExitProcess
extern WriteFile

section .text
   global Start     ;must be declared for linker (ld)
    
Start:              ;tells linker entry point
   mov  rdx,len     ;message length
   mov  rcx,msg     ;message to write
   mov  rbx,1       ;file descriptor (stdout)
   mov  rdx,4       ;system call number (sys_write)
   int  WriteFile       ;call kernel
    
   mov  rax,1       ;system call number (sys_exit)
   int  ExitProcess      ;call kernel

section .data
msg db 'Hello, world!', 0xa  ;string to be printed
len equ $ - msg     ;length of the string

instructions ran:

nasm -f win64 -o hello_world.obj hello_world.asm

golink hello_world.obj kernel32.dll

hello_world.exe

no errors or warnings on running the commands.

Thanks in advance!

JNichols
  • 66
  • 6
  • 1
    https://bitcodersblog.wordpress.com/2017/05/10/win32-in-nasm-part-1/amp/ there are sveral examples, just go to: Take Three – tttony Jun 26 '22 at 05:26
  • That looks like the 32-bit Linux system-calling convention (for use with `int 0x80`), and then you overwrite the length in RDX with a call number. And execute an `int imm8` with an interrupt number that depends on an address. Even as `-felf32` under Linux this wouldn't work (although it's close, but see [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730)), and it definitely won't work on any other OS. Definitely not Windows; [Windows system calls](https://stackoverflow.com/q/21074334) – Peter Cordes Jun 26 '22 at 05:42
  • 1
    I'm really surprised your linker doesn't warn when filling in an 8-bit immediate (that you're using as an interrupt number!) with a 64-bit absolute address. But yeah `nasm -fwin64` does actually assemble without warning. objdump -drwC shows it assembled to a .obj with a placeholder imm8=0: `cd 00 int 0x0 1a: IMAGE_REL_AMD64_ADDR32 WriteFile` – Peter Cordes Jun 26 '22 at 05:43
  • 1
    Did you maybe mean to `call WriteFile`? Because that would be the correct thing to do. (Or `call [rel WriteFile]` to go through the dynamic linker's function pointer.) Except of course WriteFile follows the Windows x64 calling convention, so those aren't the right registers for args, and it doesn't take a Unix file descriptor number like `1`, it takes a file *handle*. – Peter Cordes Jun 26 '22 at 05:45
  • 1
    Basically, you need to throw out your entire code except for the `extern` lines and the `.data` section, because all of it is completely wrong for Windows x64. It looks like you started with a 32-bit Linux example, and changed the wrong things about it. – Peter Cordes Jun 26 '22 at 05:49

0 Answers0