524 lines
13 KiB
Plaintext
524 lines
13 KiB
Plaintext
; 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 '
|