Thursday, 13 March 2014

about fossil(1)

fossil is another software I am studying on. This is a distributed version control system, bug tracking system and wiki software server for use in software development. It is like the Git. 

For now I just want to build it on my x86_64 machine first.

after downloading it and generate source code, I take a look at the whold directory.
configure file again! That makes life easy! But let me take a look at the BUILD.txt.
nothing special, lets begin building.

  mkdir build
  cd build
  ../configure

 then make, but I got error because of the sqlite3.c missing.
I check the official website and say it is included in the src, but I don't see it. So I just download another one.





Now it is built.


fossil study(1) is done.

Hua

about cxxtools(1)

This days I spend some time taking a look at the cxxtools library. It is a library written in C++, and provides classes for serialization, unicode text, multi threading, networking, rpc, http client and server, xml, logging and many more. What I will do is trying to build and test this library. And If I port the codes to aarch64, do I need to modify some codes. My environment is Fedora linux and the CPU is X86_64.

The first step is downloading the source code.  the cmd is 
          fedpkg clone -a cxxtools

Waiting for finishing downloading, then go to the cxxtools directory, and 
          fedpkg prep

Next, go to the cxxtools-2.2.1 directory, and try to find the something about the asembly codes for the first look.(to see if it needs to be modified for porting to arrch64)

Under the src directory, I find many cpp file for atomicity functions, and they all codes in asembly language, I think maybe that is what I should focus on.

All the codes using asembly,

 Leave it for now. I want build it first on the x86_64 machine.

I red the README file and INSTALL file, and know that this library's author uses the automake and autoconfig for development. He provides configure file which can be used to config and build. Then I run ./configure and then make, and it start to build:

After 10 min(so long..), it is done. and now I have a built cxxtools on my x86_64 machine.

I will continue studying about it.

Hua

Monday, 10 March 2014

What is the meaning of do{...} while(0)

    Sometimes we see some codes in C using this pattern: do{...} while(0). It looks it doesn't do anything else but just simply running everything in the braces. When I saw these codes the first time, I also felt weird. Then I did some research and post it. I hope it can help you.

    This pattern is only used in C or C++’s conditional compilation and when you want to use #define to represent multiple statements. A simple sample is like this:

#define function(x)  do { a(x); b(x); }while (0)

so, we can use it like this:

if(some condition){
    function(x);
}

else 
      blah blah....

     Why we have to use this pattern? When you want to use #define to represent multiple statements, 
this statement wouldn't work:
#define function(x)  foo(x); bar(x)   //cause syntax error in the if statement

this statement still won't work:
#define FOO(x) { foo(x); bar(x); } // doesn't work
 
only in this pattern:
#define function(x)  do { a(x); b(x); }while (0)
It work well in the if statement.

That is my study about this thing. I hope I can help you.

Hua

Sunday, 2 February 2014

Write a simple program with Assembler language

Assembler Lab

I will write a simple program to show the output below:

1. This is my code for x86_64 processor with explanation:

.text
.globl _start
start = 0                               /* starting value for the loop index */
max = 31                              /* loop exits when loop condition is i<max */
_start:
    mov     $start,%r15          /* loop index */
loop:
        mov     $0,%rdx            /* assign value 0 to rdx (refresh the rdx) */
        mov     %r15,%rax       /* move the loop index to rax (for later divide operation) */
        mov     $10,%r10          /* move value 10 to r10 register */
        div     %r10                   /* divide rax by r10 (10), places quotient into rax, */
                                             /* remainder into rdx, rdx must be zero before this step */
        mov     %rax,%r14       /* move the quotient to r14 */
        mov     %rdx,%r13       /* move the remainder to r13 */
        mov     $'0',%r12          /* assign ascii '0' to r12 */
        cmp     $0,%r14             /* compare the quotient with zero */
        je      skip                      /* skip if equal */
        add     %r12,%r14         /* modify the quotient to become the ascii character, */
                                              /* the character will be put into the msg later */
        movq    $high,%rsi        /* location the quotient will be added into */
        movb    %r14b,(%rsi)    /* move the quotient to msg */
skip:
        add     %r12,%r13         /* modify the remainder to become the ascii character */
        movq    $low,%rsi          /* location the remainder will be added into */
        movb    %r13b,(%rsi)    /* move the remainder to msg */

        movq    $len,%rdx         /* message length */
        movq    $msg,%rsi         /* message location */
        movq    $1,%rdi              /* file descriptor stdout */
        movq    $1,%rax             /* syscall sys_write */
        syscall

    inc     %r15                      /* increment index */
    cmp     $max,%r15           /* see if we're done */
    jne     loop                        /* loop if we're not */
    mov     $0,%rdi                /* exit status */
    mov     $60,%rax              /* syscall sys_exit */
    syscall
