© Jo Van Hoey 2019
J. Van HoeyBeginning x64 Assembly Programminghttps://doi.org/10.1007/978-1-4842-5076-1_22

22. From C to Assembler

Jo Van Hoey1 
(1)
Hamme, Belgium
 

In the previous chapters, we used C functions from time to time for convenience, such as the standard printf function or the version we developed, printb. In this chapter, we will show how to use assembler functions in the programming language C. The value of the calling conventions will become immediately evident. In this chapter, we use the System V AMD64 ABI calling conventions, because we are working on a Linux operating system. Windows has different calling conventions. If you have worked your way through the previous chapters and example code, this chapter will be an easy one.

Writing the C Source File

Most of the assembler code should be familiar to you from previous chapters. Just the C program is new. We compute the area and circumference of a rectangle and a circle. Then we take a string and reverse it, and finally we take the sum of the elements of an array, double the elements of the array, and take the sum of the elements of the doubled array. Let’s look at the different source files.

Let’s start with the C source file; see Listing 22-1.
// fromc.c
#include <stdio.h>
#include <string.h>
extern int rarea(int, int);
extern int rcircum(int, int);
extern double carea( double);
extern double ccircum( double);
extern void sreverse(char *, int );
extern void adouble(double [], int );
extern double asum(double [], int );
int main()
{
      char rstring[64];
      int side1, side2, r_area, r_circum;
      double radius, c_area, c_circum;
      double darray[] = {70.0, 83.2, 91.5, 72.1, 55.5};
      long int len;
      double sum;
// call an assembly function with int arguments
      printf("Compute area and circumference of a rectangle ");
      printf("Enter the length of one side : ");
      scanf("%d", &side1 );
      printf("Enter the length of the other side : ");
      scanf("%d", &side2 );
      r_area = rarea(side1, side2);
      r_circum = rcircum(side1, side2);
      printf("The area of the rectangle = %d ", r_area);
      printf("The circumference of the rectangle = %d ", r_circum);
// call an assembly function with double (float) argument
      printf("Compute area and circumference of a circle ");
      printf("Enter the radius : ");
      scanf("%lf", &radius);
      c_area = carea(radius);
      c_circum = ccircum(radius);
      printf("The area of the circle = %lf ", c_area);
      printf("The circumference of the circle = %lf ", c_circum);
// call an assembly function with string argument
      printf("Reverse a string ");
      printf("Enter the string : ");
      scanf("%s", rstring);
      printf("The string is = %s ", rstring);
      sreverse(rstring,strlen(rstring));
      printf("The reversed string is = %s ", rstring);
// call an assembly function with array argument
      printf("Some array manipulations ");
      len = sizeof (darray) / sizeof (double);
      printf("The array has %lu elements ",len);
      printf("The elements of the array are: ");
      for (int i=0;i<len;i++){
            printf("Element %d = %lf ",i, darray[i]);
      }
      sum = asum(darray,len);
      printf("The sum of the elements of this array = %lf ", sum);
      adouble(darray,len);
      printf("The elements of the doubled array are: ");
      for (int i=0;i<len;i++){
            printf("Element %d = %lf ",i, darray[i]);
      }
      sum = asum(darray,len);
      printf("The sum of the elements of this doubled array = %lf ", sum);
      return 0;
}
Listing 22-1

fromc.c.asm

Writing the Assembler Code

We start with the function declarations for the assembler functions. These are external functions, and we declare the datatypes of the return values and arguments.

The program will prompt the user for most of the data to be used, except for the array, where we provide some values for convenience.

Listing 22-2 through Listing 22-7 show the assembly functions.
;rect.asm
section .data
section .bss
section .text
global rarea
rarea:
      section .text
            push  rbp
            mov   rbp, rsp
            mov   rax, rdi
            imul  rsi
            leave
            ret
global rcircum
rcircum:
      section .text
            push  rbp
            mov   rbp, rsp
            mov   rax, rdi
            add   rax, rsi
            imul  rax, 2
            leave
            ret
