### Author Topic: Title : difficulty with two consecutive reads  (Read 4906 times)

#### dcastellacci

• Jr. Member
• Posts: 2
##### Title : difficulty with two consecutive reads
« on: August 21, 2022, 06:23:52 AM »

Hello

I don't understand why when there are two read input1 and input2 the input1 ends up with the two values of input1 first input and input2 second input.

Thank you
Didier

Code: [Select]
`    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [prompt1]    mov edx, len1 ; len    int 80h    mov eax, 3 ; read    mov ebx, 0 ; stdin    lea ecx, [input1]    mov edx, 10 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [outmsg1]    mov edx, len4 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [input1]    mov edx, 10 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [prompt2]    mov edx, len2 ; len    int 80h    mov eax, 3 ; read    mov ebx, 0 ; stdin    lea ecx, [input2]    mov edx, 10 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [outmsg1]    mov edx, len3 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [input2]    mov edx, 10 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [prompt9]    mov edx, len9 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [input1]    ;mov edx, 10 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [prompt8]    mov edx, len8 ; len    int 80h    mov eax, 4 ; write    mov ebx, 1 ; stdout    lea ecx, [input2]    ;mov edx, 10 ; len    int 80h    ;Exiting    mov eax, 1    mov ebx, 0    int 80h`

here is the output

Code: [Select]
`./third-PB-ReadEnter a number: 128You entered: 128Enter another number: 150You entered: 150Contains input1: 128150Contains input2: 150 `

#### dcastellacci

• Jr. Member
• Posts: 2
##### Re: Title : difficulty with two consecutive reads
« Reply #1 on: August 21, 2022, 06:36:48 AM »

here is the full program

Code: [Select]
`segment .dataprompt1: db "Enter a number: ", 0len1: equ \$-prompt1prompt2: db "Enter another number: ", 0len2: equ \$-prompt2outmsg1: db "You entered: ", 0len3: equ \$-outmsg1outmsg2: db "The sum is: ", 0len4: equ \$-outmsg2prompt1size1: db "Enter a size of number < 10 for size1: ", 0len1size1: equ \$-prompt1size1prompt2size2: db "Enter another size of number < 10 for size2: ", 0len2size2: equ \$-prompt2size2prompt9: db "Contains input1: ", 0len9: equ \$-prompt9prompt8: db "Contains input2: ", 0len8: equ \$-prompt8nl: db 10segment .bssinput1: resb 10input2: resb 10segment .text        global _start_start:        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt1]        mov edx, len1 ; len        int 80h        mov eax, 3  ; read        mov ebx, 0  ; stdin        lea ecx, [input1]        mov edx, 10  ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [outmsg1]        mov edx, len4 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input1]        mov edx, 10 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt2]        mov edx, len2 ; len        int 80h        mov eax, 3  ; read        mov ebx, 0  ; stdin        lea ecx, [input2]        mov edx, 10  ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [outmsg1]        mov edx, len3 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input2]        mov edx, 10 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt9]        mov edx, len9 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input1]        ;mov edx, 10  ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt8]        mov edx, len8 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input2]        ;mov edx, 10  ; len        int 80h        ;Exiting        mov eax, 1        mov ebx, 0        int 80h`

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #2 on: August 21, 2022, 08:37:46 AM »
Hi Didier,

Welcome to the forum.

I think you may not have a problem... or not the problem you think...

When the pesky user (you) enters the first number... and "enter"... eax will contain the number of characters entered... plus one for the "enter". Save this number! When you print out the contents of the first number, use this number, not 10. I think you've got one number in each buffer, but are printing them both!

Since this is Linux, I can try it, and probably will, but not right now, I just got up to pee and am going back to bed.

