19
Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see http://www.codeproject.com/Articles/15971/Using-Inline-As sembly-in-C- C

Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Embed Size (px)

Citation preview

Page 1: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

1

Machine-Level Programming X:inline Assembly

Comp 21000: Introduction to Computer Systems & Assembly Lang

On-Line resources*

* See see http://www.codeproject.com/Articles/15971/Using-Inline-Assembly-in-C-C

Page 2: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

2

Today Inline assembly

Example

Page 3: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

3

Why use assembly? Assembly can express very low-level things:

you can access machine-dependent registers and I/O you can control the exact code behavior in critical sections that might otherwise

involve deadlock between multiple software threads or hardware devices you can break the conventions of your usual compiler, which might allow some

optimizations (like temporarily breaking rules about memory allocation, threading, calling conventions, etc)

you can build interfaces between code fragments using incompatible conventions (e.g. produced by different compilers, or separated by a low-level interface)

you can get access to unusual programming modes of your processor (e.g. 16 bit mode to interface startup, firmware, or legacy code on Intel PCs)

you can produce reasonably fast code for tight loops to cope with a bad non-optimizing compiler (but then, there are free optimizing compilers available!)

you can produce hand-optimized code perfectly tuned for your particular hardware setup, though not to someone else's

you can write some code for your new language's optimizing compiler (that is something what very few ones will ever do, and even they not often)

i.e. you can be in complete control of your codeFrom the linux assembly howto

Page 4: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

4

Why use assembly? Speed

Be careful! Optimizing compilers are almost always better! useful when you know an assembly language instruction that can

replace a library call Example: transcendental function computation

has macros for some inline assembly sequences Example: if spend most of the time in a loop computing the

sine and cosine of the same angles, could use the fsincos assembly function

We’ll see an example later

Page 5: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

5

inline assembly code*

Example: mov instruction

/* put this line in your C program*/asm("assembly code");

/* alternative syntax */__asm__ ("assembly code");

asm("movl %ebx, %eax"); /* moves the contents of ebx register to eax */

__asm__("movb %ch, (%ebx)"); /* moves the byte from ch to the memory pointed by ebx */

* see http://www.codeproject.com/Articles/15971/Using-Inline-Assembly-in-C-C

Page 6: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

6

inline assembly More sophisticated assembly

For more than one assembly instruction, use semicolon at the end of each instruction of inserted code

see example on next slide

Page 7: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

7

Example#include <stdio.h>

int main() { /* Add 10 and 20 and store result into register %eax */ __asm__ ( "movl $10, %eax;" "movl $20, %ebx;" "addl %ebx, %eax;" );

/* Subtract 20 from 10 and store result into register %eax */ __asm__ ( "movl $10, %eax;" "movl $20, %ebx;" "subl %ebx, %eax;" );

/* Multiply 10 and 20 and store result into register %eax */ __asm__ ( "movl $10, %eax;" "movl $20, %ebx;" "imull %ebx, %eax;" ); return 0 ;}

compile with –m32 –O1 flagstrace in gdb to see registers change.

Page 8: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

8

Extended inline assembly Idea

In extended assembly, we can also specify the operands can specify the input registers, output registers and a list of

clobbered registers.

If there are no output operands but there are input operands, we must place two consecutive colons surrounding the place where the output operands would go.

Can omit list of clobbered registers to use, GCC and GCC’s optimization scheme will take care of the reg.

asm ( "assembly code" : output operands /* optional */ : input operands /* optional */ : list of clobbered registers /* optional */);

Page 9: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

9

Example 1

The variable "val" is kept in a register val is a C variable that must be declared earlier in the C program

the value in register %eax is copied onto that register, and the value of "val" is updated into the memory from

that register. note that eax is preceded by 2 percent signs

differentiate from a asm parameter (asm works like printf)

asm ("movl %%eax, %0;" : "=r" ( val ));

Assm instr Output operands

see ~barr/Student/Comp210/Resources/inline directory for all examples

Page 10: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

10

Example 1 (continued)

the %0 indicates the first operand of asm, it is associated with the first parameter, i.e., val (similar to printf)

“=r” indicates a register constraint see chart on next page for all possible register specifications “r” indicates that gcc may keep the variable in any available

General Purpose Registers the “=“ indicates write only mode.

asm ("movl %%eax, %0;" : "=r" ( val ));

see ~barr/Student/Comp210/Resources/inline directory for all examples

Page 11: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

11

register specifiersr register

R General register (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP)

q General register for data (EAX, EBX, ECX, EDX)

f Floating point reg

a %eax, %ax, %al

b %ebx, %bx, %bl

c %ecx, %cx, %cl

d %edx, %dx, %dl

S %esi, %si

D %edi, %di

Page 12: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

12

Example 2

Two variables are declared in the C code, no and val %0 is the first operand to asm and thus refers to the C

variable val (the output variable) %1 is the second operand and thus refers to the C variable

no (the input variable) “=r” and “r” say that gcc can use any registers to store the

corresponding variable (either val or no ) the clobbered variable is %ebx so gcc should not use that

variable anywhere else.

int no = 100, val ; asm ("movl %1, %%ebx;" "movl %%ebx, %0;" : "=r" ( val ) /* output */ : "r" ( no ) /* input */ : "%ebx" /* clobbered register */ );

Page 13: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

13

Example 3

The C code declares three variables: arg1, arg2, add The input variables will use %eax (for arg1) and %ebx (for arg2)

the output variable is add and will use register %eax no clobber register is set; gcc can determine