Listing 22-2

rect.asm

;circle.asm
section .data
      pi   dq    3.141592654
section .bss
section .text
global carea
carea:
      section .text
            push  rbp
            mov   rbp, rsp
            movsd xmm1, qword [pi]
            mulsd xmm0,xmm0       ;radius in xmm0
            mulsd xmm0, xmm1
            leave
            ret
global ccircum
ccircum:
      section .text
            push  rbp
            mov   rbp, rsp
            movsd xmm1, qword [pi]
            addsd xmm0,xmm0       ;radius in xmm0
            mulsd xmm0, xmm1
            leave
            ret
Listing 22-3

circle.asm

;sreverse.asm
section .data
section .bss
section .text
global sreverse
sreverse:
push  rbp
mov   rbp, rsp
pushing:
      mov rcx, rsi
      mov rbx, rdi
      mov r12, 0
      pushLoop:
            mov rax, qword [rbx+r12]
            push rax
            inc r12
            loop pushLoop
popping:
      mov rcx, rsi
      mov rbx, rdi
      mov r12, 0
      popLoop:
            pop rax
            mov byte [rbx+r12], al
            inc r12
            loop popLoop
mov rax, rdi
leave
ret
Listing 22-4

sreverse.asm

; asum.asm
section .data
section .bss
section .text
global asum
asum:
      section .text
;calculate the sum
            mov   rcx, rsi   ;array length
            mov   rbx, rdi   ;address of array
            mov   r12, 0
            movsd xmm0, qword [rbx+r12*8]
            dec rcx    ; one loop less, first
                       ; element already in xmm0
      sloop:
            inc r12
            addsd xmm0, qword [rbx+r12*8]
            loop sloop
ret         ; return sum in xmm0
Listing 22-5

asum.asm

; adouble.asm
section .data
section .bss
section .text
global adouble
adouble:
      section .text
;double the elements
            mov   rcx, rsi     ;array length
            mov   rbx, rdi     ;address of array
            mov   r12, 0
      aloop:
            movsd xmm0, qword [rbx+r12*8]      ;take an
            addsd xmm0,xmm0                    ; double it
            movsd qword [rbx+r12*8], xmm0      ;move it to array
            inc r12
            loop aloop
ret
Listing 22-6

adouble.asm

fromc: fromc.c rect.o circle.o sreverse.o adouble.o asum.o
      gcc -o fromc fromc.c rect.o circle.o sreverse.o
      adouble.o asum.o -no-pie
rect.o: rect.asm
      nasm -f elf64 -g -F dwarf rect.asm -l rect.lst
circle.o: circle.asm
      nasm -f elf64 -g -F dwarf circle.asm -l circle.lst
sreverse.o: sreverse.asm
      nasm -f elf64 -g -F dwarf sreverse.asm -l sreverse.lst
adouble.o: adouble.asm
      nasm -f elf64 -g -F dwarf adouble.asm -l adouble.lst
asum.o: asum.asm
      nasm -f elf64 -g -F dwarf asum.asm -l asum.lst
Listing 22-7

makefile

In the assembly code, there is nothing special; just be careful about the datatypes of the variables received from the calling C program. The assembly functions take the arguments from the calling program and store them in the registers according to the calling conventions. Results are returned to the caller in rax (integer value) or xmm0 (floating-point value). Now you can develop your own libraries of functions to use in assembler or C, and because of the calling conventions, you do not have to worry about how to pass arguments. Just be careful about using the correct datatypes.

Note how we used a backslash () in the makefile for splitting a long line, and we used tabs to align the instructions.

Figure 22-1 shows the output.
../images/483996_1_En_22_Chapter/483996_1_En_22_Fig1_HTML.jpg
Figure 22-1

fromc.c output

Summary

In this chapter, you learned about the following:
  • Calling an assembly function from within a higher language source, in this case from within C

  • The value of a calling convention

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.12.34