WinAsm Studio, The Assembly IDE - Free Downloads, Source Code
Sponsors
Articles
Programming Quick Start
32-bit Assembler is Easy
Porting Iczelion tutorials
What is FASM
Hard Drive Recovery
Wiring your own LAN
Personal menu
Welcome Guest
User:
Pass:
Register!
Resend Validation Email
 
Forum
 

Explanation of the USES MASM directive, How is this directive interpreted by the compiler ?

samael
Quote Post


Typo-lord
******

Group: Moderators
Posts: 404
Member No.: 5187
Joined: 10-June 07


Originally posted by Lahar

Can someone please explain what does the ASSUME MASM directive means?

Example Usage:
CODE
SomeFunction PROC USES EDI, ESI one:DWORD, two:DWORD
 ;Some code here
  RET
SomeFunction ENDP

Does this means that the function uses data in these registers have at the time function is called along with its parameters?

Thanks in advance,
__Lahar__

Sponsored Links
PM
Top
samael
Quote Post


Typo-lord
******

Group: Moderators
Posts: 404
Member No.: 5187
Joined: 10-June 07


The USES MASM Directive

According to the MASM Referense (MASM.hlp), installed with the MASM32 package,

QUOTE
  Syntax:   USES reglist

  Description:

     An optional keyword used with PROC. Generates code to push the
     value of registers that should be preserved (and that will be
     altered by your procedure) on the stack and pop them off when the
     procedure returns.

     The <reglist> parameter is a list of one or more registers. Separate
     multiple registers with spaces.


Lets see what that means by using it in our code and seeing the result...

Compile the following code:

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

hInstance HINSTANCE ?

.DATA

szMessage1 db "Hello World 1",0
szMessage2 db "Hello World 2",0
szCaption db "I ran out of imagination...",0

.CODE
HelloWorld:
  PUSH NULL
  CALL GetModuleHandle
  MOV hInstance, eax
  PUSH OFFSET szCaption
  PUSH OFFSET szMessage1
  CALL DisplayMessageBox1
  PUSH OFFSET szCaption
  PUSH OFFSET szMessage2
  CALL DisplayMessageBox2
  PUSH EAX
  CALL ExitProcess
  RET

DisplayMessageBox1 PROC USES EAX EDI ESI EDX EBX ECX pszMessage:LPVOID, pszCaption:LPVOID
  PUSH MB_OK
  PUSH pszCaption
  PUSH pszMessage
  PUSH NULL
  CALL MessageBox
  RET
DisplayMessageBox1 ENDP

DisplayMessageBox2 PROC pszMessage:LPVOID, pszCaption:LPVOID
  PUSH MB_OK
  PUSH pszCaption
  PUSH pszMessage
  PUSH NULL
  CALL MessageBox
  RET
DisplayMessageBox2 ENDP
END HelloWorld


As you can see, the two functions DisplayMessageBox1 and DisplayMessageBox2 are identical, except from the fact that we use the USES directive in DisplayMessageBox1. What do you expect to happen?


After compiling our executable, and disassembling it, this is the code the compiler generated (data are not included in this listing):

CODE
start           proc near
  push    NULL              ; lpModuleName
  call    GetModuleHandleA
  mov     hInstance, eax
  push    offset szCaption; "I ran out of imagination..."
  push    offset szMessage1; "Hello World 1"
  call    DisplayMessageBox1
  push    offset szCaption; "I ran out of imagination..."
  push    offset szMessage2; "Hello World 2"
  call    DisplayMessageBox2
  push    eax            ; uExitCode
  call    ExitProcess
  retn
start           endp


; --------------- S U B R O U T I N E ---------------------------------------

; Attributes: bp-based frame

; int __stdcall DisplayMessageBox1(LPCSTR lpText,LPCSTR lpCaption)
DisplayMessageBox1 proc near          ; CODE XREF: start+16p

lpText          = dword ptr  8
lpCaption       = dword ptr  0Ch

  push    ebp
  mov     ebp, esp
  push    eax
  push    edi
  push    esi
  push    edx
  push    ebx
  push    ecx
  push    MB_OK          ; uType
  push    [ebp+lpCaption]; lpCaption
  push    [ebp+lpText]  ; lpText
  push    NULL          ; hWnd
  call    MessageBoxA
  pop     ecx
  pop     ebx
  pop     edx
  pop     esi
  pop     edi
  pop     eax
  leave
  retn    8
DisplayMessageBox1 endp


; --------------- S U B R O U T I N E ---------------------------------------

; Attributes: bp-based frame

; int __stdcall DisplayMessageBox2(LPCSTR lpText,LPCSTR lpCaption)
DisplayMessageBox2 proc near          ; CODE XREF: start+25p

lpText          = dword ptr  8
lpCaption       = dword ptr  0Ch

  push    ebp
  mov     ebp, esp
  push    MB_OK          ; uType
  push    [ebp+lpCaption]; lpCaption
  push    [ebp+lpText]  ; lpText
  push    NULL          ; hWnd
  call    MessageBoxA
  leave
  retn    8
DisplayMessageBox2 endp


As you can see, the registers we have specified in the function that makes use of the USES directive, are pushed in the order in which we declared them onto the stack, then the code of the function is executed, and then, the registers are popped in the reverse order off the stack.
As a result, the original values that these registers had before entering the function, are preserved once the execution of the function finishes.

In other words, we use the USES directive in a function, in order to ensure that the value of a (some) register(s) will be preserved once the function is executed.

Attached File ( Number of downloads: 43 )
 Login or Register to download
PM
Top
2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members:

Topic Options Reply to this topicStart new topicStart Poll

 

Sponsors
Computer Science

Internet
C/C++
Hardware & PC maintenance

HiEditor

General Discussions
Suggestions/Bug Reports
WinAsm Studio

General Discussions
Suggestions/Bug Reports
WinAsm Studio FAQ
Multilingual User Interface
Add-Ins
Assembly Programming

Main
Newbies
Projects
Custom Controls
Snippets
Announcements & Rules

Announcements

General

Online Degrees - Distance Learning
The Heap
Russian
Google