News:

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

Invalid operand for OFFSET

Started by unktehi, March 05, 2009, 05:22:40 AM

Previous topic - Next topic

unktehi

Quote
          EDIT: i read your problem again. It seems that you want to pass the address where you found
                   the 0. So it should be: (note that i dont know how WriteString works !)
found:                                                     
          mov edx, ebx                          ; edx = ebx = address of string2 where we found 0
          call WriteString                        ; Write string2 begining at address EBX=EDX
          jmp exitme                             ; Then skip over 'notfound' and jump to 'exitme'
            One question to you: WriteString and crlf preserves ECX ?

No, WriteString will take what is preserved in edx and write it out to the console.  It does nothing with ecx. This 'WriteString' is why I'm trying to get the string into edx.

Why would edx and ebx need to be switched? Yes, I'm trying to pass the address of where I found the 0, place it into edx, then WriteString should take the value of what is in edx and write it to the console.

So, in this case, using 'mov dl, byte ptr [ebx]' will not put it into the register that the WriteString procedure uses.  It must be placed into edx.

In addition, when I do change this line 'mov edx, ebx' to this 'movzx edx, BYTE PTR [ebx]' the code crashes when I try to assemble.

RuiLoureiro

#16
Quote
[Q1] In addition, when I do change this line 'mov edx, ebx' to this 'movzx edx, BYTE PTR [ebx]'
the code crashes when I try to assemble.

[A1] I dont know why it crashes but i am sure you dont need and want to use
     movzx  edx, byte ptr [ebx]. Why ? Because ... read the next answers

Quote
[Q2] So, in this case, using 'mov dl, byte ptr [ebx]' will not put it into the register
     that the WriteString procedure uses.  It must be placed into edx.

[A2] Yes it must be placed into edx but edx must be an address of one string,
     i suppose an address of a null terminating string. In this case, the address
     you want is not the dword in the ebx address. Forget [ebx]

Quote
[Q3] Why would edx and ebx need to be switched? Yes, I'm trying to pass the address
     of where I found the 0, place it into edx,
     then WriteString should take the value of what is in edx
     and write it to the console.

[A3]   You need to put an address into edx because you want to use WriteString
       and WriteString expect «an address in edx» NOT «the value of what is in edx».
       Thats the problem.
       In this way, when byte ptr [ebx] = 0 then ebx is the
       address where we found that byte 0
and you want to print that string
       begining at that address and than «mov   edx, ebx»: put that address
       into edx and call WriteString.

What do you get with this code below. I hope you can explain it.
(note that i dont know how WriteString works
           i dont know how LENGTHOF works)

Quote
.data
string2 BYTE "In like a lion,"
        BYTE 0
        BYTE 50 dup('k')                 ; string to look after the 0
        BYTE 0
string3 BYTE "No 0s were found",0        ; message to show if no 0s are found

.code
main PROC            ; main procedure

mov  edx, OFFSET string2                 ; move the address of string2 into edx
call WriteString                         ; Write string to console to verify string contents
call crlf

;**********************************
mov  eax, LENGTHOF string2               ; move the length of string2 into eax
call WriteInt                            ; write out the length of value to verify it is seeing the DUP contents on end of string
call crlf

;**********************************
; if WriteString doesnt preserve ecx
; we must give it here not at the starting point
;
mov ebx, OFFSET string2                  ; mov the address of string2 into ebx
mov ecx, 66          ;LENGTHOF string2   ; mov the length of string2 into ecx - for loop
L1:
         cmp BYTE PTR [ebx], 0           ; compare the byte at address ebx with 0
         jz  found                          ; If a zero value is found go to 'found'

         inc ebx                            ; Otherwise, increment the address in ebx =
                                               ; point to the next byte
         loop L1                            ; Loop back up to L1 and repeat until ecx=0
         jmp notfound                    ; If the value of ecx gets to 0 and no 0s were found, jump to 'notfound'

found:                                                     
         mov  edx, ebx                   ; place the address where we found 0 into edx
         inc  edx                            ; begin at next address
         call WriteString                  ; Write THAT STRING to console
         jmp  exitme                      ; Then skip over 'notfound' and jump to 'exitme'

notfound:
         mov  edx, OFFSET string3        ; Place the address of string3 into edx
         call WriteString                       ; Write string3 to console

exitme:                                  ; end
   
        exit
main ENDP
;----------------
END  main
i hope it help you
Rui

MichaelW

Quote from: unktehi on March 08, 2009, 08:10:36 PM
No, WriteString will take what is preserved in edx and write it out to the console.  It does nothing with ecx. This 'WriteString' is why I'm trying to get the string into edx.

Why would edx and ebx need to be switched? Yes, I'm trying to pass the address of where I found the 0, place it into edx, then WriteString should take the value of what is in edx and write it to the console.

The problem I see with this is that when passed the address of a 0 byte WriteString will effectively see the address of an 'empty' string and display nothing. I'm assuming that the goal here is to find the address of the end of the first string, so you can append the second string to it. Here is some small, simple, and hopefully easy to understand code that finds the address of the first 0 byte in the first string.

include Irvine32.inc
.data
  str1 db "abc",10 dup(0)
  str2 db "def",0
.code
start:

    mov edx, OFFSET str1
    call WriteString
    call crlf

    mov edx, OFFSET str2
    call WriteString
    call crlf

    mov ebx, OFFSET str1
    mov eax, ebx
    call WriteInt           ; display address of str1
    call crlf

    ;-------------------------------------------------------------
    ; This code determines the address of the first 0 byte, and
    ; leaves the address in EBX. This code assumes that there will
    ; be a 0 byte, so it does not use a loop counter.
    ;-------------------------------------------------------------
  L1:
    cmp BYTE PTR [ebx], 0   ; compare byte to 0
    je  L2                  ; jump if byte is equal to 0
    inc ebx                 ; increment to next byte
    jmp L1                  ; continue

  L2:
    mov eax, ebx
    call WriteInt           ; display address of first 0 byte
    call crlf
    call ReadChar           ; wait for key press before exiting

    exit
end start


abc
def
+4206592
+4206595


Once you have the address of the first 0 byte in the first string, you can copy the second string to that address with as little as 4 instructions.

And as far as I know, all of the Irvine32 display procedures and macros preserve all registers, and the other procedures and macros preserve all registers that are not used to return a value.
eschew obfuscation

NightWare

Quote from: unktehi on March 08, 2009, 08:10:36 PM
So, in this case, using 'mov dl, byte ptr [ebx]' will not put it into the register that the WriteString procedure uses.  It must be placed into edx.

In addition, when I do change this line 'mov edx, ebx' to this 'movzx edx, BYTE PTR [ebx]' the code crashes when I try to assemble.
of course it will not work, i remember you that you have asked why the error happen with this line, not to solve the code, coz you've already found it (mov edx,ebx). belive me, if you make an error in asm you will rarely obtain the correct result at the end.

plus, just for info, writing a destination string with a source string when it's the SAME string, is totally useless.

plus2, when you post something like that, you should include the proc used... coz edx IS NOT the unique register needed, minimum you need a destination or a size... by doing this you will only obtain answers corresponding to informations YOU have provided...

unktehi

Yes, I believe the issue was that I was trying to write out a null string.  I did, however, get it to work in the larger program.  Thanks for your help and explanations.