Linking to C/C++ in Protected Mode

Linking to C/C++ in Protected Mode

Programs written for x86 processors running in Protected mode can sometimes have bottlenecks

that must be optimized for runtime efficiency. If they are embedded systems, they may have

stringent memory size limitations. With such goals in mind, we will show how to write external

procedures in assembly language that can be called from C and C++ programs running in Protected mode. Such programs consist of at least two modules: The first, written in assembly

language, contains the external procedure; the second module contains the C/C++ code that

starts and ends the program. There are a few specific requirements and features of C/C++ that

affect the way you write assembly code.

Arguments(实参) Arguments are passed by C/C++ programs from right to left, as they appear in

the argument list. After the procedure returns, the calling program is responsible for cleaning up

the stack. This can be done by either adding a value to the stack pointer equal to the size of the

arguments or popping an adequate number of values from the stack.

External Identifiers In the assembly language source, specify the C calling convention in

the .MODEL directive and create a prototype for each procedure called from an external C/C++

program:

.586

.model flat,C

AsmFindArray PROTO,

srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD

Declaring the Function In a C program, use the extern qualifier when declaring an external

assembly language procedure. For example, this is how to declare AsmFindArray:

extern bool AsmFindArray( long n, long array[], long count );

If the procedure will be called from a C++ program, add a “C” qualifier to prevent C++ name

decoration:

extern "C" bool AsmFindArray( long n, long array[], long count );

Name decoration is a standard C++ compiler technique that involves modifying a function name

with extra characters that indicate the exact type of each function parameter. It is required in any

language that supports function overloading (two functions having the same name, with different

parameter lists). From the assembly language programmer’s point of view, the problem with

name decoration is that the C++ compiler tells the linker to look for the decorated name rather

than the original one when producing the executable file.

13.3.1 Using Assembly Language to Optimize C++ Code

One of the ways you can use assembly language to optimize programs written in other languages

is to look for speed bottlenecks. Loops are good candidates for optimization because any

extra statements in a loop may be repeated enough times to have a noticeable effect on your program’s

performance.

Most C/C++ compilers have a command-line option that automatically generates an assembly

language listing of the C/C++ program. In Microsoft Visual C++, for example, the listing file can

contain any combination of C++ source code, assembly code, and machine code, shown by the

options in Table 13-2. Perhaps the most useful is /FAs, which shows how C++ statements are

translated into assembly language.

Table 13-2 Visual C++ Command-Line Options for ASM Code Generation.


Command Line


Contents of Listing File


/FA


Assembly-only listing


/FAc


Assembly with machine code


/FAs


Assembly with source code


/FAcs


Assembly, machine code, and source

FindArray Example

Let’s create a program that shows how a sample C++ compiler generates code for a function

named FindArray. Later, we will write an assembly language version of the function, attempting

to write more efficient code than the C++ compiler. The following FindArray function (in C++)

searches for a single value in an array of long integers:

bool FindArray( long searchVal, long array[], long count )

{

for(int i = 0; i < count; i++)

{

if( array[i] == searchVal )

return true;

}

return false;

}

FindArray Code Generated by Visual C++

Let’s look at the assembly language source code generated by Visual C++ for the FindArray

function, alongside the function’s C++ source code. This procedure was compiled to a Release

target with no code optimization in effect:

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 

    TITLE    c:\Users\Stud\Documents\Visual Studio 2008\Projects\FindArray\FindArray\FindArray.cpp
    .686P
    .XMM
    include listing.inc
    .model    flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC    [email protected]@[email protected]                ; FindArray
EXTRN    __RTC_Shutdown:PROC
EXTRN    __RTC_InitBase:PROC
;    COMDAT rtc$TMZ
; File c:\users\stud\documents\visual studio 2008\projects\findarray\findarray\findarray.cpp
rtc$TMZ    SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ    ENDS
;    COMDAT rtc$IMZ
rtc$IMZ    SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ    ENDS
;    COMDAT [email protected]@[email protected]
_TEXT    SEGMENT
_i$5245 = -8                        ; size = 4
_searchVal$ = 8                        ; size = 4
_array$ = 12                        ; size = 4
_count$ = 16                        ; size = 4
[email protected]@[email protected] PROC                ; FindArray, COMDAT
; Line 7
    push    ebp
    mov    ebp, esp
    sub    esp, 204                ; 000000ccH
    push    ebx
    push    esi
    push    edi
    lea    edi, DWORD PTR [ebp-204]
    mov    ecx, 51                    ; 00000033H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
; Line 8
    mov    DWORD PTR _i$5245[ebp], 0
    jmp    SHORT [email protected]
$[email protected]:
    mov    eax, DWORD PTR _i$5245[ebp]
    add    eax, 1
    mov    DWORD PTR _i$5245[ebp], eax
$[email protected]:
    mov    eax, DWORD PTR _i$5245[ebp]
    cmp    eax, DWORD PTR _count$[ebp]
    jge    SHORT [email protected]
; Line 10
    mov    eax, DWORD PTR _i$5245[ebp]
    mov    ecx, DWORD PTR _array$[ebp]
    mov    edx, DWORD PTR [ecx+eax*4]
    cmp    edx, DWORD PTR _searchVal$[ebp]
    jne    SHORT [email protected]
; Line 11
    mov    al, 1
    jmp    SHORT [email protected]
$[email protected]:
; Line 12
    jmp    SHORT [email protected]
$[email protected]:
; Line 13
    xor    al, al
$[email protected]:
; Line 14
    pop    edi
    pop    esi
    pop    ebx
    mov    esp, ebp
    pop    ebp
    ret    0
