1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
; fasmg exit-code.asm exit-code
macro mov.d target, source
match =rax?, target
db 0x48, 0xC7, 0xC0
; 48 eAX REX.W prefix
; (DEC is the 32-bit meaning, ignore it)
; eAX -> register identifier,
; width depends on operand
; REX.W -> set 64-bit operand mode
; c7 Grp 11^1A - MOV Ev, Iz
; immediate to register
; 1A -> bits 5,4,3 of ModR/M are opcode
; extension
; E -> modR/M byte to follow for operand
; v -> word of appropriate size
; I -> immediate data
; z -> 32-bit operand
; c0 ModR/M byte
; 0b11000000
; 11 mod: always 11
; 000 op/reg: Mov Ev, Iz
; 00x w absent
; 0 w (ignored)
dd source
else match =rdi, target
db 0x48, 0xC7, 0xC7
; 7: 48 c7 c7 2a 00 00 00 mov $0x2a,%rdi
; 48 eAX REX.W prefix
; (DEC is the 32-bit meaning, ignore it)
; c7 Grp 11^1A - MOV Ev, Iz
; immediate to register
; 1A -> bits 5,4,3 of ModR/M are opcode
; extension
; Ev -> ModR/M to follow for 32-bit operand
; Iz -> Immediate data, 32-bits
; c7 ModR/M byte
; 0b11000111
; 11 mod: always 11
; 000 op/reg: Mov Ev, Iz
; 11x w present
; 1 w true; use EDI
dd source
end match
end macro
macro syscall
db 0x0F, 0x05
; 0f two-byte escape
; 05 syscall ^ o64
end macro
org 0x08048000
elf_header:
db 0x7F, "ELF"
db 2 ; 64-bit
db 1 ; little-endian
db 1 ; ELF header format version 1
db 0 ; System-V ABI
db 8 dup 0 ; (padding)
dw 2 ; executable
dw 0x3E ; Intel x86-64
dd 1 ; ELF format version
dq _start ; entry point
dq program_header - $$ ; program header offset
dq 0 ; section header offset
dd 0 ; processor flags
dw elf_header_size
dw program_header_entry_size
dw 1 ; number of program header entries
dw 0 ; section header entry size
dw 0 ; number of section header entries
dw 0 ; section name string table index
elf_header_size = $ - elf_header
program_header:
dd 1 ; "loadable" segment type
dd 0x05 ; read+execute permission
dq 0 ; offset in file
dq $$ ; virtual address
dq 0 ; (padding)
dq file_size ; size in file
dq file_size ; size in memory
dq 0 ; segment alignment
program_header_entry_size = $ - program_header
_start:
mov.d rax, 60
mov.d rdi, 42
syscall
file_size = $ - $$
|