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-
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.
.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-
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.
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.
You're already a better assembly programmer than I am.
Just for future reference,...you might find this helpful: Iczelion's Win32 Assembly HomePage (http://www.woodmann.com/RCE-CD-SITES/Iczelion/index.html). These are all windows tutorials, but they are excellent.
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-
:P
you can use the "input" and "print" macros
but, if you like to see the API level calls...
: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" ? (http://www.masm32.com/board/index.php?topic=14570.0)
...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 ?
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.
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)
...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 (http://msdn.microsoft.com/en-us/library/ms682010(v=VS.85).aspx). Maybe, it'll be useful. The code examples are all in C++, but, they are fairly simple.
that's a good read
the subsection about console handles is particularly important
http://msdn.microsoft.com/en-us/library/ms682075%28v=VS.85%29.aspx