前面的章节对汇编的各种指令和用法都做了介绍,从本章开始具体介绍下如何直接在C及C++的高级语言里使用汇编代码,也就是通常所说的inline assembly(内联汇编)的方式...
/* cfunctest.c – An example of functions in C */ #include <stdio.h> float circumf(int a) { return 2 * a * 3.14159; } float area(int a) { return a * a * 3.14159; } int main() { int x = 10; printf("Radius: %d\n", x); printf("Circumference: %f\n", circumf(x)); printf("Area: %f\n",area(x)); return 0; } |
$ gcc -S cfunctest.c |
.file "cfunctest.c" .text .globl circumf .type circumf, @function circumf: pushl %ebp movl %esp, %ebp subl $8, %esp movl 8(%ebp), %eax addl %eax, %eax movl %eax, -8(%ebp) fildl -8(%ebp) fldl .LC0 fmulp %st, %st(1) fstps -4(%ebp) flds -4(%ebp) leave ret .size circumf, .-circumf .globl area .type area, @function area: pushl %ebp movl %esp, %ebp subl $8, %esp movl 8(%ebp), %eax imull 8(%ebp), %eax movl %eax, -8(%ebp) fildl -8(%ebp) fldl .LC0 fmulp %st, %st(1) fstps -4(%ebp) flds -4(%ebp) leave ret .size area, .-area .section .rodata .LC2: .string "Radius: %d\n" .LC3: .string "Circumference: %f\n" .LC4: .string "Area: %f\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $10, 28(%esp) movl $.LC2, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call printf movl 28(%esp), %eax movl %eax, (%esp) call circumf movl $.LC3, %eax fstpl 4(%esp) movl %eax, (%esp) call printf movl 28(%esp), %eax movl %eax, (%esp) call area movl $.LC4, %eax fstpl 4(%esp) movl %eax, (%esp) call printf movl $0, %eax leave ret .size main, .-main .section .rodata .align 8 .LC0: .long -266631570 .long 1074340345 .ident "GCC: (Ubuntu/Linaro 4.5.3-12ubuntu2) 4.5.3" .section .note.GNU-stack,"",@progbits |
asm( "assembly code"); |
asm ("movl $1, %eax\n\tmovl $0, %ebx\n\tint $0x80"); |
asm ( "movl $1, %eax\n\t" "movl $0, %ebx\n\t" "int $0x80"); |
/* asmtest.c – An example of using an asm section in a program*/ #include <stdio.h> int main() { int a = 10; int b = 20; int result; result = a * b; asm ( "nop"); printf("The result is %d\n", result); return 0; } |
$ gcc -S asmtest.c $ cat asmtest.s .file "asmtest.c" .section .rodata .LC0: .string "The result is %d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $10, 28(%esp) movl $20, 24(%esp) movl 28(%esp), %eax imull 24(%esp), %eax movl %eax, 20(%esp) #APP # 11 "asmtest.c" 1 nop # 0 "" 2 #NO_APP movl $.LC0, %eax movl 20(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call printf movl $0, %eax leave ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.5.3-12ubuntu2) 4.5.3" .section .note.GNU-stack,"",@progbits $ |
/* globaltest.c - An example of using C variables */ #include <stdio.h> int a = 10; int b = 20; int result; int main() { asm ( "pusha\n\t" "movl a, %eax\n\t" "movl b, %ebx\n\t" "imull %ebx, %eax\n\t" "movl %eax, result\n\t" "popa"); printf("the answer is %d\n", result); return 0; } |
$ gcc -S globaltest.c $ cat globaltest.s .file "globaltest.c" .globl a .data .align 4 .type a, @object .size a, 4 a: .long 10 .globl b .align 4 .type b, @object .size b, 4 b: .long 20 .comm result,4,4 .section .rodata .LC0: .string "the answer is %d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $16, %esp #APP # 11 "globaltest.c" 1 pusha movl a, %eax movl b, %ebx imull %ebx, %eax movl %eax, result popa # 0 "" 2 #NO_APP movl result, %edx movl $.LC0, %eax movl %edx, 4(%esp) movl %eax, (%esp) call printf movl $0, %eax leave ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.5.3-12ubuntu2) 4.5.3" .section .note.GNU-stack,"",@progbits $ |
asm volatile ("assembly code"); |
__asm__ ( "pusha\n\t" "movl a, %eax\n\t" "movl b, %ebx\n\t" "imull %ebx, %eax\n\t" "movl %eax, result\n\t" "popa"); |
__asm__ __volatile__ ( "pusha\n\t" "movl a, %eax\n\t" "movl b, %ebx\n\t" "imull %ebx, %eax\n\t" "movl %eax, result\n\t" "popa"); |