1
section .data
    msg db 10 "Enter string"
    msg_len equ $-msg
    
    
    smsg db 10 "Length is: "
    smsg_len equ $-smsg
    
    
    
    
    
section .bss
char_ans resb 2
string resb 50
string_len equ $-string
count resb 1
;----------------------------------

%macro print 2
mov rax, 1
mov rdi, 1
mov rsi, %1
mov rdx, %2
syscall
%endmacro

%macro read 2
mov rax, 0
mov rdi, 0
mov rsi, %1
mov rdx, %2
syscall
%endmacro

%macro exit 0
mov rax, 60
mov rsi, 0
syscall
%endmacro



;----------------------------------

section .text
    global _start

_start:


print msg, msg_len
read string, string_len



mov [count], rax

print smsg, smsg_len
mov rax, [count]
call display
exit



display:
    mov rbx, 16
    mov rcx, 2
    mov rsi, char_ans+1
    
cnt:
    mov rdx, 0
    div rbx
    cmp dl, 09h
    jbe add30
    add dl,37h
    
    add30:
        add dl, 30h
        mov [rsi], dl
        dec rsi
        dec rcx
        jnz cnt
print char_ans, 2
ret

i think it should be like

section .text
    global _start

_start:


print msg, msg_len
read string, string_len


mov rax, rdx               ;VALUE OF RDX MOVED TO RAX SINCE string_leN STORED IN rdx
mov [count], rax

print smsg, smsg_len
mov rax, [count]
call display
exit
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    The read system call, `read(0, string, string_len)`, returns the actual number of bytes read in RAX. (Or a `-errno` value). If you did `mov [count], rdx`, you'd just be storing the buffer size which is still in RDX (`string_len` which is an assemble-time constant `50`), not the number of bytes actually read. – Peter Cordes Jun 03 '23 at 05:08
  • not quite a duplicate of [What are the return values of system calls in Assembly?](https://stackoverflow.com/q/38751614) (which uses `read` as an example system call to discuss its return value). We've had lots of previous questions where people read into a buffer and then write out the whole buffer instead of just the part written by the `read`, so the output includes a bunch of `0` bytes. One of those Q&As could be a duplicate if I can find out. Often this goes unnoticed on the terminal since `\0` prints as zero width. – Peter Cordes Jun 03 '23 at 05:24
  • You can and should try it yourself: make that change in the source and run the program. (Use `strace ./a.out` to see the system calls it makes.) – Peter Cordes Jun 03 '23 at 07:05

1 Answers1

1

Why use RAX

If a program displays "Enter string", later followed by "Length is:", it makes sense that the length mentioned should pertain to the number of characters that were actually inputted for the string. So, very not the length of the buffer into which the input went because that would be a trivial information that you know about even before the program launches.

When using the SYSREAD function (via a macro or not), it is you that provide the length of the buffer in the RDX register and upon return it is the system function that provides you with the (positive) length of the inputted string in the RAX register (If all went well, else you receive some negative value in RAX).

Further review

mov rax, 60
mov rsi, 0
syscall

The returncode for SYSEXIT belongs in the RDI register. Typo?

count resb 1
...
mov [count], rax

If you reserve only a single byte for the count variable, then you should not be storing a full qword in that variable. It's a recipe for disaster in a program.

  cmp dl, 09h
  jbe add30
  add dl,37h
add30:
  add dl, 30h

Your display code will have trouble displaying lengths 10 and up. The extra increment that is needed for the hexdigits A through F would be 7. You erroneously are adding 37h which would be correct if and only if you would jump over the add dl, 30h instruction, something nobody should do.

This is one of the many ways you can write this conversion. It is important to note that for a hexadecimal conversion you can replace division by 16 just by shifting 4 times to the right. Division is a costly operation and especially so the 128-bit division that you were using.

; IN (al)
display:
  mov  ecx, 1
cnt:
  mov  edx, eax             ; (1)
  and  al, 15
  cmp  al, 10
  jb   .digit
  add  al, 7
.digit:
  add  al, '0'
  mov  [char_ans + rcx], al
  mov  eax, edx             ; (1)
  shr  eax, 4               ; Replaces division by 16
  dec  ecx
  jns  cnt
  print char_ans, 2
  ret
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • 1
    The raw system call in asm doesn't return `-1` on error, it return a `-errno` code. The glibc wrapper does `errno = -retval` in that case, and returns a fixed `-1`. Using `syscall` directly, you just get `-EBADF` or `-EFAULT` or whatever. – Peter Cordes Jun 04 '23 at 18:54