[email protected]@[email protected] ENDP                ; FindArray
_TEXT    ENDS
PUBLIC    _wmain
; Function compile flags: /Odtp /RTCsu /ZI
;    COMDAT _wmain
_TEXT    SEGMENT
_argc$ = 8                        ; size = 4
_argv$ = 12                        ; size = 4
_wmain    PROC                        ; COMDAT
; Line 16
    push    ebp
    mov    ebp, esp
    sub    esp, 192                ; 000000c0H
    push    ebx
    push    esi
    push    edi
    lea    edi, DWORD PTR [ebp-192]
    mov    ecx, 48                    ; 00000030H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
; Line 18
    xor    eax, eax
; Line 19
    pop    edi
    pop    esi
    pop    ebx
    mov    esp, ebp
    pop    ebp
    ret    0
_wmain    ENDP
_TEXT    ENDS
END

Specify the /FA switch for the cl compiler. Depending on the value of the switch either only assembly code or high-level code and assembly code is integrated. The filename gets .asm file extension. Here are the supported values:

  • /FA Assembly code; .asm
  • /FAc Machine and assembly code; .cod
  • /FAs Source and assembly code; .asm
  • /FAcs Machine, source, and assembly code; .cod

Click "Project"-> Double Click "Configuration Properties(配置属性)"-> Choose "C/C++"-> Click "Output Files"->

Three 32-bit arguments were pushed on the stack in the following order: count, array, and
searchVal. Of these three, array is the only one passed by reference because in C/C++, an array
name is an implicit pointer to the array’s first element. The procedure saves EBP on the stack and
creates space for the local variable i by pushing an extra doubleword on the stack (Figure 13–1).

Inside the procedure, the compiler reserves local stack space for the variable i by pushing ECX
(line 9). The same storage is released at the end when EBP is copied back into ESP (line 14).
There are 14 instructions between the labels $L284 and $L285, which constitute the main body
of the loop. We can easily write an assembly language procedure that is more efficient than the
code shown here.

时间: 2024-10-23 19:48:47

Linking to C/C++ in Protected Mode的相关文章

Linking code for an enhanced application binary interface (ABI) with decode time instruction optimization

A code sequence made up multiple instructions and specifying an offset from a base address is identified in an object file. The offset from the base address corresponds to an offset location in a memory configured for storing an address of a variable

CMake快速入门教程-实战

http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/ http://blog.csdn.net/dbzhang800/article/details/6314073 http://www.cnblogs.com/coderfenghc/archive/2013/01/20/2846621.html http://blog.sina.com.cn/s/blog_4aa4593d0100q3bt.html http://hahack.com/c

C 编译过程浅析

From where i stand, there are two programmig languages in the world, which is C lang and the other. --- standby 编译(compile) 预处理(也称预编译,Preprocessing) 编译(Compilation) 汇编 (Assembly) 连接(Linking) GCC参考 gcc - GNU project C and C++ compiler If you only want

CMake快速入门教程:实战

转自http://blog.csdn.net/ljt20061908/article/details/11736713 0. 前言    一个多月前,由于工程项目的需要,匆匆的学习了一下cmake的使用方法,现在有时间拿出来整理一下.本文假设你已经学会了cmake的使用方法,如果你还不会使用cmake,请参考相关资料之后再继续向下看.    本文中介绍的是生成可执行程序的方法和步骤,生成动态库和静态库的方法与此有所不同,随后会介绍动态库和静态库项目中cmake的编写方法.    本文参考<CMa

redmine问题集锦02

1.ERROR:  While executing gem ... (Gem::Exception)    Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources 方法: 进入ruby源码解压包,进入ruby 源码包下的  ext/openssl ,用ruby自带的openssl编译,而不是yum 的openssl cd /root/ruby-2.1.5/ex

Redis3.2.5 集群搭建

1:集群中的机器信息 IP PORT 192.168.3.10 7000,7001,7002 192.168.3.11 7004,7005,7006 2:安装Redis 分别在10与11机器上面安装Redis. (1)解压安装 #tar -zxvf redis-3.2.5.tar.gz #cd redis-3.2.5 #make && make install (2)修改系统的限制文件 修改文件/etc/security/limits.conf,加入以下两行: * soft nofile

Ubuntu14.04安装Oracle12C

原文:http://www.techienote.com/2014/04/how-to-install-oracle-12c-enterprise-edition-database-ubuntu-13-10.html.ubuntu14.04 LTS同样适用 Following is the how to for installing Oracle Database 12C on Ubuntu 13.10Note : I’m not running this installation on a p

转:CMake快速入门教程-实战

CMake快速入门教程:实战 收藏人:londonKu     2012-05-07 | 阅:10128  转:34    |   来源   |  分享      0. 前言一个多月前,由于工程项目的需要,匆匆的学习了一下cmake的使用方法,现在有时间拿出来整理一下.本文假设你已经学会了cmake的使用方法,如果你还不会使用cmake,请参考相关资料之后再继续向下看.本文中介绍的是生成可执行程序的方法和步骤,生成动态库和静态库的方法与此有所不同,随后会介绍动态库和静态库项目中cmake的编写方

5、Oracle备份

1.1 Oracle数据库备份 1.1.1 链接Oracle介质管理库 请在数据库节点上操作. [[email protected]/usr/openv/netbackup/bin]$ ./oracle_link Thu Jul  9 14:35:44 CST 2015 All Oracle instances should be shutdown before running this script. Please log into the Unix system as the Oracle