_nosay 发表于 2016-03-30 14:28

trampoline.S代码疑问?

本帖最后由 _nosay 于 2016-03-30 16:29 编辑

.code16

ENTRY(trampoline_data)
r_base = .

        mov        %cs, %ax        # Code and data in the same place
        mov        %ax, %ds

        mov        $1, %bx                # Flag an SMP trampoline
        cli                        # We should be safe anyway

        movl        $0xA5A5A5A5, trampoline_data - r_base“r_base = .”,这行代码是什么意思?
“movl $0xA5A5A5A5, trampoline_data - r_base”,0xA5A5A5A5是存到什么位置去了?


写了一个测试程序:
就是在三个函数里,都写一行“r_base = .”,并把r_base值打印出来。#include <stdio.h>

int fun1(int n)
{
      long base;

      //printf("0x%x\n", (&n)[-1]);

__asm__(
      "r_base = .\n\t"
      "movl r_base, %0\n\t"
      :"=a"((long)base)
      :"a"(0)
      :
      );

      printf("0x%x\n", (unsigned int)base);

      return 0;
}

int fun2(int n)
{
      long base;

      //printf("0x%x\n", (&n)[-1]);

__asm__(
      "r_base = .\n\t"
      "movl r_base, %0\n\t"
      :"=a"((long)base)
      :"a"(0)
      :
      );

      printf("0x%x\n", (unsigned int)base);

      return 0;
}

int fun3(int n)
{
      long base;

      //printf("0x%x\n", (&n)[-1]);

__asm__(
      "r_base = .\n\t"
      "movl r_base, %0\n\t"
      :"=a"((long)base)
      :"a"(0)
      :
      );

      printf("0x%x\n", (unsigned int)base);

      return 0;
}

int main()
{
      fun1(0);
      fun2(0);
      fun3(0);

      return 0;
}打印结果:
$ ./a.out
0x4841ba1
0x48448a1
0x48475a1

fun2()比fun1()多了0x2d00,fun3()比fun2()多了0x2d00,请问为什么有这样的规律,r_base到底是什么?

_nosay 发表于 2016-03-30 16:25

总感觉0x4800000挺特别的。

执行:
objdump -S a.out | grep 0x48
readelf -a ./a.out | grep 0x48

什么都没看到 {:qq35:}。

linux2.4.0:arch/i386/kernel/trampoline.S有一段这样的注释:
/ *        On entry to trampoline_data, the processor is in real mode
*        with 16-bit addressing and 16-bit data.CS has some value
*        and IP is zero.Thus, data addresses need to be absolute
*        (no relocation) and are taken with regard to r_base.
*/

但我还是不知道r_base值具体是什么东西 {:qq35:}。

_nosay 发表于 2016-03-30 16:50

本帖最后由 _nosay 于 2016-03-30 17:38 编辑

int fun1(int n)
{
      long base, here;

      //printf("0x%x\n", (&n)[-1]);

__asm__(
      "r_base = .\n\t"
      "r_here:movl r_base, %0\n\t"
      "movl r_here, %1\n\t"
      :"=a"((long)base), "=b"((long)here)
      :"a"(0), "b"(0)
      :
      );

      printf("0x%x, 0x%x\n", (unsigned int)base, (unsigned int)here);

      return 0;
}base值与here值打印结果一样,看来是紧接着的代码实际加载到内存的位置,那为什么fun1()、fun2()、fun3()相隔的那么远,而且还很有规律?
=在汇编里面用于定义变量,“r_base = .”与“r_base:”等效,可以说明汇编里面的标号也是变量吗?

nswcfd 发表于 2016-03-31 10:28

.是汇编过程中的概念,可以理解为当前code section的相对偏移。
这些符号相当于自动加入了一些label:,是编译过程中的常量。$ cat test.c
void f()
{
        asm("tmp1=.; mov tmp1, %rax");
        asm("tmp2=.; mov tmp2, %rbx");
        asm("tmp3=.; mov tmp3, %rcx; tmp3=.; mov tmp3, %rdx;");
}
$ make test.o
cc    -c -o test.o test.c
$ nm test.o
0000000000000000 T f
0000000000000004 t tmp1
000000000000000c t tmp2
000000000000001c t tmp3
$ objdump -d test.o

