The Assembly Programming Master Book
Authors: Pirogov V. Laing J.
Published year: 2004
Pages: 114-115/140
Buy this book on amazon.com >>

Passing Parameters through Registers

This section concentrates on another type of callthe fast call, or the register call. According to Table 20.1, this type of call assumes that the first three parameters will be passed in registers ( EAX, EDX , and ECX ) and that the remaining parameters will be passed through the stack, as was in case with the stdcall calling convention. At the same time, if the stack was used, the responsibility for releasing it is delegated to the called procedure. This approach has another nuance. If the fast calling convention is used, the C translator adds the @ prefix to the names , which must be taken into account in the module written in Assembly language.

Listing 20.4: Using the fast calling convention when calling a procedure

image from book
// The ADDC.CPP file
#include <windows.h>
#include <stdio.h>
// Declare the external function for adding four integers
extern "C" __fastcall ADDD(DWORD, DWORD, DWORD, DWORD);
void main()
{
 DWORD a, b, c, d;
 a=1; b=2; c=3; d=4;
 printf("%lu\n", (DWORD *)ADDD(a, b, c, d) ) ;
 ExitProcess(0);
}

; The ADD.ASM file
.586P
.MODEL FLAT, stdcall
PUBLIC @ADDD
; Flat memory model
_TEXT SEGMENT
; This procedure returns the sum of four parameters
; Parameters are passed through the registers
; The first three parameters are passed in the EAX, EDX, and ECX registers
; The fourth parameter is passed through the stack (e.g., [EPB+08H])
@ADDD PROC
        PUSH  EBP
        MOV   EBP, ESP
        ADD   EAX, ECX
        ADD   EAX, EDX
        ADD   EAX, DWORD PTR [EBP+08H]
        POP   EBP
        RET   4
@ADDD ENDP
_TEXT ENDS
END
image from book
 

To translate the modules presented in Listing 20.4, issue the following command:

tasm32 /ml add.asm

Then, include the ADD.OBJ file in the ADDC project (Borland C++ 5.0)

Application Programming Interface Calls and Resources in Assembly Modules

In this section, I demonstrate that the called procedure written in Assembly language can contain not only auxiliary procedures but also calls to application programming interface (API) functions. Furthermore, it can work with resources. Note that these resources are common for all modules of the project. It is possible to have several resource files. The only thing that you'll have to do is ensuring that the names and the identifiers match.

Listing 20.5: The console application written in C++ calls the graphic user interface-mode procedure (Listing 20.6) defined in an Assembly module

image from book
#include <windows. h>
#include <stdio.h>
// Declare the external function
extern "C"__stdcall DIAL1();
void main()
{
 DIAL1();
 ExitProcess(0);
}
image from book
 

Listing 20.6: Using resources and application program interface calls in the Assembly module

image from book
// The DIALFORC.RC file
// Definitions of constants
#define WS_SYSMENU     0x00080000L
// Window elements must be initially visible
#define WS_VISIBLE     0x10000000L
// Border around the elements
#define WS_BORDER      0x00800000L
// Elements can be sequentially activated
//by pressing the <Tab> key
#define WS_TABSTOP     0x00010000L
// Text in the edit field is
// aligned to the left side
#define ES_LEFT        0x0000L
// Style of all window elements
#define WS_CHILD       0x40000000L

// Keyboard input is disabled
#define ES_READONLY    0x0800L

#define DS_3DLOOK      0x0004L
// Dialog box definition
DIAL1 DIALOG 0, 0, 240, 100
STYLE WS_SYSMENU  DS_3DLOOK
CAPTION "An example dialog box with date and time"
FONT 8, "Arial"
{
 CONTROL "", 1, "edit", ES_LEFT  WS_CHILD
  WS_VISIBLE  WS_BORDER
  WS_TABSTOP  ES_READONLY, 100, 5, 130, 12
}


; The DIALFORC.INC file
; Constants
; This message arrives when the window is closed
WM_CLOSE        equ 10h
; This message arrives when the window is created
WM_INITDIALOG   equ 110h
; This message arrives when some event occurs to the window element
WM_COMMAND      equ 111h
; Message from the timer
WM_TIMER        equ 113h
; The message for sending some text to the window element
WM_SETTEXT      equ 0Ch
; Prototypes of external procedures
EXTERN      SendDlgItemMessageA:NEAR
EXTERN      _wsprintfA:NEAR
EXTERN      GetLocalTime:NEAR
EXTERN      ExitProcess:NEAR
EXTERN      GetModuleHandleA:NEAR
EXTERN      DialogBoxParamA:NEAR
EXTERN      EndDialog:NEAR
EXTERN      SetTimer:NEAR
EXTERN      KillTimer:NEAR
; Structures
; Message structure
MSGSTRUCT STRUC
        MSHWND      DD ?
        MSMESSAGE   DD ?

        MSWPARAM    DD ?
        MSLPARAM    DD ?
        MSTIME      DD ?
        MSPT        DD ?
MSGSTRUCT ENDS
; Date-time data structure
DAT STRUC
        year    DW ?
        month   DW ?
        dayweek DW ?
        day     DW ?
        hour    DW ?
        min     DW ?
        sec     DW ?
        msec    DW ?
