程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> GCC 下 C和ASM混合編程

GCC 下 C和ASM混合編程

編輯:關於C語言

下面是一個簡單的示例程序,這個程序顯示了如何實現C和ASM的接口。

Contents:
    readme.txt    --  this file
    endian_demo.c    --  the C source file, implements the main function
    function.S      --  the AT&T-format ASM file, implements the ASM functions
    Makefile    --  the makefile for compiling the program


Instructions to Compile:
-----------------------
   Just run "make" in the source file folder. If everything goes well, an executable
binary file named "endian_demo" will be created in the same folder.    

Instructions to Run:
-------------------
   Just run "./endian_demo" in the folder in which the program is compiled. Argument
should be specified in the command line. For example:
   ./endian_demo 1 255 1334
   More than one number should be specified. If no number specified, the program will
print a usage message.

Source Files:
------------------
endian_demo.c :
   This is the main C source file of the program. It implements the main()
function, which parses the command-line argument, and invokes the ASM functions
to swap the endian of the number and print the hexadecimal form of the number.

function.S :
   This is the AT&T format assembly file which implements the two functions:
writeHexASCII and swapEnds.
   To make the assembly code interface the ANSI C code, we need to understand how
the gcc C compiler generating code for the arguments of the functions and the return
value of the functions.
   Arguments of a function is passed via the stack of the program. Before invoking
the function, arguments is pushed into the stack, and then call the function. In the
function itself, it should retrive the arguments from the stack, whose current
address is stored in the esp register of the x86 CPU.
   Return value is passed via the register eax. The function puts the return value
in eax, then a "ret" instruction will return to the place where this functions is
invoked.
   
   void writeHexASCII(char *buffer,unsigned int number);
      This function takes two arguments, the address of the buffer and the number to
be converted to hexadecimal strings. Each digits of the hex value is extracted from
the number using the shifting instruction, then converted to hex value, and then
moved to the buffer.   

   unsigned int swapEnds(unsigned int x);
      This functions takes one argument and returns the swapped value.  The bytes
of the number is extracted and swapped, and then return the value in eax register.

Assumptions:
------------
1. The target linux system is running on Intel X86 32-bit CPU
2. GNU make and gcc are installed on the system.


以下是代碼:

這個是主程序文件endian_demo.c

#include <stdio.h>
#include <stdlib.h>

extern void writeHexASCII(char *buffer,unsigned int number);
extern unsigned int swapEnds(unsigned int x);

int main(int arg_c, char **arg_v)
{
    int i;
    unsigned int num, num_swap;
    char buf[16];

    if(arg_c < 2)
    {
  fprintf(stderr, "Usage: %s NUM1 NUM2 NUM3...\n", arg_v[0]);
  return -1;
    }

    i = 1;
    while(i < arg_c)
    {
  num = atoi(arg_v[i]);
  num_swap = swapEnds(num);

  fprintf(stdout, "%d: ", num);
  writeHexASCII(buf, num);
  fprintf(stdout, "%s <-> ", buf);
  writeHexASCII(buf, num_swap);
  fprintf(stdout, "%s = ", buf);
  fprintf(stdout, "%d\n", num_swap);

  i++;
    }

    return 0;
}
 


這個是實現endian swap和hex轉字符串的函數,文件名function.S

/* here we use AT&T format assembly */
    .text
    .code32
    .globl    writeHexASCII
    .globl    swapEnds

/*
0x8(%esp) = number
0x4(%esp) = *buffer
%ecx = shift length
%eax = hex value
%edi = loop count

*/
writeHexASCII:
    movl   $28,%ecx
    movl   $0,%edi
    mov    0x4(%esp),%edx
    jmp    if_loop_end
loop_start:
    mov    0x8(%esp),%eax
    shr    %cl,%eax
    and    $0xf,%eax
    cmpl   $9,%eax
    jg     hex_abcdef
hex_0_9:
    addl   $0x30,%eax
    jmp    hex_convert_complete
hex_abcdef:
    addl   $0x57,%eax
hex_convert_complete:
    mov    %al,(%edx)
    add    $1,%edx
    subl   $4,%ecx
    addl   $1,%edi
if_loop_end:
    cmpl   $7,%edi
    jle    loop_start
    movb   $0x0,(%edx)
    ret


/*
0x4(%esp) = x
%edi = temp value
*/
swapEnds:
    mov    4(%esp),%eax
    and    $0xff000000,%eax
    shr    $24,%eax
    mov    %eax,%edi
    
    movzbl 4(%esp),%eax
    shl    $24,%eax
    or     %eax,%edi
    
    mov    4(%esp),%eax
    and    $0xff0000,%eax
    shr    $8,%eax
    or     %eax,%edi
    
    mov    4(%esp),%eax
    and    $0xff00,%eax
    shl    $8,%eax
    or     %eax,%edi
    
    mov    %edi,%eax
    ret    


下面是一個簡單的Makefile,用來編譯這個程序:

all:    endian_demo

endian_demo:    function.o endian_demo.o
    gcc -o $@ function.o endian_demo.o

function.o:    function.S
    gcc -o $@ -c $<

endian_demo.o:    endian_demo.c
    gcc -o $@ -c $< -ansi

clean:
    rm -f *.o
    rm -f endian_demo

 

  幾個常用的國外干私活兼職網站 Freelancer.com - 排名第一的軟件兼職工作網站 兼職編程、開發, C/C++/C#, PHP, Web開發, ASP, 外包項目, 接國外私活, 程序員兼職, 外包開發, 國外項目外包, 網站外包項目  

本文出自 “techlife” 博客,請務必保留此出處http://techlife.blog.51cto.com/212583/55348

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved