下面是一个简单的示例程序,这个程序显示了如何实现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

 

 
几个常用的国外干私活兼职网站