summaryrefslogtreecommitdiff
path: root/string.asm
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2018-06-19 00:50:32 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2018-06-19 00:50:32 -0400
commit16ce91dac78f9a522d6b5a5f4b0f651e25635a4f (patch)
tree22ac100db4e4f42ec9f58e57614bc2dcb8d6bebf /string.asm
parent49094cc0b0f1c0031d8c5cfb4b64c3937a529b85 (diff)
downloadminos-16ce91dac78f9a522d6b5a5f4b0f651e25635a4f.tar.gz
Fix string handling
* Remove the stupid from strlen * Rewrite strtok to be more practical
Diffstat (limited to 'string.asm')
-rw-r--r--string.asm154
1 files changed, 83 insertions, 71 deletions
diff --git a/string.asm b/string.asm
index cd5d1bc..aafe30c 100644
--- a/string.asm
+++ b/string.asm
@@ -61,29 +61,22 @@ memcpy:
strlen:
; Determine length of null terminated string
- ; NOTE: 64k limit imposed
- push bp ; setup stack frame
- mov bp, sp ; ...
+ 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
+ xor cx, cx ; cx is counter
+ xor ax, ax ; ax is return value
+ mov si, [bp + 4] ; 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)
-
+ 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
jmp .loop
-.crash:
- stc ; force carry flag on failure
-
.return:
- clc
mov ax, cx
pop si
pop cx
@@ -170,69 +163,88 @@ strncmp:
pop bp
ret
-
strtok:
- push bp
- mov bp, sp
- push bx
- push cx
- push dx
- push di
- push si
-
- xor ax, ax ; clear AX for delimter
- xor bx, bx
- xor cx, cx ; initialize string length counter
- xor dx, dx ; initialize record counter
- xor si, si
- xor di, di
-
- sub sp, 2 ; reserve stack variable
- mov word [bp - 2], 0 ; final_pass = [bp - 2]
-
- mov di, [bp + 4] ; arg1 - null terminated string
- mov si, [bp + 6] ; arg2 - address of results array
- mov al, [bp + 8] ; arg3 - delimiter value
- cld ; clear direction flag (0)
-
- jmp .strtok_scan ; begin scan
-
- .strtok_record_token:
- inc dx ; increase record count
- mov bx, di ; store address of delimiter
- sub bx, cx ; subtract length from address
- ; to get start of string
-
- mov [si], bx ; store start of word
- mov [si+2], cx ; store length of word
-
- add si, 4 ; increment array pointer
- xor cx, cx ; reset counter
- cmp word [bp - 2], 0 ; is this the final pass?
- jne .strtok_return ; if so, return
- ; else, fall through
- .strtok_scan:
- inc cx
- scasb ; scan for delimiter in AL
- je .strtok_record_token ; if ZF=1, store pointer
- cmp byte [di], 0 ; if null terminated, exit loop
- jne .strtok_scan ; else continue
-
- mov word [bp - 2], 1 ; indicate final pass in progress
- dec bx ; adjust final address for null termination
- jmp .strtok_record_token ; process final address
+ push bp
+ mov bp, sp
+
+ push bx ; save GPRs
+ push cx
+ push dx
+ push di
+ push si
+
+ xor ax, ax ; use: for delimter (LSB)
+ xor bx, bx ; use: base address for effective address calculations
+ xor cx, cx ; use: input string length counter
+ xor dx, dx ; use: temp for string comparison
+ xor si, si ; use: token array
+ xor di, di ; use: input string
+
+ mov di, [bp + 4] ; arg1 - input string (null terminated)
+ mov si, [bp + 6] ; arg2 - address of token array
+ mov al, [bp + 8] ; arg3 - delimter value
+
+ cld ; clear direction flag
+
+ .find_first:
+ mov dl, byte [di] ; Load byte from input string
+ cmp dl, al ; is it the delimiter?
+ jne .calculate_length ; if not, calculate length of string at this address
+ inc di ; else, scan next byte
+ jmp .find_first
+
+ .calculate_length:
+ push ax ; save delimiter
+ push di ; get length of null terminated string
+ call strlen
+ add sp, 2
+ mov cx, ax ; count is return value
+ pop ax ; restore delimiter
+
+ lea bx, [di] ; load initial address for _no_adjust
+ jmp .strtok_record_no_adjust
+
+
+ .strtok_record_eos:
+ mov byte [di], 0 ; Null terminate token
+
+ .strtok_record:
+ lea bx, [di + 1] ; The address following the null terminated token
+ ; points to our new token address
+
+ .strtok_record_no_adjust:
+ mov [si], bx ; store address in results array
+ add si, 2 ; increment results array by one WORD
+ inc di ; increment input string
+ dec cx ; decrement input string length counter
+
+ .strtok_scan:
+ mov dl, byte [di] ; load byte from input string
+ cmp dl, 0 ; is it the end of the string?
+ je .strtok_return
+
+ cmp dl, al ; is this the delimiter?
+ je .strtok_record_eos ; if yes, record the address
+
+ dec cx ; decrement input string length counter
+ inc di ; increment input string
+ jmp .strtok_scan ; loop until scanning is done
+
+ cmp cx, 0 ; if the counter is not zero there's more to parse
+ jne .strtok_record ; loop until token parsing is done
+
.strtok_return:
- add sp, 2
- mov ax, dx ; return record count
- pop si
+ mov ax, [bp + 6] ; return token array
+
+ pop si ; restore GPRs
pop di
pop dx
pop cx
pop bx
- mov sp, bp
- pop bp
+ mov sp, bp
+ pop bp
ret
%endif ; _STRING_ASM