; Example file for nasm.xml kate syntax file
; compile with `nasm example.asm -f elf -o example.o`
; and link with 'gcc example.o -o example`
; Public domain
; kate: hl Intel x86 (NASM);

section .data

hello dd 'Hello World', 0x0A, 0h
printf_param dd '%s', 0q

section .text

extern printf

global main
main:
	push ebp
	mov ebp, esp
	
	push hello
	push printf_param
	call printf
	
	mov eax, 0b
	leave
	ret


NULL              EQU 0                         ; Constants
STD_OUTPUT_HANDLE EQU -11

extern GetStdHandle                             ; Import external symbols

global Start                                    ; Export symbols. The entry point

section .data                                   ; Initialized data segment
 Message        db "Console Message 64", 0Dh, 0Ah
 MessageLength  EQU $-Message                   ; Address of this line ($) - address of Message

section .bss                                    ; Uninitialized data segment
alignb 8
 Written        resq 1

section .text                                   ; Code segment
Start:
 sub   RSP, 8                                   ; Align the stack to a multiple of 16 bytes

 mov   ECX, STD_OUTPUT_HANDLE
 call  GetStdHandle
 mov   qword [REL StandardHandle], RAX

 sub   RSP, 32 + 8 + 8                          ; Shadow space + 5th parameter + align stack
                                                ; to a multiple of 16 bytes
 mov   RCX, qword [REL StandardHandle]          ; 1st parameter
 lea   RDX, [REL Message]                       ; 2nd parameter
 mov   R8, MessageLength                        ; 3rd parameter
 mov   qword [RSP + 4 * 8], NULL                ; 5th parameter
                                                ; Message Box, 64 bit. V1.02
.DisplayMessageBox:
 xor   ECX, ECX                                 ; 1st parameter
 lea   RDX, [REL MessageBoxText]                ; 2nd parameter
 lea   R8, [REL MessageBoxCaption]              ; 3rd parameter
 mov   R9D, MB_YESNO | MB_DEFBUTTON2            ; 4th parameter. 2 constants ORed together
 call  MessageBoxA

 cmp   RAX, IDNO                                ; Check the return value for "No"
 je    .DisplayMessageBox

extern _GetStdHandle@4                          ; Import external symbols
Start:
 call  _WriteFile@20

section .data                                   ; Initialized data segment
 Static1Colour    dd 0F0F0F0h,
 Edit2            resq 1

%define Screen.Width       RBP - 160            ; 4 bytes
%define ClientArea         RBP - 152            ; RECT structure. 16 bytes

 mov   dword [wc.cbSize], 80                    ; [RBP - 136]
 mov   dword [wc.style], CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW  ; [RBP - 132]
 mov   qword [wc.lpfnWndProc], RAX              ; [RBP - 128]
 mov   qword [wc.hIcon], RAX                    ; [RBP - 104]
 mov   dword [RSP + 4 * 8], EAX                 ; X position, now centred

 cmp   qword [uMsg], WM_CLOSE                   ; [RBP + 24]
 je    WMCLOSE
 call  DestroyWindow                            ; Send a WM_DESTROY message
 jmp   Return.WM_Processed
 mov   EDX, 0604060h
 call  SetBkColor
 mov   EDX, 0005000h

