The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: JayJay on December 14, 2011, 08:00:32 PM

Title: [new question] string processing
Post by: JayJay on December 14, 2011, 08:00:32 PM
Hellow,

I got a question. Could somebody explain me a little more about string processing? Because i read a lot. Bot on the forum and in books but one thing is still unclear to me and that i want to declare a byte in a proc/function so i could use it.

lets say for example

main PROC
      var1 db "test",0
      invoke  MessageBox,0,ustr$(ebx),ADDR capt,MB_OK
      ret
main ENDP


This will cause my program to crash.

I only see examples of bytes that are defined in the .data segment. But what if i don't have a fixed number of strings? That's why i want to use it in a PROC.

Title: Re: string processing
Post by: jj2007 on December 14, 2011, 08:16:19 PM
You are declaring a variable var1 that you don't use. Why?
Title: Re: string processing
Post by: JayJay on December 14, 2011, 08:18:31 PM
ow sorry.


main PROC
      var1 db "test",0
      invoke  MessageBox,0,ustr$(ebx),ADDR var1,MB_OK
      ret
main ENDP



the code needs to be like this
Title: Re: string processing
Post by: FORTRANS on December 14, 2011, 08:20:46 PM
Hi,

   The way you declared var1 will result in it being executed as
the first part of your program.  Put it in a data section or after
the return.

Steve
Title: Re: string processing
Post by: JayJay on December 14, 2011, 08:28:02 PM
Hi steve. Thank you for your reply. But i don't want to put it in the data section because then i am stuck to a fixed number of strings that i can use. Can you explain me what you mean by after the return?
Title: Re: string processing
Post by: clive on December 14, 2011, 08:34:52 PM
I don't understand why you're limited in strings, it is not like you are doing 16-bit coding?

Put the data AFTER the last RET instruction.

Or bracket it between a .DATA and .CODE within the PROC

main PROC
      invoke  MessageBox,0,ustr$(ebx),ADDR var1,MB_OK
      ret
      var1 db "test",0
main ENDP


main PROC
.DATA
      var1 db "test",0
.CODE
      invoke  MessageBox,0,ustr$(ebx),ADDR var1,MB_OK
      ret
main ENDP

Title: Re: string processing
Post by: clive on December 14, 2011, 08:52:39 PM
main  PROC
      lea edi,@F
      invoke  MessageBoxA,0,ustr$(ebx),edi,MB_OK
      ret
@@:
      db        "test",0
main  ENDP


Disassembly

00000000                    _main@0:
00000000 8D3D27000000           lea     edi,[$$000027] ; 'test',000h
00000006 6A0A                   push    0Ah
00000008 6830000000             push    offset ??0019
0000000D 53                     push    ebx
0000000E FF150000FFEF           call    dword ptr [__imp___ultoa]
00000014 83C40C                 add     esp,0Ch
00000017 6A00                   push    0
00000019 57                     push    edi
0000001A 6830000000             push    offset ??0019
0000001F 6A00                   push    0
00000021 E8DAFFFDEF             call    _MessageBoxA@16
00000026 C3                     ret

00000027                    $$000027:                   ; Xref 00000000
00000027 7465737400             db      'test',000h
Title: Re: string processing
Post by: bomz on December 14, 2011, 09:04:11 PM
Quotejmp label
test db 'my text',0
label:
invoke MessageBox,0,addr test,0,0
Title: Re: string processing
Post by: bomz on December 14, 2011, 09:08:35 PM
Under DOS code is not write protected. so

; ===============================================================
; ===============================================================
name NONAME
; ===============================================================
;   === Начало программы: ===
CSEG segment
assume cs:cseg, ds:cseg, ss:cseg, es:cseg
org  100h         ; COM файл
; ===============================================================
Start:
   jmp   init      ;на инициализацию резидента
new_16:            ;новая отработка вектора 16
   cmp   ah, 01h      ;
   jne   to_old_16   ;на старый вектор
   pushf
   call   dword ptr cs:old_16 ;на старый вектор
   jz   @F
   pushf   
   mov   cx,0001h   ;старшее слово числа микросекунд паузы
   mov   dx,0000h   ;младшее слово числа микросекунд паузы
   mov   ah,86h      ;функция 86h
   int   15h      ;пауза
   popf
@@:
   iret
