NASM Forum > Example Code

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

<< < (4/5) > >>

fredericopissarra:

--- Quote from: MediocreVeg1 on January 18, 2021, 03:06:55 PM ---
--- Quote ---I found strange your approach, since sub rdi,rbx (with rbx == 0) do nothing, except affect the flags. Din't you mean to use 'mov rbx,rdi' instead of 'xor rbx,rbx'?
--- End quote ---
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 ---
Nope... repnz scasb searches for AL in RDI and forward (increasing RDI and decreasing RCX). It won't change RBX.


--- Quote ---
--- Quote ---PS: Try to use E?? registers as many times as possible. Using R?? will imply a REX prefix and bigger instructions. moving and doing arithmetic/logical operations to E?? registers will automatically zero the upper 32 bits of R?? registers for you (this doen't work in a few instructions as, for example, CDQ [will zero upper RDX but not upper RAX).
--- End quote ---
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 ---
It won't get confused because E?? registers are part of R?? registers. When you use a R?? register NASM is forced to add a prefix to the instruction (REX prefix). This prefix isn't added if you use E?? registers. Of course, if the argument is an address (a pointer) you are forced to use R??.


--- Quote ---
--- Quote ---S: 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 ---
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 ---
Yep... The problem when you ser RCX to -1 is that, theoretically you can search a 18446744073709551615 bytes long string. If such string exists (not possible), than REP SCASB would take 192 YEARS to complete (@ 3 GHz). If you restrict the string to 2³²-1 bytes, if such string exists (improbable), it would take only 1.5 seconds to scan.

MediocreVeg1:

--- Quote ---Nope... repnz scasb searches for AL in RDI and forward (increasing RDI and decreasing RCX). It won't change RBX.

--- End quote ---
Oh man, I'm so stupid. How does my procedure even work then? Sheesh, now I'm even confused as to how my own procedure works :P


--- Quote ---It won't get confused because E?? registers are part of R?? registers. When you use a R?? register NASM is forced to add a prefix to the instruction (REX prefix). This prefix isn't added if you use E?? registers. Of course, if the argument is an address (a pointer) you are forced to use R??
--- End quote ---
Oh, I see. Would that mean that I would be able to enter the call number in eax too? And for example in the second argument of a system call, would I use ebx or edi for 32-bit registers?


--- Quote ---Yep... The problem when you ser RCX to -1 is that, theoretically you can search a 18446744073709551615 bytes long string. If such string exists (not possible), than REP SCASB would take 192 YEARS to complete (@ 3 GHz). If you restrict the string to 2³²-1 bytes, if such string exists (improbable), it would take only 1.5 seconds to scan.
--- End quote ---
Wow, that's... a lot. Anyway, I think this answers my question. Thanks.

fredericopissarra:

--- Quote from: MediocreVeg1 ---Oh man, I'm so stupid. How does my procedure even work then? Sheesh, now I'm even confused as to how my own procedure works :P
--- End quote ---
I confesss I cannot see how it works, too... ;)


--- Quote ---Oh, I see. Would that mean that I would be able to enter the call number in eax too? And for example in the second argument of a system call, would I use ebx or edi for 32-bit registers?
--- End quote ---
A simple example. If you want to print a string you can do:

--- Code: ---  bits 64
  default rel   ; Use RIP relative addressing.

  section .rodata

msg: db `Hello\n`
msg_len equ $ - msg

  section .text

  global writemsg
writemsg:
  mov eax,1    ; EAX, instead of RAX will zero upper 32 bits.
  mov edi,eax  ; RDI=STDOUT_FILENO (upper 32 bits zeroed).
  lea rsi,[msg] ; Need to load RSI (because it is a pointer). LEA because 'msg' is RIP relative.
  mov edx,msg_len ; RDX (upper 32 bits zeroed).
  syscall
  ret
--- End code ---

Those E?? movs are shorter than if you use R?? regs.

[]s
Fred

MediocreVeg1:

--- Quote ---I confesss I cannot see how it works, too...  ;)
--- End quote ---
Yeah, I think I'll change my thing to your not solution so I at least understand what is going on.

And about the registers, I think I finally get it now. Thanks for all the help!

munair:
Just getting my feed wet with 64 bits (yes, my very first code)  :D. If I understand correctly, there is some optimization to be gained from using 32 bit registers with the string length (which would probably never exceed 4GB).

As usual, no C externals here.  ;D

--- Code: ---; nasm -f elf64 puts.asm
; ld -m elf_x86_64 puts.o -o puts

bits 64

section .text

    global _start

_start:
    mov     rdi, msg            ; string
    call    strlen              ; length
    test    rax, rax            ; anyhing?
    jz      .__out
    call    puts                ; show it
  .__out:
    mov     rax, 0x3c
    xor     rdi, rdi
    syscall

puts:
    mov     rsi, rdi            ; string
    mov     rdi, 1              ; stdout
    mov     rdx, rax            ; length (from strlen)
    mov     rax, 1              ; write
    syscall
    ret

strlen:
    push    rdi                 ; save address
    sub     rcx, rcx
    not     rcx                 ; rcx -1
    xor     eax, eax
    cld                         ; count forward
    repne   scasb
    not     rcx
    lea     rax, [rcx - 1]      ; length
    pop     rdi
    ret

section .data
    msg db "Hello world!", 10, 0

--- End code ---

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version