Later,
Frank

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #3 on: August 24, 2022, 04:45:14 AM »
Code: [Select]
`segment .dataprompt1: db "Enter a number: ", 0len1: equ \$-prompt1prompt2: db "Enter another number: ", 0len2: equ \$-prompt2outmsg1: db "You entered: ", 0len3: equ \$-outmsg1outmsg2: db "The sum is: ", 0len4: equ \$-outmsg2prompt1size1: db "Enter a size of number < 10 for size1: ", 0len1size1: equ \$-prompt1size1prompt2size2: db "Enter another size of number < 10 for size2: ", 0len2size2: equ \$-prompt2size2prompt9: db "Contains input1: ", 0len9: equ \$-prompt9prompt8: db "Contains input2: ", 0len8: equ \$-prompt8nl: db 10segment .bssinput1: resb 10inlen1 resd 1input2: resb 10inlen2 resd 1segment .text        global _start_start:        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt1]        mov edx, len1 ; len        int 80h        mov eax, 3  ; read        mov ebx, 0  ; stdin        lea ecx, [input1]        mov edx, 10  ; len:     lea ecx, [prompt1]        mov edx, len1 ; len        int 80h        mov eax, 3  ; read        mov ebx, 0  ; stdin        lea ecx, [input1]        mov edx, 10  ; len        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt1]        mov edx, len1 ; len        int 80h        mov eax, 3  ; read        mov ebx, 0  ; stdin        lea ecx, [input1]        mov edx, 10  ; len        int 80h        mov [inlen1], eax        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [outmsg1]        mov edx, len4 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input1]        mov edx, [inlen1] ; len:        mov edx, [inlen1] ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt2]        mov edx, len2 ; len        int 80h        mov eax, 3  ; read        mov ebx, 0  ; stdin        lea ecx, [input2]        mov edx, 10  ; len        int 80h        mov [inlen2], eax        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [outmsg1]        mov edx, len3 ; len        int 80h        mov eax, 4  ; write:        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input2]        mov edx, [inlen2] ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt9]        mov edx, len9 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input1]        mov edx, [inlen1]  ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt8]        mov edx, len8 ; len:        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input1]        mov edx, [inlen1]  ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [prompt8]        mov edx, len8 ; len        int 80h        mov eax, 4  ; write        mov ebx, 1  ; stdout        lea ecx, [input2]        mov edx, [inlen2]  ; len        int 80h        ;Exiting        mov eax, 1        mov ebx, 0        int 80h`
Well, I'm pretty sure the above is badly screwed up. I'm having a problem doing something as simple as copying and pasting. If it were right, it would confirm that you don't have a problem.

I notice that you have a prompt for "sum" but don't use it. Do you know how to do that?

Best,
Frank

#### fredericopissarra

• Full Member
• Posts: 371
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #4 on: August 24, 2022, 03:13:56 PM »

1 - If you are using a distribution in amd64 mode (x86-64), use x86-64 syscalls, not i386;
2 - read syscalls will read blocks of bytes and return its sizes (-1 in case of error);
3 - If you aren't going to write a subroutine, use well documenten macros. Your code will be smaller and with less errors;
4 - Instead of using .data section to store read-only strings, use .rodata;
5 - Keep your labels consistent.
6 - `equ` is a directive, what preceeds it is NOT a label, but a symbol.

Example:
Code: [Select]
`; test.asm;;   nasm -felf64 -o test.o test.asm;   ld -s -o test test.o;  bits  64  default rel  %include "macros.inc"  section .rodataprompt:     db  "Enter value: "prompt_len  equ \$ - prompterrmsg:     db  "Error reading value from stdin."crlf:       db  `\n`crlf_len    equ \$ - crlferrmsg_len  equ \$ - errmsg  section .bssinputbuf:     resb  12inputbuf_len  equ \$ - inputbuf  section .text  global  _start  align 4_start:  ; Write prompt.  lea   rsi,[prompt]  mov   edx,prompt_len  stdout_write  ; Read data from keyboard.  lea   rsi,[inputbuf]  push  rsi               ; save buffer addr to print later  mov   edx,inputbuf_len  stdin_read  test  eax,eax           ; return < 0?  js    .error            ; yes, error!  pop   rsi               ; restore buffer addr to print.  mov   edx,eax           ; size is returned by read syscall  stdout_write  ; Print '\n'.  lea   rsi,[crlf]  mov   edx,crlf_len  stdout_write  exit  0.error:  add   rsp,8             ; we have a saved input buffer ptr on stack.                          ; dispose of it.  lea   rsi,errmsg  mov   edx,errmsg_len  stdout_write  exit 1`
Code: [Select]
`; macros.inc; Entry: RSI = buffer ptr;        EDX = buffer size; Output: EAX = size writen or < 0 if error.; Destroys: RDI (any other?)%macro stdout_write 0  mov   eax,1     ; write syscall  mov   edi,eax   ; stdout  syscall%endmacro; Entry: RSI = buffer ptr;        EDX = buffer size; Output: EAX = size read or < 0 if error.; Destroys: RDI (any other?)%macro stdin_read 0  xor   eax,eax   ; read syscall  mov   edi,eax   ; stdin  syscall%endmacro; Entry: (none) - exitcode is taken from macro usage; Do not return to the caller.%macro exit 1  mov   eax,60  mov   edi,%1  syscall%endmacro`
If you need to deal with data read from stdin as if it is an integer, you need to convert to it (atoi). And if you need to print an integer, you need to convert it to a string (itoa?). These routines aren't supplied by syscalls, you need to code your own.

