Author Topic: How to display on screen string of unicode-characters from console application?  (Read 417 times)

Mikl__

  • Member
  • ****
  • Posts: 542
Please tell me how to display a string of hieroglyphs (unicode characters) from the console application?
I can not understand where I'm wrong?
Code: [Select]
include win64a.inc
BLACK equ 0
BLUE equ 1
GREEN equ 2
CYAN equ 3
RED equ 4
PURPLE equ 5
YELLOW equ 6
SYSTEM equ 7
GREY equ 8
BRIGHTBLUE equ 9
BRIGHTGREEN equ 10
BRIGHTCYAN equ 11
BRIGHTRED equ 12
BRIGHTPURPLE equ 13
BRIGHTYELLOW equ 14
WHITE equ 15
MAXSCREENX = 80
MAXSCREENY = 25
buffersize = 200
SMALL_RECT STRUCT
   Left      WORD      ?
   Top       WORD      ?
   Right     WORD      ?
   Bottom    WORD      ?
SMALL_RECT ENDS
.code
WinMain proc
local LENS:qword
local hOut:qword
local BUFF[buffersize]:byte
local ConsoleWindow:SMALL_RECT
        push rbp
mov ebp,esp
sub esp,(28h+2*8+buffersize+sizeof SMALL_RECT+15)and(-16)

        call FreeConsole;release the existing console
        call AllocConsole;form the console
mov rcx,CP_UTF8
        call SetConsoleOutputCP
        mov ecx,STD_OUTPUT_HANDLE
        call GetStdHandle;receive the handle for a conclusion
        mov hOut,rax
        mov rcx,rax ; hConsoleOutput
call GetLargestConsoleWindowSize
; rax return in 31-16 bits: dwCoord.y
;               15-00 bits: dwCoord.x

        lea r8d,ConsoleWindow
mov [r8+SMALL_RECT.Left],0
mov [r8+SMALL_RECT.Top],0

sub ax, MAXSCREENX
sbb edx, edx
and ax, dx
add ax, MAXSCREENX-1
mov [r8+SMALL_RECT.Right],ax

shr eax, 16
sub eax, MAXSCREENY
sbb edx, edx
and eax, edx
add eax, MAXSCREENY-1
mov [r8+SMALL_RECT.Bottom],ax

mov edx,TRUE ; bAbsolute
mov rcx,hOut ; hConsoleOutput
call SetConsoleWindowInfo

mov edx,MAXSCREENY*10000h+MAXSCREENX;dwCoord
mov rcx,hOut ; hConsoleOutput
call SetConsoleScreenBufferSize;establish the new size of a window of the console
mov ecx,offset STR2
call SetConsoleTitle;definition of a title bar
        mov edx,0A0000h;Y=10(0Ah)X=0
        mov rcx,hOut
        call SetConsoleCursorPosition;establish a cursor position
        mov edx,BRIGHTGREEN;color of the output text
        mov rcx,hOut
        call SetConsoleTextAttribute;set color attributes of the output text
        mov qword ptr [rsp+20h],0
lea r9d,BUFF
        mov r8d,sizeof STR1
mov edx,offset STR1
mov rcx,hOut
        call WriteConsoleW;display a line of symbols
        mov edx,STD_INPUT_HANDLE
        mov ecx,3000;small delay
call Sleep
        call FreeConsole;close the console
xor ecx,ecx
        call ExitProcess
WinMain endp
STR1 dw 'H','e','l','l','o',0
STR2 db 'Console',0
end

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
include \Masm32\MasmBasic\Res\JBasic.inc        ; part of MasmBasic
txOut           dw "Привет мир", 0
txFormat        dw "%s", 13, 10, 0
Init            ; OPT_64 1      ; put 0 for 32 bit, 1 for 64 bit assembly
  PrintLine Chr$("This code was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format")
  jinvoke wprintf, addr txFormat, addr txOut
EndOfCode


Output:
This code was assembled with HJWasm32 in 64-bit format
Привет мир

It should work immediately when launched from RichMasm; when starting it from a DOS prompt, use chcp 65001 before.

nidud

  • Member
  • *****
  • Posts: 1371
    • https://github.com/nidud/asmc
To start a Unicode  console applications and set up the console handle:
Code: [Select]
include conio.inc

    .data
    _confh intptr_t -2

    .code