DAT ENDS

; The DIALFORC.ASM file
.586P
; Flat memory model
.MODEL FLAT, stdcall
include dialforc.inc
PUBLIC DIAL1
;--------------------------------------
; Data segment
_DATA SEGMENT
        MSG      MSGSTRUCT <?>
        HINST    DD 0 ; Application descriptor
        PA       DB "DIAL1", 0
        TIM      DB "Date %u/%u/%u Time %u:%u:%u", 0
        STRCOPY  DB 50 DUP (?)
        DATA     DAT <0>
_DATA ENDS
; Code segment
_TEXT SEGMENT
DIAL1 PROC
        PUSH  EBP
        MOV   EBP, ESP
; Get the application descriptor
        PUSH  0
        CALL  GetModuleHandleA
        MOV   [HINST], EAX

; Create a dialog
        PUSH  0
        PUSH  OFFSET WNDPROC
        PUSH  0
        PUSH  OFFSET PA
        PUSH  [HINST]
        CALL  DialogBoxParamA
        CMP   EAX, -1
;---------------------------------
        POP   EBP
        RET
DIAL1 ENDP
;---------------------------------
; Window procedure
; Position of parameters in the stack
; [BP+014H]  ; LPARAM
; [BP+10H]   ; WAPARAM
; [BP+0CH]   ; MES
; [BP+8]     ; HWND
WNDPROC       PROC
        PUSH  EBP
        MOV   EBP, ESP
        PUSH  EBX
        PUSH  ESI
        PUSH  EDI
;----------------
        CMP   DWORD PTR [EBP+0CH], WM_CLOSE
        JNE   L1
; Reaction to closing a window
; Delete timer 1
        PUSH  1 ; Timer identifier
        PUSH  DWORD PTR [EBP+08H]
        CALL  KillTimer
; Delete timer 2
        PUSH  2 ; Timer identifier
        PUSH  DWORD PTR [EBP+08H]
        CALL  KillTimer
; Close the dialog
        PUSH  0
        PUSH  DWORD PTR [EBP+08H]
        CALL  EndDialog
        JMP   FINISH

L1:
        CMP   DWORD PTR [EBP+0CH], WM_INITDIALOG
        JNE   L2
; Startup initialization
; Set timer 1
        PUSH  0    ; Parameter = NULL
        PUSH  1000 ; 1-second interval
        PUSH  1    ; Timer identifier
        PUSH  DWORD PTR [EBP+08H]
        CALL  SetTimer
; Set timer 2
        PUSH  OFFSET TIMPROC ; Parameter = NULL
        PUSH  500            ; 0.5-second interval
        PUSH  2              ; Timer identifier
        PUSH  DWORD PTR [EBP+08H]
        CALL  SetTimer
        JMP   FINISH
L2:
        CMP   DWORD PTR [EBP+0CH], WM_TIMER
        JNE   FINISH
; Send the string to the window
        PUSH  OFFSET STRCOPY
        PUSH  0
        PUSH  WM_SETTEXT
        PUSH  1 ; Element identifier
        PUSH  DWORD PTR [EBP+08H]
        CALL  SendDlgItemMessageA
FINISH:
        POP   EDI
        POP   ESI
        POP   EBX
        POP   EBP
        MOV   EAX, 0
        RET   16
WNDPROC    ENDP
;-------------------------------------------
; Timer procedure
; Position of parameters in the stack
; [BP+014H]  ; LPARAM --- Time elapsed since Windows startup
; [BP+10H]   ; WAPARAM - Timer identifier
; [BP+0CH]   ; WM_TIMER
; [BP+8]     ; HWND

TIMPROC     PROC
        PUSH  EBP
        MOV   EBP, ESP
; Get the local time
        PUSH  OFFSET DATA
        CALL  GetLocalTime
; Get the string for date and time output
        MOVZX EAX, DATA.sec
        PUSH  EAX
        MOVZX EAX, DATA.min
        PUSH  EAX
        MOVZX EAX, DATA.hour
        PUSH  EAX
        MOVZX EAX, DATA.year
        PUSH  EAX
        MOVZX EAX, DATA.month
        PUSH  EAX
        MOVZX EAX, DATA.day
        PUSH  EAX
        PUSH  OFFSET TIM
        PUSH  OFFSET STRCOPY
        CALL  _wsprintfA
; Restore the stack
        ADD   ESP, 32
        POP   EBP
        RET   16
TIMPROC ENDP
_TEXT ENDS
END
image from book
 

To translate this program, proceed as follows :

  • First methodIssue the following commands:

    tasm32 /ml dialforc.asm
        brcc32 dialforc.rc
    

    Then, include the DIALFORC.OBJ and DIALFORC.RES files in the project.

  • Second methodThis method differs from the previous one in that the DIALFORC.RC file is included in the project instead of the DIALFORC.RES file. Naturally, it is necessary to remove definitions of constants from that file because all required definitions are in the C header files.

The Assembly Programming Master Book
Authors: Pirogov V. Laing J.
Published year: 2004
Pages: 114-115/140
Buy this book on amazon.com >>