DM548/544, 2014

Resources

  • Course webpage: link

  • x86 assembler syntax, AT&T (used by the GNU tools) vs. Intel: link

  • x86 Assembly Wiki book: link

  • x86 instruction listing: link

  • x86 instruction reference: link

  • Complete developer reference from Intel: link

    • Section 5.6.3: SSE2 Integer Instructions

    • Section 5.10.1: SSE4.1 Integer Multiplication

  • Yet another instruction reference: link

Integer Division in x86-64

The difference from Kim Skak Larsens x86 example is that sign extension of %rax in to %rdx is done with cqto (“convert quad to oct”), and the division instruction is idivq.

Calling Convention (Linux)

The calling convention in 32-bit is: push the arguments on the stack in right-to-left order.

In 64-bit assembly (x86-64) the first arguemnts are passed in registers (see here).

The first 6 arguments (from left to right) that are pointers or integers are passed in the registers RDI, RSI, RDX, RCX, R8, and R9 (in that order). The first 6 arguments (from left to right) that are floating point values are passed in the registers XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, and XMM7. Additionally, the number of XMM registers used is passed in RAX. Printing a ‘float’ can for example be done with the following code.

.data
        num: .float 3.14            # define our number
        format: .string "num: %f\n" # define a format string, '%f' means insert a double precision floating point value
.text
.globl main                         # the entry point is 'main' when using the C library
main:
        mov %rsp, %rbp              # create a pointer to the base of this stack frame
        and $-16, %rsp              # make sure the stack is 16-byte aligned
        movss num, %xmm0            # 'move scalar single precision float' from our number to the first 32 bits of the first SSE register, all other bits are zeroed
        cvtps2pd %xmm0, %xmm0       # 'convert packed single precision float to packed double precision float', now we have a double precision
        mov $format, %rdi           # set rdi to be a pointer to the format string
        mov $1, %rax                # let printf know that we used 1 SSE register
        call printf                 # printf(const char *format, ...), see also x86-64 calling convensions
        mov %rbp, %rsp              # restore stack
        mov $0, %rax                # set exit code
        ret                         # return control to the C library

(It can be compiled with for example gcc test.s -o test)