.data
msg:    .ascii      "Loop:   \n" /* the content of msg  */
len = . - msg                          /* length of msg */
high = . - 3                            /* define variable high */
low = . - 2                              /* define variable low */



2. I also write codes for aarch64 processor:


.text
.globl _start
_start:
        mov             x28, 0                     /* move 0 to x28, loop index */
loop:
                mov     x27,x28                  /* move x28 to x27 for later use */
                mov     x26,'0'                    /* move ascii '0' to x26 */
                mov     x25,10                    /* move 10 to x25 for division operation */

                udiv    x24, x27, x25           /* x27 (loop index) divides by x25 (10), */

                                                          /* quotient is in the x24 */
                msub    x23, x24, x25, x27  /* (x27 - x24 * x25) will be stored in x23, */

                                                          /*which is the remainder of x27 divides by x25 */
                adr     x20,msg                   /* get the location of msg */
                cmp     x24,0                       /* compare the quotient with 0 */
                beq     skip                         /* go to skip if equal */
                add     x24, x24, x26            /* add x26 to x24,  */

                                                          /* which make the quotient become ascii value */
                strb    w24,[x20,6]               /* move the quotient ascii value to the msg offset 6 */
skip:
                add     x23, x23, x26            /* make the remainder become ascii value */
                strb    w23,[x20,7]               /* move the remainder ascii value to msg offset 7 */

                mov     x0, 1                        /* file descriptor: 1 is stdout */
                adr     x1, msg                     /* message location (memory address) */
                mov     x2, len                     /* message length (bytes) */
                mov     x8, 64                      /* write is syscall #64 */
                svc     1                               /* invoke syscall */

        add     x28, x28, 1                        /* add 1 to loop index */
        cmp     x28, 31                             /* compare index with 31 */
        bne     loop                                  /* go to loop if not equal */
        mov     x0, 0                                /* status -> 0 */
        mov     x8, 93                              /* exit is syscall #93 */
        svc     0                                       /* invoke syscall */

.data
msg:    .ascii      "Loop:   \n"               /* define msg */
len = . - msg                                        /* length of msg */


Friday, 31 January 2014

Explain the action how C program works

1. Write a basic C program which prints a message on the screen, Hello World!-style -- something like this:
 
        #include <stdio.h>

       int main() {
           printf("Hello World!\n");
       }
 
2. Compile the program using the GCC compiler. Include these compiler options (refer to the gcc manpage for details):
-g               # enable debugging information
-O0              # do not optimize (that's a capital letter and then the digit zero)
-fno-builtin     # do not use builtin function optimizations

3. The resulting binary is an ELF (Executable and Linkable Format) file, which contains multiple sections. These sections may contain object code, link tables, debugging symbols, program data (such as constants and the initial values of variables), metadata about the program and ELF sections, and comments.
Examine the binary produced by the previous step using the objdump program. These options may be useful -- see the manpage for objdump for other options:
-f          # display header information for the entire file
-s          # display per-section summary information
-d          # disassemble sections containing code
--source    # (implies -d) show source code, if available, along with disassembly

4. Try to gain a basic understanding of what the compiled code is doing.
5. Recompile the code with these changes:
(1) Add the compiler option -static. Note and explain the change in size, section headers, and the function call.
 files' size of compiling originally:


the files' size of compiling with -static:




We can see the per-section summary information, disassemble sections and source code for static one are much more than original one.
 
 The static one include all the libraries in the compiled file, section headers 
are much bigger than original one. 
Function call for original:
 
function call for -static:
 
we can see the static directly call function from IO, because it includes everything it need.
 

(2) Remove the compiler option -fno-builtin. Note and explain the change in the function call.
original function call:

remove no-builtin:





We can see when remove no-builtin, the function call is optimized and directly call the 'puts' which is the parent of printf when you don't add any parameters.

(3) Remove the compiler option -g. Note and explain the change in size, section headers, and disassembly output.
original files size:


remove -g:
 

We can see when remove the -g, the pre-section info is smaller, because it doesn't include debug information any more.

(4) Add additional arguments to the printf() function in your program. Note which register each argument is placed in. (Tip: Use sequential integer arguments after the first string argument. Go up to 10 arguments and note the pattern).
 
 We can see the integer arguments is place in the registers one by one together. And they are moved backward. Here we can also find how stack works in the when compiler is working with registers.

(5) Move the printf() call to a separate function, and call that function from main(). Explain the changes in the object code.
original code:




When separate function:


We can see when separate the printf to another function, it will go to the function first, and then call printf.

(6) Remove -O0 and add -O3 to the gcc options. Note and explain the difference in the compiled code.
 when add -o3 optimization,






the code goes to the front, and the section info become inline.

Thats it.