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
|
; Gotta get these loops down... seriously.
; Let's try to write a more manual puts function
section .text
global _start
print_newline:
push ebp ; push previous function frame pointer into stack
mov ebp, esp ; assign new frame pointer
pusha ; save all registers
mov eax, 4 ; linux write syscall
mov ebx, 1 ; stdout
mov ecx, LF ; newline char
mov edx, 2 ; 2 bytes long
int 80h
popa ; restore all registers
leave ; restore stack frame
ret
putc:
; purpose:
; print character
; arguments:
; ECX - character address
push ebp ; push previous function frame pointer into stack
mov ebp, esp ; assign new frame pointer
pusha ; save all registers, we're about to use them up
mov eax, 4 ; linux write syscall
mov ebx, 1 ; stdout
mov edx, 1
int 80h
popa ; restore all registers
leave ; restore stack frame
ret
puts:
; purpose:
; print a NULL terminated string followed by a new line
; ... character-by-character
; arguments:
; ECX - char. string
push ebp
mov ebp, esp
.loop:
mov al, [ecx] ; copy current char into 8-bit register
inc ecx ; increment pointer
mov [char], al ; copy 8-bit character into `char` variable
push eax ; save eax, we're modifying EAX (via al)
push ecx ; save ecx, to replace/send single char reference
mov ecx, char ; putc expects ECX to have a "string" so
; copy the character into the register
call putc ; print character to display
; REMEMBER THE ORDER OF PUSHES
pop ecx ; restore registers
pop eax ; ...
cmp al, 0 ; check for NULL terminator
jz .break ; if al == 0: break loop
jmp .loop ; else: repeat
.break:
call print_newline ; pretend this is C... eh?
leave ; restore stack
ret
exit:
mov eax, 1 ; linux function, terminate
mov ebx, 0 ; return value
int 80h ; linux kernel syscall
ret
display_copyright:
push ebp
mov ebp, esp
push ecx
mov ecx, copyright
call puts
pop ecx
leave
ret
display_version:
push ebp
mov ebp, esp
mov ecx, version
call puts
leave
ret
_start:
call display_copyright
call display_version
call exit
ret
section .data
copyright db 'Joseph Hunkeler (c) 2015,', 32
db 'All things reserved and whatever.', 0
version db 'Version 1.0.0'
LF db 13, 10 ; ascii newline
section .bss
char resb 1 ; reserve one byte for 'puts' to use as a buffer
|