-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcode.asm
More file actions
131 lines (102 loc) · 4.06 KB
/
code.asm
File metadata and controls
131 lines (102 loc) · 4.06 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;DEFINITIONS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%define LOAD_ADDRESS 0x00020000 ; pretty much any number >0 works
%define CODE_SIZE END-(LOAD_ADDRESS+0x78) ; everything beyond HEADER is code
%define PRINT_BUFFER_SIZE 4096
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;HEADER;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BITS 64
org LOAD_ADDRESS
ELF_HEADER:
db 0x7F,"ELF" ; magic number to indicate ELF file
db 0x02 ; 0x1 for 32-bit, 0x2 for 64-bit
db 0x01 ; 0x1 for little endian, 0x2 for big endian
db 0x01 ; 0x1 for current version of ELF
db 0x09 ; 0x9 for FreeBSD, 0x3 for Linux (doesn't seem to matter)
db 0x00 ; ABI version (ignored?)
times 7 db 0x00 ; 7 padding bytes
dw 0x0002 ; executable file
dw 0x003E ; AMD x86-64
dd 0x00000001 ; version 1
dq START ; entry point for our program
dq 0x0000000000000040 ; 0x40 offset from ELF_HEADER to PROGRAM_HEADER
dq 0x0000000000000000 ; section header offset (we don't have this)
dd 0x00000000 ; unused flags
dw 0x0040 ; 64-byte size of ELF_HEADER
dw 0x0038 ; 56-byte size of each program header entry
dw 0x0001 ; number of program header entries (we have one)
dw 0x0000 ; size of each section header entry (none)
dw 0x0000 ; number of section header entries (none)
dw 0x0000 ; index in section header table for section names (waste)
PROGRAM_HEADER:
dd 0x00000001 ; 0x1 for loadable program segment
dd 0x00000007 ; read/write/execute flags
dq 0x0000000000000078 ; offset of code start in file image (0x40+0x38)
dq LOAD_ADDRESS+0x78 ; virtual address of segment in memory
dq 0x0000000000000000 ; physical address of segment in memory (ignored?)
dq CODE_SIZE ; size (bytes) of segment in file image
dq CODE_SIZE+PRINT_BUFFER_SIZE ; size (bytes) of segment in memory
dq 0x0000000000000000 ; alignment (doesn't matter, only 1 segment)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;INCLUDES;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%include "syscalls.asm" ; requires syscall listing for your OS in lib/sys/
%include "lib/io/print_float.asm"
; void print_float(int {rdi}, double {xmm0}, long {rsi});
%include "lib/time/tick_time.asm"
; uint {rax} tick_time(void);
%include "lib/time/tock_time.asm"
; uint {rax} tock_time(void);
%include "lib/io/parse_int.asm"
; int {rax} parse_int(char* {rdi});
%include "lib/sys/exit.asm"
; void exit(byte {dil});
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;INSTRUCTIONS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START:
; check for at least 1 input
cmp qword [SYS_ARGC_START_POINTER], byte 1
jle .die
; parse the input number
mov rdi,[SYS_ARGC_START_POINTER+16]
call parse_int
; check for positive number
cmp rax,0
jle .die
cvtsi2sd xmm1,rax ; target countdown time in {xmm1}
movsd xmm2,[.millionth] ; microsecond to second conversion in {xmm2}
call tick_time
.loop:
call tock_time ; elapsed microseconds since tick in {rax}
cvtsi2sd xmm3,rax ; elapsed microsecond (float) in {xmm0}
mulsd xmm3,xmm2
movsd xmm0,xmm1
subsd xmm0,xmm3
mov rdi,SYS_STDOUT ; print countdown time
mov rsi,4
call print_float
mov rsi,.grammar+13 ; print a space and a carriage return
mov rdx,2
call print_chars
call print_buffer_flush
pxor xmm3,xmm3
comisd xmm0,xmm3
ja .loop ; check for end of countdown
mov rsi,.grammar
mov rdx,13
call print_chars
call print_buffer_flush
.die:
; exit
xor dil,dil
call exit
.grammar:
db `TIME'S UP! \n \r`
.millionth:
dq 0.000001
END:
PRINT_BUFFER: ; PRINT_BUFFER_SIZE bytes will be allocated here at runtime,
; all initialized to zeros