int arg1, arg2, add ;arg1 = 10;arg2 = 25;__asm__ ( "addl %%ebx, %%eax;" : "=a" (add) : "a" (arg1), "b" (arg2) );

Page 14: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

14

Example 4#include <stdio.h>

int main() { int arg1, arg2, add, sub, mul, quo, rem ;

printf( "Enter two integer numbers : " ); scanf( "%d%d", &arg1, &arg2 );

/* Perform Addition, Subtraction, Multiplication & Division */ __asm__ ( "addl %%ebx, %%eax;" : "=a" (add) : "a" (arg1) , "b" (arg2) ); __asm__ ( "subl %%ebx, %%eax;" : "=a" (sub) : "a" (arg1) , "b" (arg2) ); __asm__ ( "imull %%ebx, %%eax;" : "=a" (mul) : "a" (arg1) , "b" (arg2) );

__asm__ ( "movl $0x0, %%edx;" "movl %2, %%eax;" "movl %3, %%ebx;" "idivl %%ebx;" : "=a" (quo), "=d" (rem) : "g" (arg1), "g" (arg2) );

printf( "%d + %d = %d\n", arg1, arg2, add ); printf( "%d - %d = %d\n", arg1, arg2, sub ); printf( "%d * %d = %d\n", arg1, arg2, mul ); printf( "%d / %d = %d\n", arg1, arg2, quo ); printf( "%d %% %d = %d\n", arg1, arg2, rem ); return 0 ;}

Example 4

idivl S # Signed divide

R[%edx] R[%edx]:R[%eax] mod S;R[%eax] R[%edx]:R[%eax] / S

Page 15: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

15

Example 4#include <stdio.h> #include <stdlib.h>

int main (int argc, char* argv[]) {

long max = atoi (argv[1]); long number; long i; unsigned position; volatile unsigned result; /* Repeat the operation for a large number of values. */ for (number = 1; number <= max; ++number) { /* Repeatedly shift the number to the right, until the result is zero. Keep count of the number of shifts this requires. */ for (i = (number >> 1), position = 0; i != 0; ++position)

i >>= 1; /* The position of the most significant set bit is the number of shifts we needed after the first one. */ result = position; } // end outer for loop

return 0;

} // end main

Example 5why use inline assembly?no assembly in this code

% gcc -O2 -o bit-pos-loop bit-pos-loop.c

% time ./bit-pos-loop 250000000

19.51user 0.00 system 0:20.40 elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k0inputs+0outputs (73major+11minor)pagefaults 0swaps

Page 16: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

16

Example 4#include <stdio.h> #include <stdlib.h>

int main (int argc, char* argv[]) {

long max = atoi (argv[1]); long number; unsigned position; volatile unsigned result;

/* Repeat the operation for a large number of values. */ for (number = 1; number <= max; ++number) { /* Compute the position of the most significant set bit using the bsrl assembly instruction. */ asm (“bsrl %1, %0” : “=r” (position) : “r” (number));

result = position; } // end for loop

return 0;

}

Example 5why use inline assembly?assembly used for inner loop

%gcc -O2 -o bit-pos-asm bit-pos-asm.c

% time ./bit-pos-asm 250000000

3.19user 0.00system 0:03.32elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k0inputs+0outputs (73major+11minor)pagefaults 0swaps

Compare to the 19.51user of the previous C only example!

Bsr: Scans source operand for first bit set. Sets ZF if a bit is found set and loads the destination with an index to first set bit. Clears ZF is no bits are found set. BSF scans forward across bit pattern (0-n) while BSR scans in reverse (n-0).

Page 17: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

17

Volitile If our assembly statement must execute where we put it,

(e.g. must not be moved out of a loop as an optimization), put the keyword "volatile" or "__volatile__" after "asm" or "__asm__" and before the ()s.

asm volatile ( "...;” "...;" : ... );

__asm__ __volatile__ ( "...;" "...;" : ... );

Page 18: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

18

Example 4#include <stdio.h>

int gcd( int a, int b ) { int result ; /* Compute Greatest Common Divisor using Euclid's Algorithm */ __asm__ __volatile__ ( "movl %1, %%eax;" "movl %2, %%ebx;" "CONTD: cmpl $0, %%ebx;" "je DONE;" "xorl %%edx, %%edx;" "idivl %%ebx;" "movl %%ebx, %%eax;" "movl %%edx, %%ebx;" "jmp CONTD;" "DONE: movl %%eax, %0;" : "=g" (result) : "g" (a), "g" (b) ); return result ;}int main() { int first, second ; printf( "Enter two integers : " ) ; scanf( "%d%d", &first, &second ); printf( "GCD of %d & %d is %d\n", first, second, gcd(first, second) ) ; return 0 ;}

Example 5.5Compute GCD with Euclid’s Algmgcd.c

Note that we can put labels and jump to them!

Note that we can put several asm instructions in one __asm__ function call

Page 19: Ithaca College 1 Machine-Level Programming X: inline Assembly Comp 21000: Introduction to Computer Systems & Assembly Lang On-Line resources* * See see

Ithaca College

19

#include <stdio.h>

int main(){ int x, y, rslt, rtnval; int i; printf("Enter two integers\n"); rslt = scanf("%d%d", &x, &y);

/* change into assembly code */ rtnval = 0; for(i = 0; i < y; i++) { rtnval += x; } /* end change */

printf("%d * %d = %d\n", x, y, rtnval);

return 0;}

Example 6convert the for loop to assembly code(should be no more than 11 lines of assembly code)