test.o:   file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <f>:
   0:        55                           push   %rbp
   1:        48 89 e5                     mov    %rsp,%rbp

0000000000000004 <tmp1>:
   4:        48 8b 04 25 00 00 00         mov    0x0,%rax
   b:        00

000000000000000c <tmp2>:
   c:        48 8b 1c 25 00 00 00         mov    0x0,%rbx
13:        00
14:        48 8b 0c 25 00 00 00         mov    0x0,%rcx
1b:        00

000000000000001c <tmp3>:
1c:        48 8b 14 25 00 00 00         mov    0x0,%rdx
23:        00
24:        c9                           leaveq
25:        c3                           retq

nswcfd 发表于 2016-03-31 10:30

本帖最后由 nswcfd 于 2016-03-31 15:03 编辑

0x48...是link之后的结果(即把相对偏移转换为绝对地址) 《==========【更新】这个解释是错误的,是指令本身。

nswcfd 发表于 2016-03-31 10:48

包含ld结果的例子。$ cat test.c
void f1()
{
asm("tmp1=.; mov tmp1, %rax");
asm("tmp2=.; mov tmp2, %rbx");
asm("tmp3=.; mov tmp3, %rcx; tmp3=.; mov tmp3, %rdx;");
}
void f2()
{
asm("myentry=.; nop; nop; mybase=.; movl $0xabcd, myentry-mybase");
}
int main()
{
}
$ make test.o test
cc    -c -o test.o test.c
cc   test.o   -o test
$ objdump -d test.o
0000000000000000 <f1>:
   0: 55                  push   %rbp
   1: 48 89 e5            mov    %rsp,%rbp
0000000000000004 <tmp1>:
   4: 48 8b 04 25 00 00 00mov    0x0,%rax
   b: 00
000000000000000c <tmp2>:
   c: 48 8b 1c 25 00 00 00mov    0x0,%rbx
13: 00
14: 48 8b 0c 25 00 00 00mov    0x0,%rcx
1b: 00
000000000000001c <tmp3>:
1c: 48 8b 14 25 00 00 00mov    0x0,%rdx
23: 00
24: c9                  leaveq
25: c3                  retq   

0000000000000026 <f2>:
26: 55                  push   %rbp
27: 48 89 e5            mov    %rsp,%rbp
000000000000002a <myentry>:
2a: 90                  nop   
2b: 90                  nop   
000000000000002c <mybase>:
2c: c7 04 25 fe ff ff ffmovl   $0xabcd,0xfffffffffffffffe
33: cd ab 00 00
37: c9                  leaveq
38: c3                  retq   
0000000000000039 <main>:
39: 55                  push   %rbp
3a: 48 89 e5            mov    %rsp,%rbp
3d: c9                  leaveq
3e: c3                  retq   
$ objdump -d test
0000000000400448 <f1>:
400448: 55                  push   %rbp
400449: 48 89 e5            mov    %rsp,%rbp
000000000040044c <tmp1>:
40044c: 48 8b 04 25 4c 04 40mov    0x40044c,%rax
400453: 00
0000000000400454 <tmp2>:
400454: 48 8b 1c 25 54 04 40mov    0x400454,%rbx
40045b: 00
40045c: 48 8b 0c 25 5c 04 40mov    0x40045c,%rcx
400463: 00
0000000000400464 <tmp3>:
400464: 48 8b 14 25 64 04 40mov    0x400464,%rdx
40046b: 00
40046c: c9                  leaveq
40046d: c3                  retq   