__initconout proc

    CreateFileW(L"CONOUT$",
GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
    )
    mov _confh,rax
    ret

__initconout endp

__termconout proc

    .if _confh != -1 && _confh != -2

CloseHandle(_confh)
    .endif
    ret

__termconout endp

END

Print a Unicode char:
Code: [Select]
include conio.inc
include wchar.inc

.code

_putwch proc wc:UINT

;_mlock(_CONIO_LOCK)

_putwch_nolock(ecx)

;_munlock(_CONIO_LOCK)

ret

_putwch endp

_putwch_nolock proc wc:UINT

    local cchWritten:DWORD

    mov rax,-2
    .if _confh == rax
__initconout()
    .endif

    mov rax,-1
    .if _confh == rax
mov eax,WEOF
    .else
;
; write character to console file handle
;
.if WriteConsoleW(_confh, &wc, 1, &cchWritten, NULL)
    mov eax,wc
.else
    mov eax,WEOF
.endif
    .endif
    ret

_putwch_nolock endp

END

Print a Unicode string to the console:
Code: [Select]
include conio.inc
include wchar.inc

    .code

    option win64:2

_cputws proc uses rsi string:LPWSTR

    .for rsi=rcx :: rsi+=2
        movzx eax,WORD PTR [rsi]
        .break .if !eax
        .break .if _putwch_nolock(eax) == WEOF
    .endf
    ret

_cputws endp

    end

Print a formatted Unicode string to the console:
Code: [Select]
include string.inc
include stdio.inc

.code

wmain proc argc:SINT, argv:ptr

    mov edi,ecx ; argc
    mov rsi,rdx ; argv

    .while edi
lodsq
wprintf( "%s\n", rax )
dec edi
    .endw

    xor eax,eax
    ret

wmain endp

    end

Mikl__

  • Member
  • ****
  • Posts: 542
jj2007, nidud,
thank you very much!

aw27

  • Member
  • ****
  • Posts: 709
This is close to what you were trying to do and will allow you to see exactly were you were wrong.

I used UASM instead of MASM because 64-bit MASM really sucks.

Code: [Select]
option casemap:none

CP_UTF8 equ 65001

STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
TRUE equ 1
FALSE equ 0
BLACK equ 0
BLUE equ 1
GREEN equ 2
CYAN equ 3
RED equ 4
PURPLE equ 5
YELLOW equ 6
SYSTEM equ 7
GREY equ 8
BRIGHTBLUE equ 9
BRIGHTGREEN equ 10
BRIGHTCYAN equ 11
BRIGHTRED equ 12
BRIGHTPURPLE equ 13
BRIGHTYELLOW equ 14
WHITE equ 15
MAXSCREENX = 80
MAXSCREENY = 25
buffersize = 200
SMALL_RECT STRUCT
   Left      WORD      ?
   Top       WORD      ?
   Right     WORD      ?
   Bottom    WORD      ?
SMALL_RECT ENDS

includelib \masm32\lib64\kernel32.lib

HANDLE TYPEDEF PTR
MultiByteToWideChar PROTO :DWORD,:DWORD,:ptr,:DWORD,:ptr,:DWORD
WriteConsoleW  proto :HANDLE, :ptr, :dword, :dword, :ptr
GetStdHandle  proto :dword
FreeConsole proto
AllocConsole proto
SetConsoleOutputCP proto :dword
GetLargestConsoleWindowSize proto : HANDLE
SetConsoleWindowInfo proto :HANDLE, :dword, :ptr
SetConsoleScreenBufferSize proto :HANDLE, :dword
SetConsoleTitleA  proto :ptr
SetConsoleCursorPosition proto :HANDLE, : dword
SetConsoleTextAttribute proto : HANDLE, :word
ExitProcess   proto  :dword

includelib \masm32\lib64\msvcrt.lib
getchar proto

.data

STR1 db "Some Russian: Прощай"
STR2 db 'Console',0


.code

main Proc

local hOut:qword
local BUFF[buffersize]:byte
local charsWritten : dword
local len : dword
local ConsoleWindow:SMALL_RECT

INVOKE FreeConsole;release the existing console
INVOKE AllocConsole;form the console
        INVOKE SetConsoleOutputCP, CP_UTF8
invoke MultiByteToWideChar, CP_UTF8, 0, addr STR1, lengthof STR1, addr BUFF, 128
mov len, eax

