Combined Using C and Assembly Code

Here, I present an example of the simplest calculator. For Assembly language, it might be difficult to find libraries with specific procedures. Naturally, you can write everything on your own, but this approach isn't suitable when you are short of time. The method suggested here is simple. The program written in C language (or any other high-level language) is a skeleton. It calls the Assembly procedure, which carries out the main operations. In addition, you can include in the C module those procedures that are easier to write in C language. These procedures will be called from the Assembly code. The example provided in this section illustrates this approach. The C module includes procedures that convert strings into real numbers , carry out requested operations over them, and then convert the result back into a string.

Listing 20.7: A C module for the simplest calculator, which will be combined with the Assembly code in Listing 20.8
image from book
 // CALCC.CPP #include <windows.h> #include <stdio.h> // Call the Assembly procedure extern "C" __stdcall MAIN1(); // Add extern "C"__stdcall void sum(char *, char *, char *); // Subtract extern "C"__stdcall void su(char *, char *, char *); // Multiply extern "C"__stdcall void mu(char *, char *, char *); // Divide extern "C"__stdcall void dii(char *, char *, char *) ; int WINAPI WinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst,                      LPSTR lpszArgs, int nWinMode) {         MAIN1 ();         return 0; } extern "C"__stdcall void sum(char * s1, char * s2, char * s) {         float f1, f2, f;         f1 = atof(s1); f2 = atof(s2);         f = f1 + f2;         sprintf(s, "%f", f);         strcat(s, " + ");         return; } extern "C" __stdcall void su(char * s1, char * s2, char * s) {         float f1, f2, f;         f1 = atof(s1); f2 = atof(s2);         f = f1 - f2;         sprintf(s, "%f", f);         strcat(s, " -");         return; } extern "C" __stdcall void mu(char * s1, char * s2, char * s) {         float f1, f2, f;         f1 = atof(s1); f2 = atof(s2);         f = f1*f2;         sprintf(s, "%f", f);         strcat(s, " *");         return; } extern "C" __stdcall void dii(char * s1, char * s2, char * s) {         float f1, f2, f;         f1 = atof(s1); f2 = atof(s2);         if(f2!=0)          {                 f = f1/f2;                 sprintf(s, "%f", f);                 strcat(s, " /");         } else strcpy(s, "Division error");         return; } 
image from book
 