000000000040046e <f2>:
40046e: 55                  push   %rbp
40046f: 48 89 e5            mov    %rsp,%rbp
0000000000400472 <myentry>:
400472: 90                  nop   
400473: 90                  nop   
0000000000400474 <mybase>:
400474: c7 04 25 fe ff ff ffmovl   $0xabcd,0xfffffffffffffffe
40047b: cd ab 00 00
40047f: c9                  leaveq
400480: c3                  retq   

_nosay 发表于 2016-03-31 13:35

回复 6# nswcfd

我是直接编译成可执行文件的,所以已经链接过了,但是,fun1的地址是0x8048410,fun1()中的r_base值打印出来是0x48423a1。

fun1()代码(原始):int fun1(int n)
{
      long base, here;

      //printf("0x%x\n", (&n)[-1]);

__asm__(
      "r_base = .\n\t"
      "r_here:movl r_base, %0\n\t"
      "movl r_here, %1\n\t"
      :"=a"((long)base), "=b"((long)here)
      :"a"(0), "b"(0)
      :
      );

      printf("0x%x, 0x%x\n", (unsigned int)base, (unsigned int)here);

      return 0;
}fun1()代码(objdump -d):08048410 <fun1>:
8048410:       55                      push   %ebp
8048411:       89 e5                   mov    %esp,%ebp
8048413:       53                      push   %ebx
8048414:       83 ec 24                sub    $0x24,%esp
8048417:       b8 00 00 00 00          mov    $0x0,%eax
804841c:       ba 00 00 00 00          mov    $0x0,%edx
8048421:       89 d3                   mov    %edx,%ebx

08048423 <r_here>:
8048423:       a1 23 84 04 08          mov    0x8048423,%eax
8048428:       8b 1d 23 84 04 08       mov    0x8048423,%ebx
804842e:       89 da                   mov    %ebx,%edx
8048430:       89 45 f0                mov    %eax,-0x10(%ebp)
8048433:       89 55 f4                mov    %edx,-0xc(%ebp)
8048436:       8b 55 f4                mov    -0xc(%ebp),%edx
8048439:       8b 45 f0                mov    -0x10(%ebp),%eax
804843c:       89 54 24 08             mov    %edx,0x8(%esp)
8048440:       89 44 24 04             mov    %eax,0x4(%esp)
8048444:       c7 04 24 88 85 04 08    movl   $0x8048588,(%esp)
804844b:       e8 a0 fe ff ff          call   80482f0 <printf@plt>
8048450:       b8 00 00 00 00          mov    $0x0,%eax
8048455:       83 c4 24                add    $0x24,%esp
8048458:       5b                      pop    %ebx
8048459:       5d                      pop    %ebp
804845a:       c3                      ret可执行程序打印:
0x48423a1, 0x48423a1// fun1()中打印的r_base、r_here值
0x48466a1
0x48493a1

_nosay 发表于 2016-03-31 13:48

本帖最后由 _nosay 于 2016-03-31 13:48 编辑

回复 6# nswcfd

不过。。

上面的第11、12行:8048423:       a1 23 84 04 08          mov    0x8048423,%eax
8048428:       8b 1d 23 84 04 08       mov    0x8048423,%ebx对应的c代码是:      "r_here:movl r_base, %0\n\t"
      "movl r_here, %1\n\t"证明了你说的是对的,r_base值正是当前这条指令的绝对地址0x8048423,为什么printf()打印出来的变成0x48423a1了?难道“movl r_base, %0”是将0x8048423处的内容放到base变量了吗?

_nosay 发表于 2016-03-31 13:57

回复 6# nswcfd

没加$,{:qq23:} {:qq23:} 。      "r_here:movl $r_base, %0\n\t"
      "movl $r_here, %1\n\t" $ ./a.out
0x8048423, 0x8048423
0x48465a1
0x48492a1

好,一切悬疑都解开了 {:qq13:} 。。

nswcfd 发表于 2016-03-31 14:59

是的,对一个label:而言,$label代表的label的地址,label代表的是label执行的内容,也就是代码段里的指令。
页: [1] 2 3
查看完整版本: trampoline.S代码疑问?