Jump to content
Tuts 4 You

How to define local string in MASM?


alaphate

Recommended Posts

Just like C

function MyProc()

{

char szTemp[] = "Hello World!"

}

In MASM:

MyProc PROC

local szTemp:byte

MyProc ENDP

The problem is how to transfer "Hello World!" to szTemp, WITHOUT defining global variable in .DATA segment.

I figured out one way, but it will not be the best way.

MyProc PROC

local szTemp[128]:byte

mov al, 48h ;ASCII of 'H'

mov szTemp, al

mov al,65h ;ASCII of 'e'

mov szTemp+1, al

;etc...

MyProc ENDP

Could any buddy suggest me better solutions?

Thanks in advance.

Edited by alaphate
Link to comment
myproc proc local sztemp[128]:byte;---method 1----
fn lstrcpy,addr sztemp,"hello world" ;helloworld will be copied from .data section to sztemp;---method 2---
jmp @F
hello_world db "hello world",0 ;string is in .code section here
@@:
fn lstrcpy,addr sztemp,addr hello_world
;---method 3---
mov sztemp[0],"h" ;chars are stored as constant in .code section , same as method 2, but stupid
mov sztemp[1],"e"
mov sztemp[2],"l"
;---method 4 (without api function)---
lea edi,sztemp
mov esi,offset hello_world
mov ecx,sizeof hello_world
rep movsb
...
ret
myproc endp
Edited by diablo2oo2
Link to comment
;---method 2---

jmp @F

hello_world db "hello world",0 ;string is in .code section here

@@:

fn lstrcpy,addr sztemp,addr hello_world

If the intention is to hide the string in a procedure then this one is not too good, it will be seen as hard coded text in a dissembly.

MACH4

Link to comment

diablo2oo2,

Thank you for reply.

Using method 1, I got compiling error:

error A2084: struction or register not accepted in current CPU mode

.386
.model flat, stdcall
include user32.inc
include kernel32.inc.data
szCaption db "WIN32 ASM",0.code
main proc
local szTemp[128]:byte
invoke lstrcpy, addr szTemp, "Hello World!"
invoke MessageBoxA, 0, ADDR szTemp, ADDR szCaption, 0
invoke ExitProcess, 0
main endp
end main

In Method 4, Need I add:

move ax,ds

mov es,ds

;before

lea edi,szTemp

because the dest String address should be ES:EDI

I'm not sure whether ES is same to DS or not in FLAT model.

Edited by alaphate
Link to comment
diablo2oo2,

Thank you for reply.

Using method 1, I got compiling error:

error A2084: struction or register not accepted in current CPU mode

.386
.model flat, stdcall
include user32.inc
include kernel32.inc.data
szCaption db "WIN32 ASM",0.code
main proc
local szTemp[128]:byte
invoke lstrcpy, addr szTemp, "Hello World!"
invoke MessageBoxA, 0, ADDR szTemp, ADDR szCaption, 0
invoke ExitProcess, 0
main endp
end main

use latest MASM version. MASM is so powerfull because of its macros. use them! one of this macros is the "fn"macro. Use the "fn" command instead "invoke". the "fn" instruction will allow you to use strings like in c. so you don not need to put them to .data section! there is also a macro called "fnc", its used for c-style escape characters like "hello\nworld". \n is nextline. see masm helpfiles for more information.

Also you don't need to add an "A" to apinames.masm uses ansi api functions by default. but if you want to use the unicodeformat you must add an "W" to the name.

here is my file:

.586p
.mmx
.model flat, stdcall
option casemap :noneinclude \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\macros\macros.asmincludelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib.data.code
main proc
local szTemp[128]:byte fn lstrcpy, addr szTemp, "Hello World!"
fn MessageBox, 0, addr szTemp, "WIN32 ASM", MB_ICONINFORMATION fn ExitProcess, 0
main endpend main
Edited by diablo2oo2
Link to comment

diablo2oo2,

The fnc macro is so useful, thank you.

Here's another question.

In Method 4, Need I add:

move ax,ds

mov es,ax

;before

lea edi,szTemp

because the dest String address should be ES:EDI

I'm not sure whether ES is same to DS or not in FLAT model.

Edited by alaphate
Link to comment
diablo2oo2,

The fnc macro is so useful, thank you.

Here's another question.

In Method 4, Need I add:

move ax,ds

mov es,ax

;before

lea edi,szTemp

because the dest String address should be ES:EDI

I'm not sure whether ES is same to DS or not in FLAT model.

i dont understand this "old" assembler stuff with "ds,es,int..." i code only win32 assembly with highlevel language syntax (.if .else..). and it's ok, its all i need.

Link to comment

I used debug to check the register's value.

DS == ES

You are right, no need transfer DS to ES.

Thank you for your 4 methods. I learned a lot. Thx!

Edited by alaphate
Link to comment
use latest MASM version. MASM is so powerfull because of its macros. use them! one of this macros is the "fn"macro. Use the "fn" command instead "invoke". the "fn" instruction will allow you to use strings like in c. so you don not need to put them to .data section! there is also a macro called "fnc", its used for c-style escape characters like "hello\nworld". \n is nextline. see masm helpfiles for more information.

@diablo2oo2

I think this was one of the coolest things they did with MASM adding the fn macro. fnc is good as well ive used it for new lines\n. :)

Nice methods.

Link to comment
  • 1 month later...

Similiar to method 2, but a bit more difficult to step with Olly;

To figure out why this MACRO works you must know how the CALL instruction works. CALLs changes EIP to new destination address and pushes return EIP after the CALL instruction into ESP. So this MACRO pushes the return instruction (i.e. OFFSET "string") into ESP. If you try to step through the code, you will cease execution at the szCALL "string" or "00401004 . E8 07000000 CALL gamespy.00401010".

	szCALL MACRO sz
CALL @F
BYTE sz, NULL
@@:
ENDM
.CODE
start: push 0
push 0
szCALL "string"
push 0
call MessageBox
ret
end start
00401000 > $ 6A 00		  PUSH 0
00401002 . 6A 00 PUSH 0
00401004 . E8 07000000 CALL gamespy.00401010 ; stepping fails here
00401009 . 73 74 JNB SHORT gamespy.0040107F
0040100B . 72 69 JB SHORT gamespy.00401076
0040100D . 6E OUTS DX,BYTE PTR ES:[EDI]
0040100E 67 DB 67
0040100F 00 DB 00
00401010 . 6A 00 PUSH 0
00401012 . E8 01000000 CALL <JMP.&user32.MessageBoxA>
00401017 . C3 RETN
00401018 $-FF25 00204000 JMP DWORD PTR DS:[<&user32.MessageBoxA>]; user32.MessageBoxA

Similiar to method 3, but a bit more non-sequitor;

OPTION PROLOGUE:NONE		
OPTION EPILOGUE:NONE StackSZ PROTO
push ebp
mov ebp, esp
sub esp, 4
mov dword ptr [ebp-4], "321"; MOV DWORD PTR SS:[EBP-4],796548
mov eax, ebp
sub eax, 4
INVOKE MessageBox, 0, eax, 0, 0; eax = "123", NULL
add esp, 4
leave
ret
StackSZ ENDPOPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
Link to comment

Pretty cool info. That damn "fn" macro is what I've been looking for all along - I always had stupid errors with INVOKE regarding PERFECTLY written params for some APIs or functions. FN helps a lot! Good show everyone!

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...