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
|
%ifndef _STRING_ASM
%define _STRING_ASM
; stack direction
; ---------------
; + = external
; - = local
;
; ^ must be getting old D:
;
; calling conventions
; push COUNT
; push SOURCE
; push DESTINATION
; call FUNCTION
; add sp, 6 (^ in the case of three WORDS)
;
; In C, for instance, this translate to:
; FUNCTION (DESTINATION, SOURCE, COUNT);
memset:
; Set memory with byte value
push bp ; setup stack frame
mov bp, sp ; ...
push si
push di
push cx
mov di, [bp + 4] ; destination address
mov ax, [bp + 6] ; requested byte value
mov cx, [bp + 8] ; count
cld ; will decrement address ES:DI
rep stosb ; while cx > 0
; store byte AL in ES:DI
pop cx
pop di
pop si
mov sp, bp
pop bp
ret
memcpy:
push bp ; setup stack frame
mov bp, sp ; ...
mov di, [bp + 4] ; destination buffer
mov si, [bp + 6] ; source buffer
mov cx, [bp + 8] ; count of characters to move
cld
rep movsb
mov sp, bp
pop bp
ret
strlen:
; Determine length of null terminated string
; NOTE: 64k limit imposed
push bp ; setup stack frame
mov bp, sp ; ...
push cx
push si
xor cx, cx ; cx is counter
xor ax, ax ; ax is return value
mov si, [bp + 2] ; string address
.loop:
lodsb ; load byte from ES:SI into AL
cmp al, 0 ; zero?
je .return ; if so, we're done
inc cx ; if not, keep going
jc .crash ; if we roll over CX the carry flag will be set (that's bad)
jmp .loop
.crash:
stc ; force carry flag on failure
.return:
clc
mov ax, cx
pop si
pop cx
mov sp, bp
pop bp
ret
strnchr:
; Find first occurence of character in a string
push bp ; setup stack frame
mov bp, sp ; ...
push cx
push dx
push si
xor ax, ax ; ax is return value
mov si, [bp + 4] ; string address
mov dx, [bp + 6] ; needle character
mov cx, [bp + 8] ; counter
.loop:
lodsb ; load byte at si
cmp al, dl ; same as needle?
je .return ; if true: return
dec cx ; decrement counter
jne .loop ; counter zero?
.return:
mov ax, cx ; return index of character
pop si
pop dx
pop cx
mov sp, bp
pop bp
ret
strncmp:
; Determine difference between two strings
push bp ; setup stack frame
mov bp, sp ; ...
push bx ; save registers
push dx
push si
push di
mov di, [bp + 4] ; string2 address
mov si, [bp + 6] ; string1 address
mov cx, [bp + 8] ; limit to compare
.loop:
mov bx, [si] ; string1
mov dx, [di] ; string2
inc si ; next address, string1
inc di ; next address, string2
dec cx ; decrease byte counter
cmp bx, dx ; compare bytes
jne .diff ; Just die if not-equal
cmp cx, 0 ; If equal, check for null termination
jne .loop
.diff:
cmp bx, dx
jg .s1_larger
jl .s1_smaller
je .return
.s1_smaller:
mov ax, -1
jmp .return
.s1_larger:
mov ax, cx
.return:
pop di ; cleanup stack
pop si
pop dx
pop bx
mov sp, bp
pop bp
ret
%endif ; _STRING_ASM
|