Another note: `.bss` section isn't present on the binary image. Is allocated by the program loader and it is constumary to zero it all at startup. The linker (ld) uses a script filled with some symbols that will help to do this:
Code: [Select]
`  extern __bss_start  extern _end_start:  ; Zero the entire BSS.  mov   rdi,__bss_start  mov   rcx,_end  sub   rcx,rdi  inc   rcx  xor   eax,eax  rep   stosb  ...`Call "ld --verbose" from your comamand line to see the default ld script.

[]s
Fred
« Last Edit: August 24, 2022, 03:29:58 PM by fredericopissarra »

#### fredericopissarra

• Full Member
• Posts: 371
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #5 on: August 24, 2022, 03:38:16 PM »
Another piece of info that may be useful: As per SysV ABI i386 or x86-64, ESP (or RSP) points to 'argc' integer, and ESP+4 (or RSP+8) points to the begining of char * argv array terminating in 0 (NULL). So... if you wanted to get the input string from command line you could do:
Code: [Select]
`_start:  cmp   dword [rsp],2  jne   .error_args  mov   rsi,[rsp+8+1*8]   ; get argv[1].  ....error_args:  ; deal with argc != 2 here  ...`This works exactly as `main()`, in C.

#### fredericopissarra

• Full Member
• Posts: 371
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #6 on: August 24, 2022, 03:56:30 PM »

1 - If you are using a distribution in amd64 mode (x86-64), use x86-64 syscalls, not i386;
2 - read syscalls will read blocks of bytes and return its sizes (-1 in case of error);
3 - If you aren't going to write a subroutine, use well documented macros. Your code will be smaller and with less errors;
4 - Instead of using .data section to store read-only strings, use .rodata;
5 - Keep your labels consistent.
6 - `equ` is a directive, what preceeds it is NOT a label, but a symbol.

Example:
Code: [Select]
`; test.asm;;   nasm -felf64 -o test.o test.asm;   ld -s -o test test.o;  bits  64  default rel  %include "macros.inc"  section .rodataprompt:     db  "Enter value: "prompt_len  equ \$ - prompterrmsg:     db  "Error reading value from stdin."crlf:       db  `\n`crlf_len    equ \$ - crlferrmsg_len  equ \$ - errmsg  section .bssinputbuf:     resb  12inputbuf_len  equ \$ - inputbuf  section .text  global  _start  align 4_start:  ; Write prompt.  lea   rsi,[prompt]  mov   edx,prompt_len  stdout_write  ; Read data from keyboard.  lea   rsi,[inputbuf]  push  rsi               ; save buffer addr to print later  mov   edx,inputbuf_len  stdin_read  test  eax,eax           ; return < 0?  js    .error            ; yes, error!  pop   rsi               ; restore buffer addr to print.  mov   edx,eax           ; size is returned by read syscall  stdout_write  ; Print '\n'.  lea   rsi,[crlf]  mov   edx,crlf_len  stdout_write  exit  0.error:  add   rsp,8             ; we have a saved input buffer ptr on stack.                          ; dispose of it.  lea   rsi,errmsg  mov   edx,errmsg_len  stdout_write  exit 1`
Code: [Select]
`; macros.inc; Entry: RSI = buffer ptr;        EDX = buffer size; Output: EAX = size writen or < 0 if error.; Destroys: RDI (any other?)%macro stdout_write 0  mov   eax,1     ; write syscall  mov   edi,eax   ; stdout  syscall%endmacro; Entry: RSI = buffer ptr;        EDX = buffer size; Output: EAX = size read or < 0 if error.; Destroys: RDI (any other?)%macro stdin_read 0  xor   eax,eax   ; read syscall  mov   edi,eax   ; stdin  syscall%endmacro; Entry: (none) - exitcode is taken from macro usage; Do not return to the caller.%macro exit 1  mov   eax,60  mov   edi,%1  syscall%endmacro`
If you need to deal with data read from stdin as if it is an integer, you need to convert to it (atoi). And if you need to print an integer, you need to convert it to a string (itoa?). These routines aren't supplied by syscalls, you need to code your own.

