News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Acessing a null terminated user input in masm32

Started by grubish, April 19, 2011, 10:10:10 PM

Previous topic - Next topic

grubish

Hey Everyone,
I'm new to this forum and also to assembly language. And so far I'm really enjoying it. Okay, down to business. I wanted to write a assembly program that, 'Take names in <firstname> <lastname> format and returns it as <lastname>, <firstname>'. So, I started out writing the code in 16bit and I got it working. It works perfectly fine. Now I want to port it for 32bit assemblers. Like in 16bit assembly, you find the length of the input string by
 
lea si, inputbuffer
mov cx, [si+1]
add si, 2
mov ax, si
.....


Now when I load the offset of the "inputbuffer" in ESI and try to access the first ASCII characters and try to print it, it doesn't print anything. I need to know this, because the algorithm I use to flip the "lastname" and "firstname", needs to access the "inputbuffer" every time.

I've a hunch I might be doing something wrong and I'd be glad if someone could point that out.
Cheers!

-grubish-
-grubish-

baltoro

Well, assuming this is just a simple test program,...why not post all the code ?
We have no way of knowing how you got to that point of execution (whatever conditional code you might have used).
And, as a first suggestion, I would use the complete 32-bit register value (just for clarity's sake), although what you are doing should work in 16-bit.
But, initially, accessing the first character byte at: [si+1] is incorrect.
In 32-bit mode, the correct address of the first character byte would be: [esi+0].
The first character byte resides at the array address (which is a 32-bit value).

Also, we don't know how you declared the array,...but, that's not really important
...
XOR esi, esi    ;  sets esi register to zero
XOR eax, eax    ;  sets eax register to zero
MOV esi, inputbuffer    ;  load the offset of the array
MOV eax, [esi]    ;  dereference the first DWORD of the array

This is a kind of dumb example,...but, the point is that: the first four byte values of your array are now in the eax register.
Baltoro

grubish


.386
.model flat, stdcall
option casemap: none

include \masm32\include\kernel32.inc
include \masm32\include\windows.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib

.data
msg db "Enter your name in <firstname>  <lastname> format", 13, 10, 0
newname db 80 DUP(?), 0
crlf db 13, 10, 0
input db 80
len db  4 DUP(?), 0

.code

start:

invoke StdOut, addr msg
invoke StdIn, addr newname, 80
invoke szLen, addr newname
lea esi, input
lea edi, len
mov eax, [esi]
mov [edi], eax


invoke StdOut, addr len







invoke ExitProcess, 0
end start




Well, it's the preliminary code. I'm testing out all the spheres which i might run into. Then when I start to port the code for 32bit assembler, I won't run into too many bugs that it comes a hassle for me to decipher which one's causing what.

-grubish-
-grubish-

baltoro

#3
You know, there are alot of really excellent assembly programmers here,...and, I am probably the most inept,... :bg
Also, most of the guys here start off their main function with:   
invoke GetModuleHandle, NULL
        mov hInstance,eax

I don't think it's necessary here. hInstance is declared in the data section as: hInstance   HINSTANCE  0

You've got the right idea,...except:
mov [edi], eax

The simplest possible way to proceed would be to read the character bytes into a memory variable using the mov instruction.
I rarely write console applications, so I'm unfamiliar with StdIn and StdOut,... :eek
I would declare TWO strings, (in addition to the StdIn memory location),...and write the data sequentially,...that way you can just display the strings in reverse order.
What is it that separates the <firstname> <lastname> when the user inputs whatever he inputs ?
You might have some checking of specific characters and correct format, before you proceed with the rest of the code.
Users are notorious for doing the wrong thing,...and if you don't validate the input,...your display code probably won't function as you would expect.
Baltoro

grubish


The Algorithm is pretty simple.
1) First it counts the characters in 'firstname'
2) Push it onto the stack
3) Since spaces ie. 20h, separates the 'firstname' and the 'lastname'
4) So we count the number of spaces.
5) pushes the no of spaces onto the stack
6) Now " UserInput - (firstname + spaces separating them) " = lastname; and push the number of chars onto the stack
7) Then We copy the lastname into  a long enough buffer, advance EDI and add a ',' and then copy the 'firstname'
8) Display the string


Disclaimer - I know, I haven't added checks for leading or trailing spaces or TABS or for middle names either. It's pretty simple at this point and has a O(n) algorithm, and It just has been 3/4 days  started assembly. So I'd rather not delve into such complexity. But as it stands out, I still can't print the characters from the input string.

'$' terminated are easier to handle I guess, or I'm just overwhelmed by the 32bit assemblers.
-grubish-

baltoro

You're already a better assembly programmer than I am.
Just for future reference,...you might find this helpful: Iczelion's Win32 Assembly HomePage. These are all windows tutorials, but they are excellent.
Baltoro

grubish

I just figured out what I did wrong. And I feel pretty stupid for it.
Check it out:

invoke StdIn, addr newname, 80

......
lea esi, input
lea edi, len
mov eax, [esi]
mov [edi], eax



I took the user input in 'newname' and i was trying to load BYTES from 'input'. Of course it's either loading garbage or nothing.  Now it works. Let me know if the approach I use, is any good.

-grubish-
-grubish-

dedndave

 :P

you can use the "input" and "print" macros

but, if you like to see the API level calls...

baltoro

:bg ...Saved by the Dave,... :bg
Also, I found this lengthy thread that illustrates all the cool console techniques: How can I say "You pressed Down Arrow Key" ?
...Not surprisingly, Dave is all over that one, too,... :eek

;initialization

        INVOKE  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hStdOut,eax
        INVOKE  GetStdHandle,STD_INPUT_HANDLE
        mov     hStdInp,eax
        INVOKE  SetConsoleMode,eax,
                ENABLE_LINE_INPUT or ENABLE_ECHO_INPUT or ENABLE_PROCESSED_INPUT



Because I never write console apps, I wouldn't have guessed this was the proper beginning,...but, what does it mean ?
Baltoro

grubish

Thanks you guys for your input. I plan on adding other validity checks and make the code flawless. When I'm done writing the code, I'll post it here. Could be of some use to someone or not! Either way, masm32 is fun. :bg

Yea i checked out the Windows API and wrote a I/O routine using those API calls. I get confused with the data types - HISTANCE, LPSTR etc. As it turns out, they're all DWORD. I think most of those are alias for DWORD.
-grubish-

dedndave

        INVOKE  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hStdOut,eax
        INVOKE  GetStdHandle,STD_INPUT_HANDLE
        mov     hStdInp,eax
        INVOKE  SetConsoleMode,eax,
                ENABLE_LINE_INPUT or ENABLE_ECHO_INPUT or ENABLE_PROCESSED_INPUT


well, the first 2 are rather obvious, i would hope
you need handles for console I/O so that it can be treated as a file Read/Write
of course, all this stuff applies to console mode, only

the last one sets up the console input so that...
1) characters are echoed as they are typed
2) Ctrl+C is not echoed, and is handled by the system (ENABLE_PROCESSED_INPUT)

baltoro

...Thanks, Dave,... :eek ...Your brain is an encyclopedia,...

Quote from: GRUBISH...I get confused with the data types - HISTANCE, LPSTR etc. As it turns out, they're all DWORD. I think most of those are alias for DWORD,...
...The thing that can get confusing is that the addresses are all DWORDS too,...which makes it very convenient to move almost any value into a register,...

By the way, here is the MSDN reference for: Consoles. Maybe, it'll be useful. The code examples are all in C++, but, they are fairly simple.

Baltoro

dedndave