INVOKE GetStdHandle, STD_OUTPUT_HANDLE
        mov hOut,rax

INVOKE GetLargestConsoleWindowSize, hOut

mov ConsoleWindow.Left,0
mov ConsoleWindow.Top,0

sub ax, MAXSCREENX
sbb edx, edx
and ax, dx
add ax, MAXSCREENX-1
mov ConsoleWindow.Right,ax

shr eax, 16
sub eax, MAXSCREENY
sbb edx, edx
and eax, edx
add eax, MAXSCREENY-1
mov ConsoleWindow.Bottom,ax

INVOKE SetConsoleWindowInfo, hOut, TRUE, addr ConsoleWindow
INVOKE SetConsoleScreenBufferSize, hOut, MAXSCREENY*10000h+MAXSCREENX

INVOKE SetConsoleTitleA, addr STR2
INVOKE SetConsoleCursorPosition, hOut, 0A0000h
INVOKE SetConsoleTextAttribute, hOut, BRIGHTGREEN

INVOKE WriteConsoleW, hOut, addr BUFF, len, addr charsWritten, 0

INVOKE getchar
INVOKE FreeConsole
INVOKE ExitProcess, 0
main endp

end

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
This is close to what you were trying to do

Your setup seems somehow different from mine: Error A2091: Language type must be specified

nidud

  • Member
  • *****
  • Posts: 1371
    • https://github.com/nidud/asmc
Please tell me how to display a string of hieroglyphs (unicode characters) from the console application?

Here's the Unicode table for Egyptian Hieroglyphs: http://www.unicode.org/charts/PDF/U13000.pdf

Unicode range 0x13000 to 0x130DF.

aw27

  • Member
  • ****
  • Posts: 709
This is close to what you were trying to do

Your setup seems somehow different from mine: Error A2091: Language type must be specified
I have no idea. The source was saved in UTF8 with BOM. I can't check now if saving without BOM will make a difference.

felipe

  • Member
  • ***
  • Posts: 282
  • I love assembly language programming.
Wow! 64 bit in the campus, we are making progress!.... :lol:
Felipe.

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic

aw27

  • Member
  • ****
  • Posts: 709
Your setup seems somehow different from mine: Error A2091: Language type must be specified
You must assemble for 64-bit: uasm64 -c -win64 -Zp8 test.asm  ;)

Mikl__

  • Member
  • ****
  • Posts: 542
Hi, aw27!
UASM what is it? This assembler has a website?
UASM Assembler Development? Interesting, never was on this thread...

aw27

  • Member
  • ****
  • Posts: 709
This is a variation that deals directly with UTF16.



Code: [Select]
;uasm64 -c -win64 -Zp8 test.asm
;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\link" /ENTRY:main /SUBSYSTEM:console test.obj

option casemap:none
option WIN64:2

STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
TRUE equ 1
FALSE equ 0
BLACK equ 0
BLUE equ 1
GREEN equ 2
CYAN equ 3
RED equ 4
PURPLE equ 5
YELLOW equ 6
SYSTEM equ 7
GREY equ 8
BRIGHTBLUE equ 9
BRIGHTGREEN equ 10
BRIGHTCYAN equ 11
BRIGHTRED equ 12
BRIGHTPURPLE equ 13
BRIGHTYELLOW equ 14
WHITE equ 15
MAXSCREENX = 80
MAXSCREENY = 25
buffersize = 200
SMALL_RECT STRUCT
   Left      WORD      ?
   Top       WORD      ?
   Right     WORD      ?
   Bottom    WORD      ?
SMALL_RECT ENDS

COORD STRUCT
X  WORD ?
Y  WORD ?
COORD ends

CONSOLE_FONT_INFOEX struct
cbSize dword 0
nFont dword 0
dwFontSize COORD <?>
FontFamily dword 0
FontWeight dword 0
FaceName word 32 dup (0)
CONSOLE_FONT_INFOEX ends


includelib "C:\WinDDK\7600.16385.1\lib\win7\amd64\kernel32.lib" ; SetCurrentConsoleFontEx not available in MASM32 Lib

