Author Topic: Win64: Printing characters read from console does not work  (Read 11662 times)

Offline HD1920.1

  • Jr. Member
  • *
  • Posts: 40
Win64: Printing characters read from console does not work
« on: February 05, 2014, 02:18:46 PM »
Hello, I wanted to write a simple Win64 Hello World program that should greet the user personally. Unfortunately, the program does not work properly. It does not print the read name and exits if the name entered was too long. What is my mistake?
Code: [Select]
bits 64
extern ExitProcess
extern GetStdHandle
extern WriteConsoleA
extern ReadConsoleA

STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11

section .bss
CharsWritten resq 1
CharsRead resq 1
InputBuffer resq 20
StdOut resq 1
StdIn resq 1
namelen resq 1

section .text
global main
main:
sub rsp, 0x28

mov rcx, STD_OUTPUT_HANDLE
call GetStdHandle
mov [StdOut], rax

mov rcx, STD_INPUT_HANDLE
call GetStdHandle
mov [StdIn], rax

mov rcx, [StdOut]
mov rdx, msg1
mov r8, msg1.len
mov r9, CharsWritten
mov rax, qword 0
mov qword [rsp+0x28], rax
call WriteConsoleA

mov rcx, [StdIn]
mov rdx, InputBuffer
mov r8, CTR1
mov r9, CharsRead
mov rax, qword 0
mov qword [rsp+0x28], rax
call ReadConsoleA

mov rcx, [StdOut]
mov rdx, msg2
mov r8, msg2.len
mov r9, CharsWritten
mov rax, qword 0
mov qword [rsp+0x28], rax
call WriteConsoleA

mov rax, qword [CharsRead]
sub rax, 2
mov qword [namelen], rax

mov rcx, [StdOut]
mov rdx, InputBuffer
mov r8, namelen
mov r9, CharsWritten
mov rax, qword 0
mov qword [rsp+0x28], rax
call WriteConsoleA

mov rcx, [StdOut]
mov rdx, msg3
mov r8, msg3.len
mov r9, CharsWritten
mov rax, qword 0
mov qword [rsp+0x28], rax
call WriteConsoleA

mov rcx, [StdIn]
mov rdx, InputBuffer
mov r8, CTR2
mov r9, CharsRead
mov rax, qword 0
mov qword [rsp+0x28], rax
call ReadConsoleA

add rsp, 0x28
xor rcx, rcx
call ExitProcess

section .data
msg1 db "Hello, World!", 10, "Please enter your name (maximum 20 characters): "
msg1.len equ $ - msg1
msg2 db "Hello, "
msg2.len equ $ - msg2
msg3 db "!", 10, "Please press enter to quit."
msg3.len equ $ - msg3
CTR1 equ 20
CTR2 equ 0
« Last Edit: February 05, 2014, 02:21:00 PM by HD1920.1 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Win64: Printing characters read from console does not work
« Reply #1 on: February 05, 2014, 03:31:27 PM »
I "don't do Windows" but on the optimistic assumption that "code is code",,,
Code: [Select]
; ...
mov rcx, [StdOut]
mov rdx, InputBuffer
mov r8, namelen ; <---
mov r9, CharsWritten
mov rax, qword 0
mov qword [rsp+0x28], rax
call WriteConsoleA
; ...
Unlike the other places you set the length, this one is "[contents]" of memory. What you've got there is the address of the variable "namelen". I have no idea if this is your problem (or one of them), but it doesn't look right to me.

Best,
Frank


Offline encryptor256

  • Full Member
  • **
  • Posts: 250
  • Country: lv
  • Win64 .
    • On Youtube: encryptor256
Re: Win64: Printing characters read from console does not work
« Reply #2 on: February 05, 2014, 05:23:36 PM »

Fifth argument.

Wrong:
Code: [Select]
; ...
        sub rsp, 0x28
; ...
mov rax, qword 0
mov qword [rsp+0x28], rax
call WriteConsoleA
; ...

Where goes fifth argument of WriteConsoleA?
rsp+0x28 ?
No!

Allocated stack space, arguments:
RCX is at [RSP+0x00]
RDX is at [RSP+0x08]
R8 is at [RSP+0x10]
R9 is at [RSP+0x18]
Fifth argument, before call is made, goes into [RSP+0x20]

Should be like this:
Code: [Select]
; ...
mov rax, qword 0
mov qword [rsp+0x20], rax
call WriteConsoleA
; ...


Stack deallocation.

- Rules are still the same, why, deallocate stack for a call?

Wrong:
Code: [Select]
        add rsp, 0x28
xor rcx, rcx
call ExitProcess

Right:
Code: [Select]
xor rcx, rcx
call ExitProcess
        add rsp, 0x28

Perfect:
Code: [Select]
xor rcx, rcx
call ExitProcess
        add rsp, 0x28
        ret


Encryptor256's Investigation \ Research Department.

Offline HD1920.1

  • Jr. Member
  • *
  • Posts: 40
Re: Win64: Printing characters read from console does not work
« Reply #3 on: February 06, 2014, 01:21:43 PM »
Thank you, Frank Kotler, the program does work now! I forgot that variables defined by equ are directly moved into the register. But the program still exits when I enter a name that is longer than 17 characters. How to prevent this?
@encryptor256: Thank you that the program ist correct now. I thought the program does not do anything after ExitProcess, so I thought you have to deallocate the stack space before.
« Last Edit: February 06, 2014, 02:47:54 PM by HD1920.1 »