|
The Assembly Programming Master Book Authors: Pirogov V., Laing J. Published year: 2004 Pages: 114-115/140 |
|
|
||
|
|
||
|
|
||
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
|
|
// 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
|
|
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)
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
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
|
|
#include <windows. h>
#include <stdio.h>
// Declare the external function
extern "C"__stdcall DIAL1();
void main()
{
DIAL1();
ExitProcess(0);
}
|
|
Listing 20.6: Using resources and application program interface calls in the Assembly module
|
|
// 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
|
|
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 |