-
Notifications
You must be signed in to change notification settings - Fork 126
Expand file tree
/
Copy pathfunctions.asm
More file actions
160 lines (133 loc) · 6.18 KB
/
functions.asm
File metadata and controls
160 lines (133 loc) · 6.18 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
;------------------------------------------
; int atoi(Integer number)
; Ascii to integer function (atoi)
atoi:
push ebx ; preserve ebx on the stack to be restored after function runs
push ecx ; preserve ecx on the stack to be restored after function runs
push edx ; preserve edx on the stack to be restored after function runs
push esi ; preserve esi on the stack to be restored after function runs
mov esi, eax ; move pointer in eax into esi (our number to convert)
mov eax, 0 ; initialise eax with decimal value 0
mov ecx, 0 ; initialise ecx with decimal value 0
.multiplyLoop:
xor ebx, ebx ; resets both lower and uppper bytes of ebx to be 0
mov bl, [esi+ecx] ; move a single byte into ebx register's lower half
cmp bl, 48 ; compare ebx register's lower half value against ascii value 48 (char value 0)
jl .finished ; jump if less than to label finished
cmp bl, 57 ; compare ebx register's lower half value against ascii value 57 (char value 9)
jg .finished ; jump if greater than to label finished
sub bl, 48 ; convert ebx register's lower half to decimal representation of ascii value
add eax, ebx ; add ebx to our interger value in eax
mov ebx, 10 ; move decimal value 10 into ebx
mul ebx ; multiply eax by ebx to get place value
inc ecx ; increment ecx (our counter register)
jmp .multiplyLoop ; continue multiply loop
.finished:
cmp ecx, 0 ; compare ecx register's value against decimal 0 (our counter register)
je .restore ; jump if equal to 0 (no integer arguments were passed to atoi)
mov ebx, 10 ; move decimal value 10 into ebx
div ebx ; divide eax by value in ebx (in this case 10)
.restore:
pop esi ; restore esi from the value we pushed onto the stack at the start
pop edx ; restore edx from the value we pushed onto the stack at the start
pop ecx ; restore ecx from the value we pushed onto the stack at the start
pop ebx ; restore ebx from the value we pushed onto the stack at the start
ret
;------------------------------------------
; void iprint(Integer number)
; Integer printing function (itoa)
iprint:
push eax ; preserve eax on the stack to be restored after function runs
push ecx ; preserve ecx on the stack to be restored after function runs
push edx ; preserve edx on the stack to be restored after function runs
push esi ; preserve esi on the stack to be restored after function runs
mov ecx, 0 ; counter of how many bytes we need to print in the end
.divideLoop:
inc ecx ; count each byte to print - number of characters
mov edx, 0 ; empty edx
mov esi, 10 ; mov 10 into esi
idiv esi ; divide eax by esi
add edx, 48 ; convert edx to it's ascii representation - edx holds the remainder after a divide instruction
push edx ; push edx (string representation of an intger) onto the stack
cmp eax, 0 ; can the integer be divided anymore?
jnz .divideLoop ; jump if not zero to the label divideLoop
.printLoop:
dec ecx ; count down each byte that we put on the stack
mov eax, esp ; mov the stack pointer into eax for printing
call sprint ; call our string print function
pop eax ; remove last character from the stack to move esp forward
cmp ecx, 0 ; have we printed all bytes we pushed onto the stack?
jnz .printLoop ; jump is not zero to the label printLoop
pop esi ; restore esi from the value we pushed onto the stack at the start
pop edx ; restore edx from the value we pushed onto the stack at the start
pop ecx ; restore ecx from the value we pushed onto the stack at the start
pop eax ; restore eax from the value we pushed onto the stack at the start
ret
;------------------------------------------
; void iprintLF(Integer number)
; Integer printing function with linefeed (itoa)
iprintLF:
call iprint ; call our integer printing function
push eax ; push eax onto the stack to preserve it while we use the eax register in this function
mov eax, 0Ah ; move 0Ah into eax - 0Ah is the ascii character for a linefeed
push eax ; push the linefeed onto the stack so we can get the address
mov eax, esp ; move the address of the current stack pointer into eax for sprint
call sprint ; call our sprint function
pop eax ; remove our linefeed character from the stack
pop eax ; restore the original value of eax before our function was called
ret
;------------------------------------------
; int slen(String message)
; String length calculation function
slen:
push ebx
mov ebx, eax
.nextchar:
cmp byte [eax], 0
jz .finished
inc eax
jmp .nextchar
.finished:
sub eax, ebx
pop ebx
ret
;------------------------------------------
; void sprint(String message)
; String printing function
sprint:
push edx
push ecx
push ebx
push eax
call slen
mov edx, eax
pop eax
mov ecx, eax
mov ebx, 1
mov eax, 4
int 80h
pop ebx
pop ecx
pop edx
ret
;------------------------------------------
; void sprintLF(String message)
; String printing with line feed function
sprintLF:
call sprint
push eax
mov eax, 0AH
push eax
mov eax, esp
call sprint
pop eax
pop eax
ret
;------------------------------------------
; void exit()
; Exit program and restore resources
quit:
mov ebx, 0
mov eax, 1
int 80h
ret