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

12. Functions

Jo Van Hoey1 
(1)
Hamme, Belgium
 

Assembler is not a “structured language.” Look at the multitude of jmp instructions and labels that allow the program execution to jump around and back and forth. Modern high-level programming languages have structures such as do...while, while...do, case, and so on. This is not so with assembly language.

But similar to modern program languages, assembly language has functions and procedures to help you give your code more structure. A little bit of nit-picking: a function executes instructions and returns a value. A procedure executes instructions and does not return a value.

In this book, we have already used functions; that is, we used an external function called printf , which is a C library function. In this chapter, we will introduce simple functions; in later chapters, we will cover important aspects of functions such as stack alignment, external functions, and calling conventions.

Writing a Simple Function

Listing 12-1 shows an example of an assembler program with a simple function to calculate the area of a circle.
; function.asm
extern printf
section .data
      radius      dq    10.0
      pi          dq    3.14
      fmt         db    "The area of the circle is %.2f",10,0
section .bss
section .text
      global main
;----------------------------------------------
main:
push  rbp
mov   rbp, rsp
      call  area              ; call the function
      mov   rdi,fmt           ; print format
      movsd xmm1, [radius]    ; move float to xmm1
      mov   rax,1             ; area in xmm0
      call  printf
leave
ret
;----------------------------------------------
area:
push  rbp
mov   rbp, rsp
      movsd xmm0, [radius]    ; move float to xmm0
      mulsd xmm0, [radius]    ; multiply xmm0 by float
      mulsd xmm0, [pi]        ; multiply xmm0 by float
leave
ret
Listing 12-1

function.asm

Figure 12-1 shows the output.
../images/483996_1_En_12_Chapter/483996_1_En_12_Fig1_HTML.jpg
Figure 12-1

function.asm output

There is a main part, identified as before with the label main, and then there is a function, identified with the label area. In main, the function area is called, which calculates the area of a circle using radius and pi, which are variables stored in a location in memory. As you can see, functions must have a prologue and an epilogue, similar to main.

The computed area is stored in xmm0. Returning from the function to main, printf is called with rax containing the value 1, meaning there is one xmm register that needs to be printed. We introduce a new instruction here: leave. This instruction does the same as mov rsp, rbp, and pop rbp (the epilogue).

If you return a value from a function, you use xmm0 for floating-point values and use rax for other values, such as integers or addresses. The function arguments, pi and radius, are located in memory. That is okay for now, but it is better to use registers and the stack to store function arguments. Using memory variables to pass on values to functions can create naming conflicts between values used in main and in functions and can make your code less “portable.”

More Functions

Let’s discuss some more characteristics of functions using another example (see Listing 12-2).
; function2.asm
extern printf
section .data
      radius      dq    10.0
section .bss
section .text
;----------------------------------------------
area:
      section .data
            .pi  dq    3.141592654      ; local to area
      section .text
push  rbp
mov   rbp, rsp
      movsd      xmm0, [radius]
      mulsd      xmm0, [radius]
      mulsd      xmm0, [.pi]
leave
ret
;----------------------------------------------
circum:
section .data
      .pi  dq     3.14        ; local to circum
section .text
push  rbp
mov   rbp, rsp
      movsd       xmm0, [radius]
      addsd       xmm0, [radius]
      mulsd       xmm0, [.pi]
leave
ret
;----------------------------------------------
circle:
section .data
      .fmt_area  db    "The area is %f",10,0
      .fmt_circum      db    "The circumference is %f",10,0
section .text
push  rbp
mov   rbp, rsp
      call  area
      mov   rdi,.fmt_area
      mov   rax,1            ; area in xmm0
      call  printf
      call  circum
      mov   rdi,.fmt_circum
      mov   rax,1            ; circumference in xmm0
      call  printf
leave
ret
;----------------------------------------------
      global main
main:
push  rbp
mov   rbp, rsp
      call  circle
leave
ret
Listing 12-2

function2.asm

Here, we have main calling the function circle, which in turn calls the functions area and circum. So, functions can call other functions. In fact, main is just a function calling other functions. But beware that functions cannot be nested, which means functions cannot contain the code for other functions.

Also, functions can have their own sections, such as .data, .bss, and .text. What about the period before pi and the fmt variables? The period indicates a local variable, which means that the variable is known only inside the function where it is declared. In the function area, we used a value for pi that is different from the pi used in the function circum. The variable radius, declared in section .data of main, is known in every function in this source code listing, including main. It is always advisable to use local variables whenever possible; this reduces the risk of conflicting variable names.

Figure 12-2 shows the output for the program.
../images/483996_1_En_12_Chapter/483996_1_En_12_Fig2_HTML.jpg
Figure 12-2

function2.asm output

Summary

In this chapter, you learned the following:
  • How to use functions.

  • Functions can have their own section .data and section .bss.

  • Functions cannot be nested.

  • Functions can call other functions.

  • main is just another function.

  • How to use local variables.

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

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