NASM Forum > Example Code

My own 64-bit `puts' instruction (No length required)

<< < (5/5)

fredericopissarra:

--- Quote from: MediocreVeg1 on January 18, 2021, 03:06:55 PM ---Maybe I'm not understanding how scas works, but isn't the result of scasb stored in rbx in 64-bit assembly? That's why I cleared it with XOR before using scasb and why I substracted it from rdi (which has starting address of string). I'm probably wrong here though.
--- End quote ---
SCASB reads from ES:RDI and compares with AL, affecting the flags, and updates RDI. With REP (or REPNZ) prefix it does RCX times while ZF=0 (hence the NZ). So strlen could be implemented as:

--- Code: ---; Same as: size_t strlen( const char * );
; the function assumes ALL strings will be NUL terminated.
strlen_:
  xor eax,eax
  lea ecx,[rax-1]   ; Limiting the string size to 2³²-1, max.
  mov rdx,rdi
  repnz scasb     ; Scan for '\0'...
  sub rdi,rdx
  mov rax,rdi     ; returns size in RAX.
  ret
--- End code ---


--- Quote from: MediocreVeg1 on January 18, 2021, 03:06:55 PM ---Wouldn't the assembler get confused if I used 64-bit syscalls on 32-bit registers? Or if I put some arguments of a syscall in R?? registers and others in E?? registers?
--- End quote ---
E?? registers are the lower part of R?? registers. And, in x86-64 mode, when you change E?? register the upper 32 bits of R?? register is automatically zeroed... Instructions using R?? registers need to insert an prefix (REX prefix), with E?? no prefix...


--- Quote from: MediocreVeg1 on January 18, 2021, 03:06:55 PM ---Wouldn't the assembler
--- Quote ---Notice in my routine, if '\0' isn't found in a block of 2³²-1 bytes it returns -1 (all bits set) in RAX. This allows you to test an error:
--- End quote ---
... Wouldn't this event be highly unlikely though? ...
--- End quote ---
You are right!... It easier to assume the routine expects ALL strings to be zero terminated...

munair:

--- Quote from: fredericopissarra on July 22, 2023, 11:46:12 AM ---So strlen could be implemented as:

--- Code: ---; Same as: size_t strlen( const char * );
; the function assumes ALL strings will be NUL terminated.
strlen_:
  xor eax,eax
  lea ecx,[rax-1]   ; Limiting the string size to 2³²-1, max.
  mov rdx,rdi
  repnz scasb     ; Scan for '\0'...
  sub rdi,rdx
  mov rax,rdi     ; returns size in RAX.
  ret
--- End code ---

--- End quote ---

That would return string length + 1. So alternatively:


--- Code: ---    xor     eax, eax
    lea     ecx, [rax - 1]
    mov     rdx, rdi
    repnz   scasb
    sub     rdi, rdx
    ;mov     rax, rdi
    lea     rax, [rdi - 1]        ; not counting the null terminator

--- End code ---

fredericopissarra:

--- Quote from: munair on July 22, 2023, 03:38:17 PM ---That would return string length + 1....

--- End quote ---
Ops... sorry... my bad...

alCoPaUL:
you can just iterate displaying letters until it's \0..

so you can display a 1 gigabyte or more worth of strings and then cut it when it's \0.

fredericopissarra:

--- Quote from: MediocreVeg1 on January 18, 2021, 03:06:55 PM ---Maybe I'm not understanding how scas works, but isn't the result of scasb stored in rbx in 64-bit assembly?
--- End quote ---
Nope! scasb tests AL against ES:[RDI], setting the flags. repnz scasb does the same, RCX times while ZF=0.


--- Quote from: MediocreVeg1 ---Wouldn't the assembler get confused if I used 64-bit syscalls on 32-bit registers? Or if I put some arguments of a syscall in R?? registers and others in E?? registers?
--- End quote ---
Nope! E?? registers are the lower 32 bits of R?? registers. When you use a R?? register the instrunction is prefixed with a REX prefix (and, an immediate can be bigger), like, for example:


--- Code: ---  mov eax,-1    ; B8 FF FF FF FF
  mov rax,-1    ; 48 B8 FF FF FF FF FF FF FF FF
--- End code ---

When using EAX the upper 32 bits are automagically (hehe) zeroed.


--- Quote from: MediocreVeg1 ---Yeah, I put it into my procedure as well after you showed your example. Wouldn't this event be highly unlikely though? I think 2^32-1 is like 4294967295 bytes so every single byte after the starting address of the string would have to be non-zero, right?
--- End quote ---
That's why it doesn't make sense using R?? registers to hold string lengths...

[]s
Fred

Navigation

[0] Message Index

[*] Previous page

Go to full version