I did a little code that inputs a string and get its length.
The code is as follows:
include \masm32\include\masm32rt.inc
;.386
;.model flat
;.stack 100h
.data
lgth sdword 0
.code
_main proc
mov edi,input("Input your string:")
wh01:mov ah,[edi]
cmp ah,0
je ew01
inc lgth
inc edi
jmp wh01
ew01:nop
print "Length:",0
print sstr$(lgth),0
print " ",0ah,0
inkey "Ending program..."
ret
_main endp
end _main
It works, but when I use, for example, eax as pointer, it does not work, the length always gives me 1. Why is that?
include \masm32\include\masm32rt.inc
;.386
;.model flat
;.stack 100h
.data
lgth sdword 0
.code
_main proc
mov edi,input("Input your string:")
mov eax,edi
wh01:mov ah,[eax]
cmp ah,0
je ew01
inc lgth
inc eax
jmp wh01
ew01:nop
print "Length:",0
print sstr$(lgth),0
print " ",0ah,0
inkey "Ending program..."
ret
_main endp
end _main
You ned to learn your register preservation convention then use a register that is not over written by another procedure. EAX is being used in the "input" and "print" macros so you cannot use it as the calculated value you are after.
Just try this,
push esi BEFORE the INPUT statement.
Copy EAX into ESI
Perform the print operation with ESI then when you have finished use,
pop esi.
ESI is not overwritten by normal macros or procedures.
Zaratustra,
please read up about x86 registers: AH represent the bits 8 to 15 of the register EAX.
eax = xx xx ah al (as qWord already wrote)
Your string pointer is in edi, so get it from there. mov ah,[eax] makes absolutely no sense because you destroy the ah part of eax in the first round.
wh01:mov ah,[edi]
cmp ah,0
je ew01
inc lgth
inc edi
jmp wh01
ew01:nop
print "Length:"
print sstr$(lgth)
One last advice: Open the exe file in Olly (http://www.ollydbg.de/version2.html) and hit F8 slowly. See what happens to eax...
Thanx for all your answers. Yes I know that AH belongs to EAX, but for some dump reason, I forgot about that.
I change the register for EDX for example, and it works.
I have just one more question, What if I wanted to use a variable as pointer? I It is possible?
Quote from: Zaratustra on June 20, 2014, 02:10:08 AMWhat if I wanted to use a variable as pointer? I It is possible?
No. To check the value of a memory location, you need a register. Compilers do the same, under the hood. Here is a slightly modified version of your program.
include \masm32\include\masm32rt.inc
.data?
lgth sdword ? ; create variable in the uninitialised data section (doesn't bloat your exe)
.code
_main proc
mov edi, input("Input your string:")
or lgth, -1 ; set all bits - same as mov lgth, -1 but shorter
dec edi ; compensate the inc edi before the comparison
wh01:
inc lgth ; in round 1, it will be -1+1=0
inc edi ; in round 1, it will be on start of string
cmp byte ptr [edi], 0
jne wh01
print "Length: "
print sstr$(lgth), 13, 10
inkey "Ending program..."
invoke ExitProcess, 0 ; ret is not a legal way to end a program
_main endp
end _main
Quote from: Zaratustra on June 20, 2014, 02:10:08 AM
...
I change the register for EDX for example, and it works.
...
Hummmm, but not for much more time !
You are a lucky man.
You should use EBX or ESI or EDI.
Quote from: RuiLoureiro on June 20, 2014, 03:55:28 AM
Quote from: Zaratustra on June 20, 2014, 02:10:08 AM
...
I change the register for EDX for example, and it works.
...
Hummmm, but not for much more time !
You are a lucky man.
Why?
On a simple test piece you can get awy with not preserving the critical registers as it exits without calling the operating system but apart from the simplest case, you MUST conform to the normal register convention OR you will keep getting the same problem of overwriting registers.
Try this in your procedures.
push ebx
push esi
push edi
; write any code here where you can use a register that does not overwrite EAX ECX or EDX
pop edi
pop esi
pop ebx
This way you preserve the important registers AND you can then use them for tasks that call other procedures that can also modify EAX ECX and EDX.
What is important to understand is the operating system is written with these assumptions of register preservation and if you don't do the same, your code will be very unreliable.
Also keep in mind that you don't have to use a register to hold a pointer, you can use a normal memory operand.
LOCAL pMem :DWORD
; as a macro call
mov pMem, [memory allocation function] ; returns in EAX like normal.
; as a normal API function call in MASM
invoke memory_allocation_function,args etc ....
mov pMem, eax
It works, but when I use, for example, eax
as pointer,
it does not work, the length always gives me 1.
Why is that?
Quote
include \masm32\include\masm32rt.inc
;.386
;.model flat
;.stack 100h
.data
lgth sdword 0
.code
_main proc
mov eax,input("Input your string:")
wh01:mov dh,[eax] ; if the pointer is in EAX
cmp dh,0 ; we MUST use another register
je ew01 ; to get each BYTE !!!
inc lgth
inc eax
jmp wh01
ew01:nop
print "Length:",0
print sstr$(lgth),0
print " ",0ah,0
inkey "Ending program..."
ret
_main endp
end _main
;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
Input your string:this work of course
Length:19
Ending program...
Try this:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
;---------------------------------------------------------------------
; To print a string at iLin, kCol
;
printstring MACRO iLin, kCol, pStr
invoke locate, kCol, iLin
invoke StdOut, pStr
ENDM
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
ThisString db "This work", 0
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.code
start:
cls
;----------------------------------------
; set the pointer into EDX
;----------------------------------------
mov edx, offset ThisString
;----------------------------------------
; now, we use the printstring macro
;----------------------------------------
printstring 4, 20, edx
;----------------------------------------
; HERE
; the pointer of ThisString is not at EDX
;----------------------------------------
inkey " ********** END 1 ********** "
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;----------------------------------------
; set the pointer into EBX
;----------------------------------------
mov ebx, offset ThisString
;----------------------------------------
; now, we use the printstring macro
;----------------------------------------
printstring 4, 20, ebx
;---------------------------------------------
; call API's or MACROS here
;---------------------------------------------
;--------------------------------------------
; HERE
; the pointer of ThisString is at EBX
;--------------------------------------------
inkey " ********** END 2 ********** "
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Quote from: RuiLoureiro on June 21, 2014, 02:47:05 AM
It works, but when I use, for example, eax as pointer,
it does not work, the length always gives me 1.
And that is the reason why he use EDX as pointer - that has nothing to do with luck :t
Quote from: qWord on June 21, 2014, 04:17:34 AM
Quote from: RuiLoureiro on June 21, 2014, 02:47:05 AM
It works, but when I use, for example, eax as pointer,
it does not work, the length always gives me 1.
And that is the reason why he use EDX as pointer - that has nothing to do with luck :t
But i used "luck" and it has nothing to do with that
particular case :t
I didnt read his first post or his example.