db 0x55 ; just the byte 0x55
db 0x55,0x56,0x57 ; three bytes in succession
db 'a',0x55 ; character constants are OK
db 'hello',13,10,'$' ; so are string constants
dw 0x1234 ; 0x34 0x12
dw 'a' ; 0x61 0x00 (it's just a number)
dw 'ab' ; 0x61 0x62 (character constant)
dw 'abc' ; 0x61 0x62 0x63 0x00 (string)
dd 0x12345678 ; 0x78 0x56 0x34 0x12
dd 1.234567e20 ; floating-point constant
dq 0x123456789abcdef0 ; eight byte constant
dq 1.234567e20 ; double-precision float
dt 1.234567e20 ; extended-precision float

db 33
db (44)               ; Integer expression
; db (44,55)            ; Invalid - error
db %(44,55)
db %('XX','YY')
db ('AA')             ; Integer expression - outputs single byte
db %('BB')            ; List, containing a string
db ?
db 6 dup (33)
db 6 dup (33, 34)
db 6 dup (33, 34), 35
db 7 dup (99)
db 7 dup dword (?, word ?, ?)
dw byte (?,44)
dw 3 dup (0xcc, 4 dup byte ('PQR'), ?), 0xabcd
dd 16 dup (0xaaaa, ?, 0xbbbbbb)
dd 64 dup (?)
db `\u263a`            ; UTF-8 smiley face
db `\xe2\x98\xba`      ; UTF-8 smiley face
db 0E2h, 098h, 0BAh    ; UTF-8 smiley face
buffer:         resb    64              ; reserve 64 bytes 
wordvar:        resw    1               ; reserve a word 
buffer:         db      64 dup (?)      ; reserve 64 bytes 
wordvar:        dw      ?               ; reserve a word 

incbin  "file.dat"             ; include the whole file
incbin  "file.dat",1024        ; skip the first 1024 bytes
incbin  "file.dat",1024,512    ; skip the first 1024, and
                               ; actually include at most 512

message         db      'hello, world' 
msglen          equ     $-message

buffer: db      'hello, world' 
        times 64-$+buffer db ' '

     bndstx [rbx*1+rax+0x3], bnd0    ; GAS - '*1' indecates an index reg
     VDIVPS zmm4, zmm5, dword [rbx]{1to16}   ; single-precision float 
     VDIVPS zmm4, zmm5, zword [rbx]          ; packed 512 bit memory

mov     ax,200          ; decimal
mov     ax,0200         ; still decimal
mov     ax,0200d        ; explicitly decimal
mov     ax,0d200        ; also decimal
mov     ax,0c8h         ; hex
mov     ax,$0c8         ; hex again: the 0 is required
mov     ax,0xc8         ; hex yet again
mov     ax,0hc8         ; still hex
mov     ax,310q         ; octal
mov     ax,310o         ; octal again
mov     ax,0o310        ; octal yet again
mov     ax,0q310        ; octal yet again
mov     ax,11001000b    ; binary
mov     ax,1100_1000b   ; same binary constant
mov     ax,1100_1000y   ; same binary constant once more
mov     ax,0b1100_1000  ; same binary constant yet again
mov     ax,0y1100_1000  ; same binary constant yet again

%define u(x) __?utf16?__(x) 
%define w(x) __?utf32?__(x) 

dw u('C:\WINDOWS'), 0       ; Pathname in UTF-16
dd w(`A + B = \u206a`), 0   ; String in UTF-32

db    -0.2                    ; "Quarter precision"
dw    -0.5                    ; IEEE 754r/SSE5 half precision
dd    1.2                     ; an easy one
dd    1.222_222_222           ; underscores are permitted
dd    0x1p+2                  ; 1.0x2^2 = 4.0
dq    0x1p+32                 ; 1.0x2^32 = 4 294 967 296.0
dq    1.e10                   ; 10 000 000 000.0
dq    1.e+10                  ; synonymous with 1.e10
dq    1.e-10                  ; 0.000 000 000 1
dt    3.141592653589793238462 ; pi
do    1.e+4000                ; IEEE 754r quad precision

mov    rax,__?float64?__(3.141592653589793238462)
mov    rax,0x400921fb54442d18

%define Inf __?Infinity?__ 
%define NaN __?QNaN?__ 

dq    +1.5, -Inf, NaN         ; Double-precision constants
dt 12_345_678_901_245_678p
dt -12_345_678_901_245_678p
dt +0p33
dt 33p

dq b * (a // b) + (a %% b)

call    (seg procedure):procedure
call    weird_seg:(procedure wrt weird_seg)

push dword 33
push strict dword 33

times (label-$) db 0

label:  db      'Where am I?'
        times (label-$+1) db 0 
label:  db      'NOW where am I?'

label1  ; some code 

.loop 
        ; some more code 

        jne     .loop 
        ret 

label1:                         ; a non-local label 
.local:                         ; this is really label1.local 
..@foo:                         ; this is a special symbol 
label2:                         ; another non-local label 
.local:                         ; this is really label2.local 

        jmp     ..@foo          ; this will jump three lines up


%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ 
        THIS_VALUE

%define ctrl    0x1F & 
%define param(a,b) ((a)+(a)*(b)) 

        mov     byte [param(2,ebx)], ctrl 'D'
        mov     byte [(2)+(2)*(ebx)], 0x1F & 'D'

%define a(x)    1+b(x) 
%define b(x)    2*x 

        mov     ax,a(8)

   %define foo (a,b)               ; no arguments, (a,b) is the expansion 
   %define bar(a,b)                ; two arguments, empty expansion

   %define ereg(foo,) e %+ foo 
     mov eax,ereg(dx,cx)

    %define xyzzy(=expr,&val) expr, str 
    %define plugh(x) xyzzy(x,x) 
    db plugh(3+5), `\0` ; Expands to: db 8, "3+5", `\0`

     mov ax,Foo%[__?BITS?__] ; The Foo value
%xdefine Bar         Quux    ; Expands due to %xdefine 
%define  Bar         %[Quux] ; Expands due to %[...]



%define BDASTART 400h                ; Start of BIOS data area

struc   tBIOSDA                      ; its structure 
        .COM1addr       RESW    1 
        .COM2addr       RESW    1 
        ; ..and so on 
endstruc

        mov     ax,BDASTART + tBIOSDA.COM1addr 
        mov     bx,BDASTART + tBIOSDA.COM2addr
; Macro to access BIOS variables by their names (from tBDA):

%idefine Foo mov %?,%?? 

%idefine keyword $%?

%idefine pause $%?                  ; Hide the PAUSE instruction
%define foo bar 
%undef  foo 

        mov     eax, foo
%assign i i+1
%defstr test TEST
%define test 'TEST'
%defstr PATH %!PATH          ; The operating system PATH variable

%deftok test 'TEST'

%define test TEST

%define greedy(a,b,c+) a + 66 %, b * 3 %, c 

       db greedy(1,2)          ; db 1 + 66, 2 * 3 
       db greedy(1,2,3)        ; db 1 + 66, 2 * 3, 3 
       db greedy(1,2,3,4)      ; db 1 + 66, 2 * 3, 3, 4 
       db greedy(1,2,3,4,5)    ; db 1 + 66, 2 * 3, 3, 4, 5

%macro  silly 2 
    %2: db      %1 
%endmacro 

        silly 'a', letter_a             ; letter_a:  db 'a' 
        silly 'ab', string_ab           ; string_ab: db 'ab' 
        silly {13,10}, crlf             ; crlf:      db 13,10
%pragma preproc sane_empty_expansion

%macro mpar 1-*
     db %{3:5} 
     db %{-1:-3} 
%endmacro

mpar 1,2,3,4,5,6

%macro  die 0-1 "Painful program death has occurred." 

        writefile 2,%1 
        mov     ax,0x4c01 
        int     0x21 

%endmacro

%macro  multipush 1-* 

  %rep  %0 
        push    %1 
  %rotate 1 
  %endrep 

        j%-1    %%skip 
        ret 
  %%skip: 

%endmacro


%macro foo 1.nolist

%endmacro

%macro  pushparam 1 

  %ifidni %1,ip 
        call    %%label 
  %%label: 
  %else 
        push    %1 
  %endif 

%endmacro

%assign i 0 
%rep    64 
        inc     word [table+2*i] 
%assign i i+1 
%endrep


fibonacci: 
%assign i 0 
%assign j 1 
%rep 100 
%if j > 65535 
    %exitrep 
%endif 
        dw j 
%assign k j+i 
%assign i j 
%assign j k 
%endrep 

fib_number equ ($-fibonacci)/2


%include "macros.mac"


%ifndef MACROS_MAC 
    %define MACROS_MAC 
    ; now define some macros 
%endif

%pathsearch MyFoo "foo.bin"

%imacro incbin 1-2+ 0 
%pathsearch dep %1 
%depend dep 
        incbin dep,%2 
%endmacro
%use altreg 
%use 'altreg'

%push    foobar

%macro repeat 0 

    %push   repeat 
    %$begin: 

%endmacro

%macro until 1

        j%-1    %$begin
    %pop 

%endmacro

%define %$localmac 3

%macro else 0 

  %ifctx if 
        %repl   else 
        jmp     %$ifend 
        %$ifnot: 
  %else 
        %error  "expected `if' before `else'" 
  %endif 

%endmacro 

%macro endif 0 

  %ifctx if 
        %$ifnot: 
        %pop 
  %elifctx      else 
        %$ifend: 
        %pop 
  %else 
        %error  "expected `if' or `else' before `endif'" 
  %endif 

%endmacro

some_function: 
    %push mycontext             ; save the current context 
    %stacksize small            ; tell NASM to use bp 
    %assign %$localsize 0       ; see text for explanation 
    %local old_ax:word, old_dx:word 

        enter   %$localsize,0   ; see text for explanation 
        mov     [old_ax],ax     ; swap ax & bx 
        mov     cx,[old_dx] 
        leave                   ; restore old bp 
        ret                     ; 

    %pop                        ; restore original context


%ifdef F1 
    ; do some setup 
%elifdef F2 
    ; do some different setup 
%else 
    %error "Neither F1 nor F2 was defined." 
%endif
%ifdef F1 
    ; do some setup 
%elifdef F2 
    ; do some different setup 
%else 
    %warning "Neither F1 nor F2 was defined, assuming F1." 
    %define F1 
%endif%if foo > 64 
    %assign foo_over foo-64 
    %error foo is foo_over bytes too large 
%endif

        db      __?NASM_VER?__

struc   mytype 
  mt_long:      resd    1 
  .str:         resb    32 
endstruc

%use altreg 


%macro  writefile 2+ 

        [section .data] 

  %%str:        db      %2 
  %%endstr: 

        __?SECT?__ 

        mov     dx,%%str 
        mov     cx,%%endstr-%%str 
        mov     bx,%1 
        mov     ah,0x40 
        int     0x21 

%endmacro

 DEFAULT BND 
     call foo            ; BND will be prefixed 
     nobnd call foo      ; BND will NOT be prefixed

global _main 
_main: 
global  hashlookup:function, hashtable:data

common  intvar  4
static foo 
foo: 
         ; codes

%pragma macho lprefix L_
; The most common conventions 
%pragma output gprefix _ 
%pragma output lprefix L_ 
; ELF uses a different convention 
%pragma elf    gprefix                       ; empty 
%pragma elf    lprefix .L

section .pdata  rdata align=4 
        dd      main wrt ..imagebase 
        dd      main_end wrt ..imagebase 
        dd      xmain wrt ..imagebase 
section .xdata  rdata align=8 
xmain:  db      9,0,0,0 
        dd      handler wrt ..imagebase 
section .drectve info 
        db      '/defaultlib:user32.lib /defaultlib:msvcrt.lib '
