Basic Assembly


In this post I’ll go over writing a basic Hello World program in C, using MinGW to compile, assemble and link it. I’ll be looking at the assembly, writing my own Hello World in NASM and using nasm and ld to assemble and link it.

Writing “Hello World” in C

# hello world.c

#include <stdio.h>

int main() {
    printf("Hello World");
    return 0

Using MinGW

Generate raw assembly: compile, not assemble, not link
gcc -S "hello world.c" -o "hello world.S"

Generate object file: compile, assemble, not link
gcc -c "hello world.S" -o "hello world.o"

Generate stripped portable executable (PE): compile, assemble, link, strip
gcc -s "hello world.o" -o "hello world.exe"

Writing “Hello World” in NASM

; hello world.asm

        global  _start
        extern  _ExitProcess@4      ; stdcall calling convention: leading _, trailing @, number of bytes in parameter list in decimal
        extern  _GetStdHandle@4
        extern  _WriteConsoleA@20

        section .data
msg:    db      'Hello, World', 0xA     ; 0xA denotes a new line
handle: db      0

        section .text
        ; handle = GetStdHandle(-11)
        push    dword -11       ; -11 denotes standard output device, initially this is the active console screen buffer
        call    _GetStdHandle@4
        mov     [handle], eax   ; eax contains return value from GetStdHandle()

        ; WriteConsole(handle, &msg, 13, &written, 0)
        push    dword 0             ; reserved: must be null
        push    dword 0             ; optional out parameter: number of actual characters written
        push    dword 13            ; number of characters to write
        push    msg                 ; buffer to write
        push    dword [handle]      ; handle to console window
        call    _WriteConsoleA@20   ; direct win32 API call

        ; ExitProcess(0)
        push    dword 0
        call    _ExitProcess@4

Using nasm.exe and ld.exe

Generate object file: assemble with nasm
nasm -fwin32 "hello world.asm"

Generate portable executable (PE): link with ld
ld -e _start "hello world.obj" C:\Windows\System32\kernel32.dll -o "hello world.exe"