Skip to the content.

gcc 内联汇编

我感觉可以按照 makefile 的教程然后重写一下这个东西

https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html

分析一下

loongson-community/musl

static inline long __syscall0(long n)
{
  register long a0 __asm__("$a0");
  register long a7 __asm__("$a7") = n;

  __asm__ __volatile__ (
    "syscall 0"
    : "+&r"(a0)
    : "r"(a7)
    : SYSCALL_CLOBBERLIST);
  return a0;
}

glibc:

internal_syscall0(number, err, dummy...){
  long int _sys_result;
  {
  register long int __a7 asm ("$a7") = number;
  register long int __a0 asm ("$a0");
  __asm__ volatile (
  "syscall  0\n\t"
  : "=r" (__a0)
  : "r" (__a7)
  : __SYSCALL_CLOBBERS);
  _sys_result = __a0;
  }
  _sys_result;
}

asm clobber

#include <assert.h>  // assert
#include <fcntl.h>   // open
#include <limits.h>  // INT_MAX
#include <math.h>    // sqrt
#include <stdbool.h> // bool false true
#include <stdio.h>
#include <stdlib.h> // malloc sort
#include <string.h> // strcmp ..
#include <unistd.h> // sleep

#define __SYSCALL_CLOBBERS                                                     \
  "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"

long hello(long arg0, long arg1, long arg2, long arg3,
                                  long arg4, long arg5, long arg6,
                                  long number) {
  return 77;
}

long __syscall0(long number) {
  long int _sys_result;

  {
    register long int __a7 asm("$a7") = number;
    register long int __a0 asm("$a0");
    __asm__ volatile("bl hello" "\n\t"
                     : "=r"(__a0)
                     : "r"(__a7)
                     : __SYSCALL_CLOBBERS);
    _sys_result = __a0;
  }
  asm(
    "move $ra, $zero \n\t"
  );
  return _sys_result;
}

int main(int argc, char *argv[]) {
  printf("%ld\n", __syscall0(12));
  return 0;
}

找个经典例子

musl/arch/x86_64/atomic_arch.h

static inline int a_cas(volatile int *p, int t, int s)
{
  __asm__ __volatile__ (
    "lock ; cmpxchg %3, %1"
    : "=a"(t), "=m"(*p) : "a"(t), "r"(s) : "memory" );
  return t;
}

Asm label

/* Declare sqrt for use within GLIBC.  Compilers typically inline sqrt as a
   single instruction.  Use an asm to avoid use of PLTs if it doesn't.  */
float (sqrtf) (float) asm ("__ieee754_sqrtf");
double (sqrt) (double) asm ("__ieee754_sqrt");

Tutorial about assembly

inline assembly

eg 1

__asm__ __volatile__ ("" ::: "memory") https://stackoverflow.com/questions/14950614/working-of-asm-volatile-memory

eg2

#include<stdio.h>

int main(){
  int answer;
  int operand = 0x100;
  asm ("shrl $8, %0" : "=r" (answer) : "r" (operand) : "cc");
  /* asm ("shrl $8, %0" : "=m" (answer) : "m" (operand) : "cc"); */
  printf("%x", answer);
  return 0;
}

why change to =m m failed ?

TODO

https://stackoverflow.com/questions/27594297/how-to-print-a-string-to-the-terminal-in-x86-64-assembly-nasm-without-syscall

examples

https://stackoverflow.com/questions/10461798/asm-code-containing-0-what-does-that-mean

int a=10, b;
asm ("movl %1, %%eax;
      movl %%eax, %0;"
     :"=r"(b)        /* output */
     :"r"(a)         /* input */
     :"%eax"         /* clobbered register */
     );

clobbered register

Official Documentation

https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html#Using-Assembly-Language-with-C

This is main framework, merge anything here!

Basic asm

Basic-Asm

too basic ?

extended asm

Extended-Asm

6.47.2.5 Input Operands

constraints

Awesome

example

来源: https://zhuanlan.zhihu.com/p/41872203

inline void xchg(volatile int *x, volatile int *y) {
  asm volatile("xchgl %0, %1"
               : "+r"(x), "+m"(y)::"memory", "cc"); // swap(x, tmp)
}

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。