HANDLE TYPEDEF PTR
MultiByteToWideChar PROTO :DWORD,:DWORD,:ptr,:DWORD,:ptr,:DWORD
WideCharToMultiByte proto : dword, :dword, :ptr, :dword, :ptr, :dword, :ptr, :dword
WriteConsoleA proto :HANDLE, :ptr, :dword, :dword, :ptr
WriteConsoleW  proto :HANDLE, :ptr, :dword, :dword, :ptr
GetStdHandle  proto :dword
FreeConsole proto
AllocConsole proto
SetConsoleOutputCP proto :dword
GetLargestConsoleWindowSize proto : HANDLE
SetConsoleWindowInfo proto :HANDLE, :dword, :ptr
SetConsoleScreenBufferSize proto :HANDLE, :dword
SetConsoleTitleA  proto :ptr
SetConsoleCursorPosition proto :HANDLE, : dword
SetConsoleTextAttribute proto : HANDLE, :word
Sleep proto : dword
ExitProcess   proto  :dword
SetCurrentConsoleFontEx proto :HANDLE, :dword, :ptr

includelib \masm32\lib64\msvcrt.lib
wcscpy proto :ptr, :ptr
getchar proto

.data

STR1 dw 'Unicode Fun: ',266Ah,266Bh,20h,41Fh,440h,43Eh,449h,430h,439h,20h,263Ah,0Dh,0Ah
STR2 db 'Console',0
STR3 dw 'More Unicode Fun: ', 2776h, 2777h, 2778h, 2779h, 277Ah, 277Bh, 277Ch, 277Dh, 277Eh, 277Fh
fontname1 dw "Lucida Console",0 ; does not support all characters used
fontname2 dw "Consolas",0 ; We will use this one


.code

main Proc

local hOut:qword
local charsWritten : dword
local ConsoleWindow:SMALL_RECT
local myFont : CONSOLE_FONT_INFOEX

INVOKE FreeConsole;release the existing console
INVOKE AllocConsole;form the console

INVOKE GetStdHandle, STD_OUTPUT_HANDLE
        mov hOut,rax

INVOKE GetLargestConsoleWindowSize, hOut

mov ConsoleWindow.Left,0
mov ConsoleWindow.Top,0

sub ax, MAXSCREENX
sbb edx, edx
and ax, dx
add ax, MAXSCREENX-1
mov ConsoleWindow.Right,ax

shr eax, 16
sub eax, MAXSCREENY
sbb edx, edx
and eax, edx
add eax, MAXSCREENY-1
mov ConsoleWindow.Bottom,ax

INVOKE SetConsoleWindowInfo, hOut, TRUE, addr ConsoleWindow
INVOKE SetConsoleScreenBufferSize, hOut, MAXSCREENY*10000h+MAXSCREENX

INVOKE SetConsoleTitleA, addr STR2
INVOKE SetConsoleCursorPosition, hOut, 0A0000h
INVOKE SetConsoleTextAttribute, hOut, BRIGHTGREEN

mov myFont.cbSize, sizeof CONSOLE_FONT_INFOEX
mov myFont.nFont, 0
mov myFont.dwFontSize.X, 0h
mov myFont.dwFontSize.Y, 72
mov myFont.FontFamily, 0
mov myFont.FontWeight, 400
invoke wcscpy, addr myFont.FaceName, addr fontname2 ; We will use Consolas because will support all UTF16 characters used
invoke SetCurrentConsoleFontEx, hOut, FALSE, addr myFont
.if eax==0
ret
.endif
INVOKE WriteConsoleW, hOut, addr STR1, lengthof STR1, addr charsWritten, 0

INVOKE WriteConsoleW, hOut, addr STR3, lengthof STR3, addr charsWritten, 0

INVOKE getchar
INVOKE FreeConsole
INVOKE ExitProcess, 0
main endp

end

.



« Last Edit: July 17, 2017, 01:01:49 AM by aw27 »

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
POLINK: fatal error: File not found: 'C:\WinDDK\7600.16385.1\lib\win7\amd64\kernel32.lib'

Can you post it, or is it too big?

aw27

  • Member
  • ****
  • Posts: 709
POLINK: fatal error: File not found: 'C:\WinDDK\7600.16385.1\lib\win7\amd64\kernel32.lib'

Can you post it, or is it too big?
You can use any other DDK or SDK after windows XP.
Or you can install this one while Microsoft does not make it disappear from:  :icon_rolleyes:
https://www.microsoft.com/en-us/download/details.aspx?id=11800