News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Using general registers as pointers.

Started by Zaratustra, June 20, 2014, 12:50:53 AM

Previous topic - Next topic

Zaratustra

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





hutch--

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.

qWord

Zaratustra,
please read up about x86 registers: AH represent the bits 8 to 15 of the register EAX.
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

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 and hit F8 slowly. See what happens to eax...

Zaratustra

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?

jj2007

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

RuiLoureiro

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.

qWord

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?
MREAL macros - when you need floating point arithmetic while assembling!

hutch--

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

RuiLoureiro

Quote from: qWord on June 20, 2014, 04:56:55 AM
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?
Why what ?

RuiLoureiro

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...

RuiLoureiro

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

qWord

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
MREAL macros - when you need floating point arithmetic while assembling!

RuiLoureiro

#13
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.