patternMinor
X86_64 implementation of STRCHR using NASM
Viewed 0 times
strchrx86_64usingimplementationnasm
Problem
As this will eventually become part of an operating system I'm developing, there is no specific adherence to any particular
One of my methodologies is to utilize as many bits of the register as possible, especially when 16 or less are significant. I have found too, that in a lot of cases this can simplify calling process. It does however complicate things a little ie:
This would traverse the buffer pointed to by RDI for the first occurence of period for a maximum of 784 characters. This snippet had evolved from just scanning for NULL for a maximum of FFFFFFFFH bytes, to scanning for any of the values (0 - FF), to traversing buffer for specified number of bytes.
Question
Do you think I've achived the maximum utility with the least amount of code.
```
; Determine length, including terminating character EOS. Result may include
; VT100 escape sequences.
; ENTER: RDI = Pointer to ASCII string.
; RCX Bits 31 - 08 = Max chars to scan (1 - 1.67e7)
; 07 - 00 = Terminating character (0 - FF)
; LEAVE: RAX = Pointer to next string (optional).
; FLAGS: ZF = Terminating character found, NZ otherwise (overrun).
; DF = Unmodified incase it was already set.
strlen: pushf ; Preserve DF (Direction flag)
push rcx ; Preserve registers used by proc so
push rdi ; its non-destructive except for RAX.
mov al, cl ; Byte to scan for in AL.
shr ecx, 8 ; Shift max count into bits 23 - 00
std ; Auto decrement.
repnz scasb
ABI, even though this is being developed and tested on Ubuntu 16.04. My OS will however adopt a SYSTEM V paradigm insomuch as passing values by register, but they will be passed in the one most suitable to the algorithm.One of my methodologies is to utilize as many bits of the register as possible, especially when 16 or less are significant. I have found too, that in a lot of cases this can simplify calling process. It does however complicate things a little ie:
mov rdi, Pointer_to_String
mov ecx, 784 << 8 | '.'
call strlenThis would traverse the buffer pointed to by RDI for the first occurence of period for a maximum of 784 characters. This snippet had evolved from just scanning for NULL for a maximum of FFFFFFFFH bytes, to scanning for any of the values (0 - FF), to traversing buffer for specified number of bytes.
Question
Do you think I've achived the maximum utility with the least amount of code.
```
; Determine length, including terminating character EOS. Result may include
; VT100 escape sequences.
; ENTER: RDI = Pointer to ASCII string.
; RCX Bits 31 - 08 = Max chars to scan (1 - 1.67e7)
; 07 - 00 = Terminating character (0 - FF)
; LEAVE: RAX = Pointer to next string (optional).
; FLAGS: ZF = Terminating character found, NZ otherwise (overrun).
; DF = Unmodified incase it was already set.
strlen: pushf ; Preserve DF (Direction flag)
push rcx ; Preserve registers used by proc so
push rdi ; its non-destructive except for RAX.
mov al, cl ; Byte to scan for in AL.
shr ecx, 8 ; Shift max count into bits 23 - 00
std ; Auto decrement.
repnz scasb
Solution
Bug #1
You set the
Bug #2
If you reach the byte limit, your function will return the original string pointer in
Bug #3
According to the comments, your function should return with
Your own ABI
I would suggest following the standard X64 ABI rather than inventing a new ABI per function. For one thing, you will be able to use high level languages to interface with your assembly routines. Another thing is that it would be hard for you to remember details such as "when I call strlen, ZF set means that the terminating character was found".
Don't call it strlen
Your function is closer to
You set the
DF flag, so your string operation is going to run backwards. You should clear the DF flag to scan your string in the forwards direction.Bug #2
If you reach the byte limit, your function will return the original string pointer in
RAX. The comment says it should return NULL. Perhaps you meant xor rax, rax instead of mov rax, rdi?Bug #3
According to the comments, your function should return with
ZF set according to the result of the scan. However, since you do pushf and then popf, the ZF result is wiped out by the popf.Your own ABI
I would suggest following the standard X64 ABI rather than inventing a new ABI per function. For one thing, you will be able to use high level languages to interface with your assembly routines. Another thing is that it would be hard for you to remember details such as "when I call strlen, ZF set means that the terminating character was found".
Don't call it strlen
Your function is closer to
strchr or strnchr than strlen. Any reasonable person would expect a function called strlen to return a length rather than a pointer.Context
StackExchange Code Review Q#144861, answer score: 6
Revisions (0)
No revisions yet.