Another note: `.bss` section isn't present on the binary image. Is allocated by the program loader and it is constumary to zero it all at startup. The linker (ld) uses a script filled with some symbols that will help to do this:
Code: [Select]
`  extern __bss_start  extern _end_start:  ; Zero the entire BSS.  mov   rdi,__bss_start  mov   rcx,_end  sub   rcx,rdi  inc   rcx  xor   eax,eax  rep   stosb  ...`Call "ld --verbose" from your comamand line to see the default ld script.

[]s
Fred

#### fredericopissarra

• Full Member
• Posts: 371
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #7 on: August 24, 2022, 03:59:10 PM »

1 - If you are using a distribution in amd64 mode (x86-64), use x86-64 syscalls, not i386;
2 - read syscalls will read blocks of bytes and return its sizes (-1 in case of error);
3 - If you aren't going to write a subroutine, use well documenten macros. Your code will be smaller and with less errors;
4 - Instead of using .data section to store read-only strings, use .rodata;
5 - Keep your labels consistent.
6 - `equ` is a directive, what preceeds it is NOT a label, but a symbol.

Example:
Code: [Select]
`; test.asm;;   nasm -felf64 -o test.o test.asm;   ld -s -o test test.o;  bits  64  default rel   ; to use RIP relative effective addresses (permit ASLR).  %include "macros.inc"  section .rodataprompt:     db  "Enter value: "prompt_len  equ \$ - prompterrmsg:     db  "Error reading value from stdin."crlf:       db  `\n`crlf_len    equ \$ - crlferrmsg_len  equ \$ - errmsg  section .bssinputbuf:     resb  12inputbuf_len  equ \$ - inputbuf  section .text  global  _start  align 4_start:  ; Write prompt.  lea   rsi,[prompt]  mov   edx,prompt_len  stdout_write  ; Read data from keyboard.  lea   rsi,[inputbuf]  push  rsi               ; save buffer addr to print later  mov   edx,inputbuf_len  stdin_read  test  eax,eax           ; return < 0?  js    .error            ; yes, error!  pop   rsi               ; restore buffer addr to print.  mov   edx,eax           ; size is returned by read syscall  stdout_write  ; Print '\n'.  lea   rsi,[crlf]  mov   edx,crlf_len  stdout_write  exit  0.error:  add   rsp,8             ; we have a saved input buffer ptr on stack.                          ; dispose of it.  lea   rsi,errmsg  mov   edx,errmsg_len  stdout_write  exit 1`
Code: [Select]
`; macros.inc; Entry: RSI = buffer ptr;        EDX = buffer size; Output: EAX = size writen or < 0 if error.; Destroys: RDI (any other?)%macro stdout_write 0  mov   eax,1     ; write syscall  mov   edi,eax   ; stdout  syscall%endmacro; Entry: RSI = buffer ptr;        EDX = buffer size; Output: EAX = size read or < 0 if error.; Destroys: RDI (any other?)%macro stdin_read 0  xor   eax,eax   ; read syscall  mov   edi,eax   ; stdin  syscall%endmacro; Entry: (none) - exitcode is taken from macro usage; Do not return to the caller.%macro exit 1  mov   eax,60  mov   edi,%1  syscall%endmacro`
If you need to deal with data read from stdin as if it is an integer, you need to convert to it (atoi). And if you need to print an integer, you need to convert it to a string (itoa?). These routines aren't supplied by syscalls, you need to code your own.

Another note: `.bss` section isn't present on the binary image. Is allocated by the program loader and it is constumary to zero it all at startup. The linker (ld) uses a script filled with some symbols that will help to do this:
Code: [Select]
`  extern __bss_start  extern _end_start:  ; Zero the entire BSS.  mov   rdi,__bss_start  mov   rcx,_end  sub   rcx,rdi  inc   rcx  xor   eax,eax  rep   stosb  ...`Call "ld --verbose" from your comamand line to see the default ld script.

[]s
Fred

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: Title : difficulty with two consecutive reads
« Reply #8 on: August 24, 2022, 05:11:35 PM »
Wow! Thank you, Fred!

Best,
Frank