Author Topic: My own 64-bit `puts' instruction (No length required)  (Read 19502 times)

Online fredericopissarra

  • Full Member
  • **
  • Posts: 307
  • Country: br
Re: My own 64-bit `puts' instruction (No length required)
« Reply #15 on: January 18, 2021, 06:40:38 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'?
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.
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).
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?
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:
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?
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.
« Last Edit: January 18, 2021, 06:42:38 PM by fredericopissarra »

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: My own 64-bit `puts' instruction (No length required)
« Reply #16 on: January 19, 2021, 11:31:18 AM »
Quote
Nope... repnz scasb searches for AL in RDI and forward (increasing RDI and decreasing RCX). It won't change RBX.
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??
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.
Wow, that's... a lot. Anyway, I think this answers my question. Thanks.

Online fredericopissarra

  • Full Member
  • **
  • Posts: 307
  • Country: br
Re: My own 64-bit `puts' instruction (No length required)
« Reply #17 on: January 19, 2021, 05:13:06 PM »
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
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?
A simple example. If you want to print a string you can do:
Code: [Select]
  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

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

[]s
Fred
« Last Edit: January 20, 2021, 12:31:01 PM by fredericopissarra »

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: My own 64-bit `puts' instruction (No length required)
« Reply #18 on: January 19, 2021, 05:27:09 PM »
Quote
I confesss I cannot see how it works, too...  ;)
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!