Listing 20.8: Assembly module that must be combined with the C program from Listing 20.7
image from book
 // CALC.RC // Definitions of constants // Window styles #define WS_SYSMENU       0x00080000L #define WS_MINIMIZEBOX   0x00020000L #define DS_3DLOOK        0x0004L #defin  ES_LEFT          0x0000L #define WS_CHILD         0x40000000L #define WS_VISIBLE       0x10000000L #define WS_BORDER        0x00800000L #define WS_TABSTOP       0x00010000L #define SS_LEFT          0x00000000L #define BS_PUSHBUTTON    0x00000000L #define BS_CENTER        0x00000300L #define DS_LOCALEDIT     0x20L #define ES_READONLY      0x0800L // Button identifiers #define IDC_BUTTON1        101 #define IDC_BUTTON2        102 #define IDC_BUTTON3        103 #define IDC_BUTTON4        104 DIAL1 DIALOG 0, 0, 170, 110 STYLE WS_OVERLAPPED  WS_CAPTION  WS_SYSMENU  WS_MINIMIZEBOX  DS_3DLOOK CAPTION "An example of a simple calculator" FONT 8, "Arial" {  CONTROL "", 1, "edit", ES_LEFT  WS_CHILD  WS_VISIBLE   WS_BORDER  WS_TABSTOP, 9, 8, 128, 12  CONTROL "", 2, "edit", ES_LEFT  WS_CHILD  WS_VISIBLE   WS_BORDER  WS_TABSTOP, 9, 27, 128, 12  CONTROL "", 3, "edit", ES_LEFT  WS_CHILD  ES_READONLY   WS_VISIBLE  WS_BORDER  WS_TABSTOP, 9, 76, 127, 12  CONTROL "+", IDC_BUTTON1, "button", BS_PUSHBUTTON   BS_CENTER  WS_CHILD  WS_VISIBLE  WS_TABSTOP, 11,  48, 15, 14  CONTROL "-", IDC_BUTTON2, "button", BS_PUSHBUTTON   BS_CENTER  WS_CHILD  WS_VISIBLE  WS_TABSTOP, 34,  48, 15, 14  CONTROL "*", IDC_BUTTON3, "button", BS_PUSHBUTTON   BS_CENTER  WS_CHILD  WS_VISIBLE  WS_TABSTOP, 56,  48, 15, 14  CONTROL "/", IDC_BUTTON4, "button", BS_PUSHBUTTON   BS_CENTER  WS_CHILD  WS_VISIBLE  WS_TABSTOP, 80,  48, 15, 14 } ; CALC.INC ; Constants ; This message arrives when the window is closed WM_CLOSE        equ 10h WM_INITDIALOG   equ 110h WM_COMMAND      equ 111h WM_GETTEXT      equ 0Dh WM_SETTEXT      equ 0Ch ; Prototypes of external procedures EXTERN      ExitProcess:NEAR EXTERN      GetModuleHandleA:NEAR EXTERN      DialogBoxParamA:NEAR EXTERN      EndDialog:NEAR EXTERN      SendDlgitemMessageA:NEAR ; Structures ; Message structure MSGSTRUCT STRUC         MSHWND        DWORD ?         MSMESSAGE     DWORD ?         MSWPARAM      DWORD ?         MSLPARAM      DWORD ?         MSTIME        DWORD ?         MSPT          DWORD ? MSGSTRUCT ENDS ; The CALC.ASM module .586P ; Flat memory model .MODEL FLAT, stdcall include calc.inc EXTERN sum:NEAR EXTERN su:NEAR EXTERN mu:NEAR EXTERN dii:NEAR PUBLIC MAIN1 ; INCLUDELIB directives for the linker includelib c:\tasm32\lib\import32.lib ;------------------------------------------- ; Data segment _DATA SEGMENT         MSG MSGSTRUCT <?>         HINST DD 0 ; Application descriptor         PA    DB "DIAL1", 0         S1    DB 50 DUP(0)         S2    DB 50 DUP(0)         S     DB 50 DUP(0) _DATA ENDS ; Code segment _TEXT SEGMENT ; The procedure called from the C module MAIN1 PROC ; Get the application descriptor         PUSH  0         CALL  GetModuleHandleA         MOV   [HINST], EAX ;-----------------------------------         PUSH  0         PUSH  OFFSET WNDPROC         PUSH  0         PUSH  OFFSET PA         PUSH  [HINST]         CALL  DialogBoxParamA ;-----------------------------------         RET MAIN1 ENDP ; Window procedure ; Position of parameters in the stack ; [EBP+014H]  ; LPARAM ; [EBP+10H]   ; WAPARAM ; [EBP+0CH]   ; MES ; [EBP+8]     ; HWND WNDPROC PROC         PUSH  EBP         MOV   EBP, ESP ;-----------------------------------         CMP   DWORD PTR [EBP+0CH], WM_CLOSE         JNE   L1         PUSH  0         PUSH  DWORD PTR [EBP+08H]         CALL  EndDialog         MOV   EAX, 1         JMP   FINISH L1:         CMP   DWORD PTR [EBP+0CH], WM_INITDIALOG         JNE   L2 ; Fill the edit fields if necessary JMP FINISH L2:         CMP   DWORD PTR [EBP+0CH], WM_COMMAND         JNE   FINISH         CMP   WORD PTR [EBP+10H], 101         JNE   NO_SUM ; First addend         PUSH  OFFSET S1         PUSH  50         PUSH  WM_GETTEXT         PUSH  1         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA ; Second addend         PUSH  OFFSET S2         PUSH  50         PUSH  WM_GETTEXT         PUSH  2         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgitemMessageA ; Sum         PUSH  OFFSET S         PUSH  OFFSET S2         PUSH  OFFSET S1         CALL  sum ; Output the sum         PUSH  OFFSET S         PUSH  50         PUSH  WM_SETTEXT         PUSH  3         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA         JMP   FINISH NO_SUM:         CMP   WORD PTR [EBP+10H], 102         JNE   NO_SUB ; Minuend         PUSH  OFFSET S1         PUSH  50         PUSH  WM_GETTEXT         PUSH  1         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA ; Subtrahend         PUSH  OFFSET S2         PUSH  50         PUSH  WM_GETTEXT         PUSH  2         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgitemMessageA ; Difference         PUSH  OFFSET S         PUSH  OFFSET S2         PUSH  OFFSET S1         CALL  su ; Compute the difference         PUSH  OFFSET S         PUSH  50         PUSH  WM_SETTEXT         PUSH  3         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA         JMP   FINISH NO_SUB:         CMP   WORD PTR [EBP+10H], 103         JNE   NO_MULT ; First multiplier         PUSH  OFFSET S1         PUSH  50         PUSH  WM_GETTEXT         PUSH  1         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA ; Second multiplier         PUSH  OFFSET S2         PUSH  50         PUSH  WM_GETTEXT         PUSH  2         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA ; Product         PUSH  OFFSET S         PUSH  OFFSET S2         PUSH  OFFSET S1         CALL  mu ; Output the product         PUSH  OFFSET S         PUSH  50         PUSH  WM_SETTEXT         PUSH  3         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgitemMessageA         JMP   FINISH NO_MULT:         CMP   WORD PTR [EBP+10H], 104         JNE   FINISH ; Dividend         PUSH  OFFSET S1         PUSH  50         PUSH  WM_GETTEXT         PUSH  1         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA ; Divisor         PUSH  OFFSET S2         PUSH  50         PUSH  WM_GETTEXT         PUSH  2         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA ; Division         PUSH  OFFSET S         PUSH  OFFSET S2         PUSH  OFFSET S1         CALL  dii ; Output the division result         PUSH  OFFSET S         PUSH  50         PUSH  WM_SETTEXT         PUSH  3         PUSH  DWORD PTR [EBP+08H]         CALL  SendDlgItemMessageA         JNE   FINISH FINISH:         MOV   EAX, 0         POP   EBP         RET   16 WNDPROC ENDP _TEXT ENDS END 
image from book
 

To translate this program, issue the following commands:

 tasm32 /ml calc.asm     brcc32 calc.rc 

Then, add the CALC.OBJ and CALC.RES files to the CALCC.CPP project (Listing 20.8).

image from book
Figure 20.1: The calculator program (Listings 20.7 and 20.8)


The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net