-
Notifications
You must be signed in to change notification settings - Fork 0
/
string.asm
227 lines (191 loc) · 5.11 KB
/
string.asm
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
; String library
; NAMESPACE: "string"
string:
; ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
; ### MACRO: "putChar"
; Places a character at the current cursor position and advances the cursor
;
; param:
; al = character to display at current position
; destroyed:
; ah
macro string.putChar
{
mov ah, 0x0E
int 0x10
}
; ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
; ### PROC: "teletype"
; Prints the string using the TTY interrupt feature, scrolling and advancing the cursor as needed.
;
; param:
; si = pointer to string, null terminated
macro string.teletype {
.teletype:
push ax
push si
mov ah, 0x0E ; 0x10 - teletype output
.teletype.nextChar:
mov al, [si]
cmp al, 0 ; if char==0 then return
jz .teletype.return
int 0x10 ; write to screen
inc si ; next character
jmp .teletype.nextChar
.teletype.return:
pop si
pop ax
ret
}
; ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
; ### PROC: "match"
; Determines if the two strings are identical.
;
; param:
; si = pointer to primary string to be compared against, null terminated
; di = pointer to secondary string to be compared, null terminated
; return:
; (flag) carry = set if match, clear if not.
macro string.match {
.match:
push ax
push si
push di
.match.nextChar:
mov ah, [si]
mov al, [di]
cmp ah, al ; if char1 != char2 then goto notEqual
jne .match.notEqual
cmp al, 0 ; elseif char2==0 then goto equal (end of strings)
je .match.equal
inc si ; else next character
inc di ; ...
jmp .match.nextChar
.match.notEqual:
clc
jmp .match.return
.match.equal:
stc
jmp .match.return
.match.return:
pop di
pop si
pop ax
ret
}
; ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
; ### PROC: "getLength"
; Determines the length of the string in number of characters, excluding the null termination character
;
; param:
; si = pointer to string, null terminated
; return:
; al = number of characters
macro string.getLength {
.getLength:
push si
mov al, 0
.getLength.nextChar:
mov ah, [si]
cmp ah, 0 ; if char==0 then goto return
je .getLength.return
inc al ; else charCount++
inc si ; next character
jmp .getLength.nextChar
.getLength.return:
pop si
ret
}
; ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
; ### PROC: "reverse"
; Reverses the string, so that the last character is first and vice versa.
;
; param:
; si = pointer to string, null terminated
; di = pointer to new string destination
; return
; di = pointer to new string, null terminated
macro string.reverse {
.reverse:
push ax
push cx
push si
push di
xor cx, cx ; clear cx for use as for-loop counter
.reverse.gotoEnd: ; count number of characters in source string, excluding null terminator
mov al, [si]
cmp al, 0
je .reverse.nextChar.setup
inc si
inc cl
jmp .reverse.gotoEnd
.reverse.nextChar.setup:
dec si ; character before null terminator
.reverse.nextChar: ; for (i=getLength(si); i>0; i--)
mov al, [si] ; [di] <== [si]
mov [di], al
dec si ; next character
inc di
loop .reverse.nextChar
.reverse.appendTerminator:
mov [di], byte 0 ; add null terminator to the end
.reverse.return:
pop di
pop si
pop cx
pop ax
ret
}
; ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
; ### PROC: "numberToString"
; Translates a number into a null terminated string value
;
; param:
; ax = number
; di = pointer to new string destination
; return:
; di = pointer to new string, null terminated
macro string.numberToString {
.numberToString:
push ax
push bx
push dx
push si
push di
mov bx, 10 ; constant used to divide by
mov si, .numberToString.rawString
; sandbox area for reversing string before returning it
xor dx, dx ; clear dx for doubleword division
cmp ax, 0 ; if (number==0) then goto numberIsZero
jz .numberToString.numberIsZero
jmp .numberToString.extractLeastSignificant
; else goto extractLeastSignificant
.numberToString.numberIsZero:
mov [di], byte '0' ; set string to '0'
inc di
mov [di], byte 0 ; append null terminator ... and return
jmp .numberToString.return
.numberToString.extractLeastSignificant:
div bx ; ax=ax/10, dx=remainder -- remainder will be the least significant number off the rest of it
add dl, 48 ; convert single digit remainder into ASCII code
mov [si], dl ; write character to string
inc si
mov dl, 0 ; sanitize dl before dividing again
cmp ax, 0 ; a quotient of 0 means that there are no more numbers to extract
jz .numberToString.flipString
jmp .numberToString.extractLeastSignificant
.numberToString.flipString:
mov [si], byte 0 ; append null terminator
mov si, .numberToString.rawString
; si = pointer to sandbox area, di = destination passed by program
call .reverse ; reverse it!
.numberToString.return:
pop di
pop si
pop dx
pop bx
pop ax
ret
.numberToString.rawString:
db 6 dup (0)
}