to_old_16:
   db      0eah      ;Код межсегментного JMP.  jmp code
old_16   dw      0, 0      ;Адрес старого обработчика.old offset address


init:            ;инициализация программы
   mov   ax, 3516h   ;прочитаем старый вектор
   int   21h
   mov   old_16, bx   ;сохраним в переменной смещение
   mov   old_16+2, es   ;и сегмент
   mov   ax, 2516h   ;установим новый вектор отработки прерывания 16
   lea   dx, new_16   ;адрес нового обработчика
   int   21h
   lea   dx, init   ;последний адрес программы, который оставляем в памяти
   int   27h      ;оставляем резидент в памяти и завершаемся

CSEG ends
end Start
; ===============================================================
; ===============================================================
Title: Re: string processing
Post by: MichaelW on December 15, 2011, 01:39:49 AM
JayJay,

How could putting your strings in the data section limit you to a "fixed number of strings", and putting them in the code section not limit you to a fixed number of strings?

Title: Re: string processing
Post by: bomz on December 15, 2011, 01:56:17 AM
(http://s1.ipicture.ru/uploads/20111215/HVWRLILI.png)
var1 must be before place where it used

Title: Re: string processing
Post by: dedndave on December 15, 2011, 02:05:36 AM
var1    db "test",0

main    PROC
        invoke  MessageBox,0,ustr$(ebx),ADDR var1,MB_OK
        ret
main    ENDP

        END     main


:P
Title: Re: string processing
Post by: clive on December 15, 2011, 02:25:18 AM
Quote from: bomzvar1 must be before place where it used
touche, but only because the implementation of ADDR sucks, forward references aren't impossible to implement.

But in any case, the repeated use of "var1" or "label" doesn't work either.

I think we can infer from JayJay's request is that he wants to use the same generic string name over and over, so defining it with global scope probably isn't the way to go.
Title: Re: string processing
Post by: bomz on December 15, 2011, 02:36:51 AM
I make this examples that he understand what he do only
Title: Re: string processing
Post by: JayJay on December 15, 2011, 08:22:03 AM
Hi,

I solved the problem by putting it in the .data section. I thought it was not allowed to put a .data section in a proc. I thought it was only allowed at the beginning of your .asm file :lol

Thanks for the help you all!

JayJay
Title: Re: string processing
Post by: bomz on December 15, 2011, 08:34:09 AM
QuoteI thought it was not allowed to put a .data section in a proc.

(http://smiles.kolobok.us/light_skin/yes3.gif)

Sometimes I do this (put data in code section) to make prog 512 bytes smaller. If it 1.5 kb for ex, make it 1.0 kb
Title: Re: string processing
Post by: dedndave on December 15, 2011, 08:36:08 AM
i think you can forward reference if you use...
main    PROC
        invoke  MessageBox,0,ustr$(ebx),ADDR byte ptr var1,MB_OK
        ret
var1    db "test",0
main    ENDP

        END     main

or
main    PROC
        invoke  MessageBox,0,ustr$(ebx),offset byte ptr var1,MB_OK
        ret
var1    db "test",0
main    ENDP

        END     main

on the first pass, the assembler needs a type - not an address

at least, that's how we used to do it for .COM files using MASM v 5.10 and earlier
all the data was at the end of the code section
Title: Re: string processing
Post by: dedndave on December 15, 2011, 08:37:20 AM
Bomz...
you can put data in the code section, but you cannot write to it without using VirtualProtect to alter the permissions
Title: Re: string processing
Post by: bomz on December 15, 2011, 08:46:43 AM
(http://smiles.kolobok.us/light_skin/yes3.gif)

If I may do this a make prog 1 kb smaller
Title: Re: string processing
Post by: bomz on December 15, 2011, 09:12:07 AM
Quote.386

.model flat, stdcall
option casemap :none

include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\user32.inc
include \MASM32\INCLUDE\kernel32.inc
includelib \MASM32\LIB\user32.lib
includelib \MASM32\LIB\kernel32.lib

.data
mestitle   db "self-modifying code",0
form      db "EAX: %u", 0

.data?
buffer      db 512 dup(?)
OldProtect   dd ?

.code
start:
jmp DATASECTOR
var      dd 0
DATASECTOR:
;Invoke GetCurrentProcessId
;invoke  OpenProcess,PROCESS_VM_OPERATION,FALSE,eax
Invoke VirtualProtect, 4198400, 512, PAGE_READWRITE, addr OldProtect
;invoke GetLastError

mov var, 1
mov eax, var

invoke wsprintf,ADDR buffer,ADDR form,eax
invoke MessageBox,0,ADDR buffer,ADDR mestitle,MB_ICONASTERISK
invoke ExitProcess,0
end start

;PAGE_EXECUTE_READWRITE
;ERROR_NOACCESS
;998 (0x3E6)
Title: Re: string processing
Post by: dedndave on December 15, 2011, 09:16:23 AM
Invoke VirtualProtect, 4198400, 512, PAGE_READWRITE, addr OldProtect
you got what you asked for on that one   :P

Invoke VirtualProtect, offset var, 4, PAGE_EXECUTE_READWRITE, addr OldProtect

notice that - when the permission of 1 byte is changed, the entire "page" of memory changes with it
pages are, as far as i know, always 4 kb
Title: Re: string processing
Post by: bomz on December 15, 2011, 09:19:34 AM
to make write code - you need one variable - OldProtect
Title: Re: string processing
Post by: dedndave on December 15, 2011, 09:23:30 AM
create it on the stack
push eax
Invoke VirtualProtect, offset var, 4, PAGE_EXECUTE_READWRITE, esp
pop edx    ;EDX = old protection value


the problems with your original code:
1) you "hard-wired" the address
2) you did not allow EXECUTE in the code section   :P
Title: Re: string processing
Post by: bomz on December 15, 2011, 09:24:59 AM
(http://smiles.kolobok.us/light_skin/yes3.gif)


I have no any idea for self-modyfing reason
Title: Re: string processing
Post by: jj2007 on December 15, 2011, 09:40:44 AM
Complete example:
include \masm32\include\masm32rt.inc

.code
AppName db "Masm is great:", 0
start: push eax
mov edi, offset AppName
Invoke VirtualProtect, edi, 4, PAGE_EXECUTE_READWRITE, esp
mov [edi], "zmob"
Invoke VirtualProtect, edi, 4, PAGE_EXECUTE, esp
pop edx ; EDX = old protection value
MsgBox 0, str$(eax), edi, MB_OK ; show return value
mov [edi], "msaM" ; let it crash
MsgBox 0, str$(eax), edi, MB_OK ; you won't see this one
exit
end start
Title: Re: string processing
Post by: bomz on December 15, 2011, 09:53:44 AM
ERROR in the END
Quoteinclude \masm32\include\masm32rt.inc

.code
AppName db "Masm is great:", 0
start: push eax
mov edi, offset AppName
Invoke VirtualProtect, edi, 4, PAGE_EXECUTE_READWRITE, esp
mov dword ptr[edi], "zmob"
Invoke VirtualProtect, edi, 4, PAGE_EXECUTE, esp
pop edx ; EDX = old protection value
MsgBox 0, str$(eax), edi, MB_OK ; show return value
mov dword ptr[edi], "msaM" ; let it crash
MsgBox 0, str$(eax), edi, MB_OK ; you won't see this one
invoke ExitProcess,0
exit
end start
Title: Re: string processing
Post by: dedndave on December 15, 2011, 10:23:01 AM
mov dword ptr[edi], "msaM" ; let it crash <--------
Jochen put that error in there for demonstration purposes
Title: [new question]string processing
Post by: JayJay on December 15, 2011, 03:32:46 PM
Hi,

Although i said i fixed it. I actually didn't. I thought so.... Because when i define a .data section within the proc. i can't use the name of the var in another proc.

I am trying to make a small language that converts code tot asssembly.

What i am trying to achieve is that i have a string at local level. So it only exists in the procedure.

for example

void test()
{
    string str = "masm32 is fun";
}


would become but this doesn't work. :(

test PROC
   str     db "masm32 is fun",0
   ret
test ENDP



Title: Re: [new question] string processing
Post by: clive on December 16, 2011, 02:19:08 AM
You again seem to miss the point that the processor can't execute ASCII characters, you have to jump over them. With C it allocates space on the stack and copies the data there, it does not embedded it in-line as ASCII characters.

To use the same name repetitively you'll need to do it like this.

main1 PROC
        jmp @F
var1:
      db "test",0
@@:
      invoke  MessageBox,0,ustr$(ebx),ADDR var1,MB_OK
      ret
main1 ENDP

main2 PROC
        jmp @F
var1:
      db "test",0
@@:
      invoke  MessageBox,0,ustr$(ebx),ADDR var1,MB_OK
      ret
main2 ENDP
Title: Re: [new question] string processing
Post by: donkey on December 16, 2011, 02:37:06 AM
As clive said, you can't execute ascii strings, but the processor will try since all it does is consume bytes regardless of what you intended them for. So for example:

DB "Hello",0

is encoded as

048h, 065h, 06Ch, 06Ch, 06Fh, 00h

When the processor sees that byte sequence it will execute it as follows:

0040435c 48              dec     eax
0040435d 656c            ins     byte ptr es:[edi],dx
0040435f 6c              ins     byte ptr es:[edi],dx
00404360 6f              outs    dx,dword ptr [esi]
00404361 0000            add     byte ptr [eax],al


Obviously not what you wanted. So you have to jump past it or store it in an area that is not executed, normally it would be stored in either the DATA?, DATA or CONST section, however if its never going to be modified you can store it in the CODE section as you tried above. You can put it anywhere as long as it is not addressed before being declared (MASM limitation, GoAsm does not care),  however to make sure that the processor does not try to execute it you must jump over it using a JMP instruction.

Edgar
Title: Re: [new question] string processing
Post by: jj2007 on December 16, 2011, 06:08:21 AM
Quote from: donkey on December 16, 2011, 02:37:06 AMYou can put it anywhere as long as it is not addressed before being declared (MASM limitation, GoAsm does not care),  however to make sure that the processor does not try to execute it you must jump over it using a JMP instruction.

Another convenient place is just before the proc:
include \masm32\include\masm32rt.inc

.code
start: call MyTest
exit

mText db "The text", 0
mTitle db "The title", 0
MyTest proc
invoke MessageBox, 0, addr mText, addr mTitle, MB_OK
ret
MyTest endp

end start


By the way, JWasm allows forward references, too - a source of trouble if you use JWasm by default and want to remain compatible with Masm :wink
Title: Re: [new question] string processing
Post by: clive on December 16, 2011, 02:37:08 PM
But the issue to be addressed is how to keep the names local to the procedure, which MASM 6.xx only does for "foo:" references not "foo db ?" ones.

JayJay is asking for locally scoped strings, without using the stack/LOCAL, with the possibility of using the same name in multiple procedures for different data.
Title: Re: [new question] string processing
Post by: FORTRANS on December 16, 2011, 02:54:55 PM
Quote from: clive on December 16, 2011, 02:37:08 PM
But the issue to be addressed is how to keep the names local to the procedure, which MASM 6.xx only does for "foo:" references not "foo db ?" ones.

JayJay is asking for locally scoped strings, without using the stack/LOCAL, with the possibility of using the same name in multiple procedures for different data.

Hi,

   Well, if the name is local, and you want it global, you have a
problem of sorts, correct?  A possible way out is indirect addressing
with a pre-defined pointer to a string?  Like maybe;

.DATA
StringPointer   DD      ?
NullString      DB      "Null!",0
.CODE

PROC    SomeWhere

        MOV     StringPointer,OFFSET Foo

; Code that calls another procedure that wants the local string.
        CALL    Bar
; ...

; Then reset the pointer after usage.

        MOV     StringPointer,OFFSET NullString
        RET

Foo:
        DB      "This is a local string.",0

ENDP


   Seems a bit contrived though.

Regards,

Steve N.
Title: Re: [new question] string processing
Post by: jj2007 on December 16, 2011, 03:10:08 PM
Quote from: clive on December 16, 2011, 02:37:08 PM
But the issue to be addressed is how to keep the names local to the procedure, which MASM 6.xx only does for "foo:" references not "foo db ?" ones.

To complicate things further: This assembles fine...

include \masm32\include\masm32rt.inc

.code
start: call MyTest
exit

MyTest proc
jmp @F
mText:
db "The text", 0
@@:
invoke MessageBox, 0, offset mText, 0, MB_OK
ret
MyTest endp

MyTest2 proc
jmp @F
mText:
db "The text", 0
@@:
; invoke MessageBox, 0, offset mText, 0, MB_OK
ret
MyTest2 endp

end start